mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-12 21:02:17 +02:00
fix(x): surface coding tool errors
This commit is contained in:
parent
36c0cca3f9
commit
4a2fe30153
11 changed files with 138 additions and 18 deletions
|
|
@ -79,7 +79,7 @@ After \`code_agent_run\` returns:
|
|||
- Pass through the agent's \`summary\` as-is. Do not rewrite it.
|
||||
- Refer to file paths as plain text. Do NOT use \`\`\`file:path\`\`\` reference blocks. (This overrides the global "always wrap paths in filepath blocks" rule — for code-mode output, plain text.)
|
||||
- Only add your own explanation if it failed:
|
||||
- \`success: false\` with a message — surface the message. If it mentions the agent isn't installed or signed in, tell the user to install or sign in via **Settings → Code Mode**.
|
||||
- A tool error with a message — surface the message. If it mentions the agent isn't installed or signed in, tell the user to install or sign in via **Settings → Code Mode**.
|
||||
- \`stopReason: "cancelled"\` — the run was stopped; acknowledge briefly and ask if they want to continue.
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import container from "../../di/container.js";
|
||||
import { InMemoryAbortRegistry } from "../../runs/abort-registry.js";
|
||||
import { BuiltinTools } from "./builtin-tools.js";
|
||||
import type { ToolContext } from "./exec-tool.js";
|
||||
|
||||
function context(signal: AbortSignal): ToolContext {
|
||||
return {
|
||||
runId: "turn-1",
|
||||
toolCallId: "tool-1",
|
||||
signal,
|
||||
abortRegistry: new InMemoryAbortRegistry(),
|
||||
publish: async () => {},
|
||||
codePolicy: "ask",
|
||||
};
|
||||
}
|
||||
|
||||
function mockCodeServices(runPrompt: () => Promise<never>): void {
|
||||
vi.spyOn(container, "resolve").mockImplementation(((name: string) => {
|
||||
if (name === "codeModeManager") return { runPrompt };
|
||||
if (name === "codePermissionRegistry") {
|
||||
return { cancelRun: vi.fn(), request: vi.fn() };
|
||||
}
|
||||
throw new Error(`Unexpected dependency: ${name}`);
|
||||
}) as typeof container.resolve);
|
||||
}
|
||||
|
||||
describe("code_agent_run", () => {
|
||||
afterEach(() => vi.restoreAllMocks());
|
||||
|
||||
it("throws genuine coding-agent failures for the runtime to mark as errors", async () => {
|
||||
mockCodeServices(async () => {
|
||||
throw new Error("spawn Electron ENOENT");
|
||||
});
|
||||
|
||||
await expect(BuiltinTools.code_agent_run.execute(
|
||||
{ agent: "codex", cwd: "/repo", prompt: "Fix it" },
|
||||
context(new AbortController().signal),
|
||||
)).rejects.toThrow("Coding agent failed: spawn Electron ENOENT");
|
||||
});
|
||||
|
||||
it("returns an ordinary cancellation result when the turn was aborted", async () => {
|
||||
const controller = new AbortController();
|
||||
controller.abort();
|
||||
mockCodeServices(async () => {
|
||||
throw new Error("cancelled");
|
||||
});
|
||||
|
||||
await expect(BuiltinTools.code_agent_run.execute(
|
||||
{ agent: "codex", cwd: "/repo", prompt: "Fix it" },
|
||||
context(controller.signal),
|
||||
)).resolves.toMatchObject({ success: false, stopReason: "cancelled" });
|
||||
});
|
||||
});
|
||||
|
|
@ -868,7 +868,7 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
}),
|
||||
execute: async ({ agent, cwd, prompt }: { agent: 'claude' | 'codex', cwd: string, prompt: string }, ctx?: ToolContext) => {
|
||||
if (!ctx) {
|
||||
return { success: false, message: 'code_agent_run requires run context (runId / streaming).' };
|
||||
throw new Error('code_agent_run requires run context (runId / streaming).');
|
||||
}
|
||||
// The composer chip is the source of truth for the agent. The model's `agent`
|
||||
// argument is only a fallback for the ask-human flow (code mode not active, no
|
||||
|
|
@ -955,10 +955,7 @@ export const BuiltinTools: z.infer<typeof BuiltinToolsSchema> = {
|
|||
changedFiles: [...changedFiles],
|
||||
};
|
||||
}
|
||||
return {
|
||||
success: false,
|
||||
message: `Coding agent failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
};
|
||||
throw new Error(`Coding agent failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
} finally {
|
||||
ctx.signal.removeEventListener('abort', onAbort);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue