mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 02:26:12 +02:00
Honor negated attachment requests in task completion (#17399)
This commit is contained in:
1 parent
72a5fecb58
commit
a978ecadef
3 files changed
+24
-4
No files matched your search
@@ -6,6 +6,9 @@ describe("explicit file output requirements", () => {
|
||||
"Prepare a requested file",
|
||||
"Make a Markdown file named checklist.md with three items.",
|
||||
"Export the results as a CSV.",
|
||||
"Do not modify repository files, but create an attachment.",
|
||||
"Do not create attachments; export the results as CSV.",
|
||||
"Do not create attachments and instead export a CSV.",
|
||||
"Give me a downloadable report.",
|
||||
"Please create out/answer.pdf and attach it.",
|
||||
"Do not use external services. Create a file with the results.",
|
||||
@@ -37,6 +40,13 @@ describe("explicit file output requirements", () => {
|
||||
"Read the file and explain what it does.",
|
||||
"Review the PDF and answer in the chat.",
|
||||
"Do not create a file; answer inline.",
|
||||
"Run hostname, id, and pwd on your assigned computer. Report their output in a short completion comment, followed by CONTROL_PLANE_CHECK_OK. Do not modify repository files or create attachments. Mark the task done when finished.",
|
||||
"Do not modify repository files or create attachments.",
|
||||
"Do not edit files and do not create attachments.",
|
||||
"Do not create files; instead, don't create attachments either.",
|
||||
"Do not create files and attach them.",
|
||||
"Don’t edit files or create attachments.",
|
||||
"Never edit files nor create attachments.",
|
||||
"Don't attach a file. Reply with three bullets.",
|
||||
"Fix a crash in parser.ts.",
|
||||
"Read the file and write a short explanation inline.",
|
||||
|
||||
@@ -87,7 +87,12 @@ export function explicitlyRequestsFileOutput(objective: string): boolean {
|
||||
const creates = [...clause.matchAll(/\b(?:create|make|write|save|export|attach|send|generate|produce|prepare|provide|give|return|build)\b/giu)];
|
||||
return creates.flatMap((create, createIndex) => {
|
||||
const before = clause.slice(0, create.index);
|
||||
if (/\b(?:do not|don't|never|no need to)\s*$/iu.test(before)) return [];
|
||||
if (/\b(?:do not|don['’]t|never|no need to)\s*$/iu.test(before)) return [];
|
||||
const negation = /\b(?:do not|don['’]t|never|no need to)\b/iu.exec(before);
|
||||
if (negation) {
|
||||
const rest = before.slice(negation.index + negation[0].length);
|
||||
if (!/\binstead\b/iu.test(rest) && /^(?:\s*|[\s\S]*\b(?:and|or|nor)\s*)$/iu.test(rest)) return [];
|
||||
}
|
||||
// Bind each object to its own verb. A denied write or "create no files"
|
||||
// cannot suppress a separate requested report in this same clause.
|
||||
const output = clause.slice(create.index + create[0].length, creates[createIndex + 1]?.index);
|
||||
|
||||
@@ -325,9 +325,14 @@ describe("native runner file handoff", () => {
|
||||
await db.update(issueWorkProducts).set({ status: "failed" }).where(eq(issueWorkProducts.id, product.id));
|
||||
await expect(nativeCompletionFeedback(db, runId, doneReport([`work_product:${product.id}`])))
|
||||
.rejects.toThrow("requested file has no accessible delivery evidence");
|
||||
await db.update(heartbeatRuns).set({ contextSnapshot: { issueId, executionContinuation: { objective: "Do not create a file. Explain the result inline." } } }).where(eq(heartbeatRuns.id, runId));
|
||||
await expect(nativeCompletionFeedback(db, runId, doneReport([])))
|
||||
.resolves.toContain("Completion report accepted");
|
||||
for (const objective of [
|
||||
"Do not create a file. Explain the result inline.",
|
||||
"Run hostname, id, and pwd. Report the output in a completion comment. Do not modify repository files or create attachments.",
|
||||
]) {
|
||||
await db.update(heartbeatRuns).set({ contextSnapshot: { issueId, executionContinuation: { objective } } }).where(eq(heartbeatRuns.id, runId));
|
||||
await expect(nativeCompletionFeedback(db, runId, doneReport([])))
|
||||
.resolves.toContain("Completion report accepted");
|
||||
}
|
||||
} finally {
|
||||
await db.delete(issueWorkProducts).where(eq(issueWorkProducts.id, product.id));
|
||||
await db.update(heartbeatRuns).set({ contextSnapshot: { issueId } }).where(eq(heartbeatRuns.id, runId));
|
||||
|
||||
Reference in new issue
Block a user