mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-24 10:13:11 +02:00
Merge preserved Grok cleanup failure outcomes
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/instruction-provider-stop-boundary: fix(grok): retain provider results across collection and restore failures
This commit is contained in:
commit
e822ce4d71
2 files changed
+56
-3
No files matched your search
@@ -868,12 +868,48 @@ describe("grok_local execute", () => {
|
||||
});
|
||||
const ctx = await makeCtx("run-collection-reject", await makeTempRoot());
|
||||
ctx.onProviderStopped = async () => { order.push("collect"); throw collectionError; };
|
||||
await expect(execute(ctx)).rejects.toBe(collectionError);
|
||||
const result = await execute(ctx);
|
||||
expect(result.errorCode).toBe("instruction_collection_failed");
|
||||
expect(result.resultJson?.instructionCollectionFailure).toBe("collection_failed");
|
||||
expect(result.resultJson?.workspaceRestoreFailure).toBeUndefined();
|
||||
expect(order).toEqual(["collect", "restore"]);
|
||||
expect(stagedDir).not.toBe("");
|
||||
expect(await pathExists(stagedDir)).toBe(false);
|
||||
});
|
||||
|
||||
it.each([0, 2])("preserves provider output when collection and restore both fail after exit %s", async (exitCode) => {
|
||||
delete process.env.XAI_API_KEY;
|
||||
mocks.state.isRemote = true;
|
||||
await seedHostGrokAuth("{}");
|
||||
runProcessMock.mockImplementation(async (_run, _target, _command, _args, options) => {
|
||||
options.onProcessStopped();
|
||||
return {
|
||||
...makeSuccessfulRunResult(), exitCode,
|
||||
stderr: exitCode ? "Model request failed." : "",
|
||||
stdout: [JSON.stringify({ type: "text", data: "Saved output." }), JSON.stringify({
|
||||
type: "end", sessionId: "sess-1", requestId: "req-1", stopReason: "EndTurn",
|
||||
usage: { input_tokens: 4, output_tokens: 9 },
|
||||
})].join("\n"),
|
||||
};
|
||||
});
|
||||
prepareRuntimeMock.mockImplementationOnce(async () => ({
|
||||
workspaceRemoteDir: "/remote/workspace",
|
||||
assetDirs: { home: "/remote/workspace/.paperclip-runtime/grok/home" },
|
||||
restoreWorkspace: async () => { throw new Error("restore failed"); },
|
||||
}));
|
||||
const ctx = await makeCtx("run-collection-and-restore-reject", await makeTempRoot());
|
||||
ctx.onProviderStopped = async () => { throw new Error("instruction collection failed"); };
|
||||
const result = await execute(ctx);
|
||||
expect(result).toMatchObject({
|
||||
errorCode: "workspace_restore_failed", exitCode, sessionId: "sess-1", summary: "Saved output.",
|
||||
usage: { inputTokens: 4, outputTokens: 9 },
|
||||
resultJson: { instructionCollectionFailure: "collection_failed", workspaceRestoreFailure: "restore_failed",
|
||||
requestId: "req-1", finalResponseRecorded: true, executionBeforeRestore: { exitCode } },
|
||||
});
|
||||
expect(result.errorMessage).toContain("Instruction collection failed");
|
||||
if (exitCode) expect(result.errorMessage).toContain("Model request failed.");
|
||||
});
|
||||
|
||||
it.each(["completed", "failed", "timed_out"])("preserves %s output and removes the staged home when restore fails", async (state) => {
|
||||
delete process.env.XAI_API_KEY;
|
||||
mocks.state.isRemote = true;
|
||||
|
||||
@@ -730,11 +730,28 @@ async function executeTurn(ctx: AdapterExecutionContext): Promise<AdapterExecuti
|
||||
try {
|
||||
return await withWorkspaceRestore(
|
||||
async () => {
|
||||
let result: AdapterExecutionResult;
|
||||
let collectionFailed = false;
|
||||
const collectionFailureMessage = "Instruction collection failed after provider stop. No instruction save is claimed.";
|
||||
try {
|
||||
return await executeTurn();
|
||||
result = await executeTurn();
|
||||
} finally {
|
||||
await providerStop.collectBeforeRestore();
|
||||
try {
|
||||
await providerStop.collectBeforeRestore();
|
||||
} catch {
|
||||
collectionFailed = true;
|
||||
await onLog("stderr", `[paperclip] ${collectionFailureMessage}\n`).catch(() => undefined);
|
||||
}
|
||||
}
|
||||
if (!collectionFailed) return result;
|
||||
const providerFailed = result.timedOut || result.signal || result.errorCode
|
||||
|| (result.exitCode !== null && result.exitCode !== 0);
|
||||
return {
|
||||
...result,
|
||||
...(!providerFailed ? { errorCode: "instruction_collection_failed" } : {}),
|
||||
errorMessage: [result.errorMessage, collectionFailureMessage].filter(Boolean).join(" "),
|
||||
resultJson: { ...result.resultJson, instructionCollectionFailure: "collection_failed" },
|
||||
};
|
||||
},
|
||||
async () => { await restoreRemoteWorkspace?.(); },
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user