Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions desktop/src/features/agents/lib/friendlyAgentLastError.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import test from "node:test";
import {
friendlyAgentLastError,
friendlyTurnErrorCopy,
CLI_ACP_INTERNAL_ERROR_COPY,
ACP_INTERNAL_ERROR_COPY,
MODEL_NOT_FOUND_COPY,
RELAY_MESH_DENIED_COPY,
} from "./friendlyAgentLastError.ts";
Expand Down Expand Up @@ -215,17 +215,18 @@ test("friendlyTurnErrorCopy: garbage string code coerces to NaN → string path"
);
});

// --- -32603 internal error (Fix #2: CLI-ACP unsupported model hint) ---
// --- -32603 internal error ---

test("code -32603 bare 'Internal error' → cli-acp internal error hint (severity: generic)", () => {
test("code -32603 bare 'Internal error' → harness-neutral internal error hint (severity: generic)", () => {
const result = friendlyAgentLastError("Internal error", -32603);
assert.deepEqual(result, {
severity: "generic",
copy: CLI_ACP_INTERNAL_ERROR_COPY,
copy: ACP_INTERNAL_ERROR_COPY,
});
assert.doesNotMatch(result.copy, /codex/i);
});

test("code -32603 bare Internal error (wrapped) → cli-acp internal error hint", () => {
test("code -32603 bare Internal error (wrapped) → harness-neutral internal error hint", () => {
// The ACP wrapper form "Agent reported error (code -32603): Internal error"
// is treated as bare — the remainder after stripping the prefix is
// "Internal error", which maps to the hint.
Expand All @@ -235,13 +236,13 @@ test("code -32603 bare Internal error (wrapped) → cli-acp internal error hint"
);
assert.deepEqual(result, {
severity: "generic",
copy: CLI_ACP_INTERNAL_ERROR_COPY,
copy: ACP_INTERNAL_ERROR_COPY,
});
});

test("code -32603 with specific message → original message preserved, NOT hint", () => {
// If the adapter provides detail beyond "Internal error", preserve it —
// don't bury actionable information with a broad codex-specific hint.
// don't bury actionable information with a generic hint.
const result = friendlyAgentLastError(
"Internal error: model gpt-5.6-sol rejected by adapter",
-32603,
Expand All @@ -259,7 +260,7 @@ test("embedded code -32603 recovered from message when code param is null", () =
);
assert.deepEqual(result, {
severity: "generic",
copy: CLI_ACP_INTERNAL_ERROR_COPY,
copy: ACP_INTERNAL_ERROR_COPY,
});
});

Expand Down Expand Up @@ -299,10 +300,10 @@ test("friendlyTurnErrorCopy: -32603 structured param + wrapped specific detail
);
});

test("friendlyTurnErrorCopy: code -32603 bare Internal error → cli-acp internal error hint", () => {
test("friendlyTurnErrorCopy: code -32603 bare Internal error → harness-neutral internal error hint", () => {
assert.equal(
friendlyTurnErrorCopy("Internal error", -32603),
CLI_ACP_INTERNAL_ERROR_COPY,
ACP_INTERNAL_ERROR_COPY,
);
});

Expand Down
12 changes: 6 additions & 6 deletions desktop/src/features/agents/lib/friendlyAgentLastError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export const RELAY_MESH_DENIED_COPY =
export const MODEL_NOT_FOUND_COPY =
"The configured model is not available — open agent settings and select a different one from the dropdown.";

export const CLI_ACP_INTERNAL_ERROR_COPY =
"The agent's harness reported an internal error. For Codex agents this can mean the configured model isn't supported by your installed codex-acp — check the model in `~/.codex/config.toml` or upgrade the adapter (`brew upgrade codex-acp`).";
export const ACP_INTERNAL_ERROR_COPY =
"The agent's harness reported an internal error. Check the agent's runtime log for details.";

const EMBEDDED_CODE_RE = /^Agent reported error \(code (-?\d+)\): /;
/** Bare form of the standard JSON-RPC -32603 message (after stripping the ACP wrapper prefix). */
Expand Down Expand Up @@ -83,18 +83,18 @@ export function friendlyAgentLastError(
return { severity: "denied", copy: MODEL_NOT_FOUND_COPY };
case -32603: {
// Standard JSON-RPC "Internal error" — emitted by external harnesses
// (e.g. codex-acp) when the configured model is unsupported. Only
// substitute the hint when the message is the bare "Internal error"
// without identifying the underlying cause. Only substitute the
// harness-neutral hint when the message is the bare "Internal error"
// form; if the adapter included specific detail, preserve it so we
// don't bury actionable information with a broad codex-specific hint.
// don't bury actionable information with a generic hint.
//
// "Bare" means the remainder after stripping the ACP wrapper prefix
// (if present) is exactly "Internal error". This covers both the raw
// form ("Internal error") and the ACP-wrapped form
// ("Agent reported error (code -32603): Internal error").
const remainder = embedded?.remainder ?? trimmed;
if (remainder === BARE_INTERNAL_ERROR) {
return { severity: "generic", copy: CLI_ACP_INTERNAL_ERROR_COPY };
return { severity: "generic", copy: ACP_INTERNAL_ERROR_COPY };
}
return { severity: "generic", copy: remainder };
}
Expand Down