Skip to content
Merged
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
5 changes: 3 additions & 2 deletions phoenix-builder-mcp/mcp-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ const AI_TEST_SUITES = {
"unsaved-buffers": "suite-unsaved-buffers.md",
"self-sufficiency": "suite-self-sufficiency.md",
"bug-fixing": "suite-bug-fixing.md",
"questions": "suite-questions.md",
"plan-mode": "suite-plan-mode.md",
"permissions": "suite-permissions.md"
};
// The four model runs that have caught every regression seen so far, plus the
// free deterministic/piggyback checks. See model_tests.md, "Deterministic first".
const AI_TEST_QUICK = {
suites: ["editor-context", "unsaved-buffers", "self-sufficiency", "bug-fixing"],
tests: ["UB-1", "EC-5", "EC-2", "SS-4", "EC-1", "UB-2", "SS-1", "BF-1"]
suites: ["editor-context", "unsaved-buffers", "self-sufficiency", "bug-fixing", "questions"],
tests: ["UB-1", "EC-5", "EC-2", "SS-4", "QF-6", "EC-1", "UB-2", "SS-1", "BF-1", "QF-1"]
};

function _gitInfo(cwd) {
Expand Down
19 changes: 18 additions & 1 deletion src-node/claude-code-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,9 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale,
// SDK tool_use id (e.g. "toolu_01...") → our sequential toolCounter so a
// tool_result block can be mapped back to its indicator on the browser.
const _toolUseIdToCounter = {};
// tool_use id → SDK tool name, so a tool_result can be interpreted in the
// light of which tool produced it (see the AskUserQuestion note below).
const _toolUseIdToName = {};
// Set true once the user clicks "Allow & Switch to Edit Mode" on a
// plan-mode write confirmation. Subsequent Edit/Write attempts in the same
// turn skip the prompt and use the cached "allow" decision so a multi-edit
Expand Down Expand Up @@ -2396,6 +2399,7 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale,
toolCounter++;
if (block.id) {
_toolUseIdToCounter[block.id] = toolCounter;
_toolUseIdToName[block.id] = block.name;
}
_log("Subagent tool:", block.name, "#" + toolCounter,
"parent=#" + (parentToolId !== undefined ? parentToolId : "?"));
Expand Down Expand Up @@ -2598,6 +2602,7 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale,
// correlate later tool_result blocks back to the indicator.
if (event.content_block.id) {
_toolUseIdToCounter[event.content_block.id] = activeToolCounter;
_toolUseIdToName[event.content_block.id] = activeToolName;
}
_log("Tool start:", activeToolName, "#" + activeToolCounter);
nodeConnector.triggerPeer("aiProgress", {
Expand Down Expand Up @@ -2713,10 +2718,22 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale,
// on the corresponding tool indicator (errored vs ran).
const counterId = _toolUseIdToCounter[block.tool_use_id];
if (counterId !== undefined) {
// A question is answered by DENYING the tool call and
// handing the user's answer back as the denial reason
// (see the AskUserQuestion PreToolUse hook). The CLI
// reports every deny as an error result, so without
// this the panel painted a red "failed" badge on a
// question the user had just answered normally — and
// counted every question as a tool error in metrics.
// The deny is our transport, not a failure; an
// unanswered question means the user cancelled or
// stopped the turn, which is not a failure either.
const resultToolName = _toolUseIdToName[block.tool_use_id];
const isAnsweredByDeny = resultToolName === "AskUserQuestion";
nodeConnector.triggerPeer("aiToolResult", {
requestId: requestId,
toolId: counterId,
isError: !!block.is_error,
isError: !!block.is_error && !isAnsweredByDeny,
preview: preview
});
}
Expand Down
Loading