341
const isError = block.is_error === true;
342
const content: ToolResultContent[] = extractToolResultContent(block.content) ?? [];
344
>
if (fileEdit) {
345
content.push(fileEdit);
346
}
347
const info = state.toolCalls.lookup(block.tool_use_id)?.info;
349
>
.filter((c): c is { type: ToolResultContentType.Text; text: string } => c.type === ToolResultContentType.Text)
350
>
.map(c => c.text)
351
>
.join('\n');
352
>
const pastTenseMessage: StringOrMarkdown = info
353
? getClaudePastTenseMessage(info.toolName, info.displayName, info.parsedInput, !isError, resultText)
354
: `${getClaudeToolDisplayName(tracked.toolName)} finished`;
356
>
// is the deny `message` we returned from `canUseTool`; classify it so the
357
>
// telemetry reports `userCancelled` rather than a generic error.
358
>
const denialCode = isError ? claudeToolDenialCode(resultText) : undefined;
359
>
signals.push({
360
>
kind: 'action',
361
>
resource: chat,
362
>
action: {
363
>
type: ActionType.ChatToolCallComplete,
364
>
turnId: tracked.turnId,
365
>
toolCallId: block.tool_use_id,
366
>
result: {
367
>
success: !isError,
368
>
pastTenseMessage,
369
>
content: content.length > 0 ? content : undefined,
370
>
...(denialCode ? { error: { message: resultText, code: denialCode } } : {}),
371
>
},
372
>
},
373
>
});
374
>
state.completeToolCall(block.tool_use_id);
375
>
// Phase 12 — foreground subagent completion. A tool_result for a
376
>
// known spawning Task/Agent tool_use fires `subagent_completed`
377
>
// UNLESS the spawning entry has been flagged background, in which
378
>
// case completion is deferred to a later `task_notification`.
379
>
const spawn = registry.getSpawn(block.tool_use_id);
380
>
if (spawn && !spawn.background && spawn.markCompleted()) {
381
signals.push({
382
kind: 'subagent_completed',