kimi-code/packages/agent-core/test/tools
Kai f3269eacb9
fix(tui): show real terminal status for background agents (#197)
* fix(tui): show real terminal status for background agents

The Agent tool's run_in_background=true call returns a non-error
ToolResult whose body just says "status: running". The transcript
card derived its done/failed badge from that result, so every
terminated background agent — including ones reconcile reclassifies
as lost on resume — kept the green "✓ Completed" label even when
the actual task failed, was killed, or never came back.

Push the real BackgroundTaskInfo.status into the matching Agent
card so the badge reflects what happened. The card's resolver
prefers subagent agentId (live) and falls back to the description
on resume; on resume the apply step also runs after replay
finishes so the agent group can reach the borrowed components.

Also adds an agent-core regression test that pins live, busy,
group, race, and resume scenarios for the bg notification chain.

* fix(tui): also propagate bg agent terminal status to standalone cards

Standalone Agent cards (only one Agent tool call in a step, never
upgraded into an AgentGroupComponent) bypassed the previous
`setBackgroundTaskTerminalStatus` path: the standalone header reads
`getDerivedSubagentPhase`, which still derived `done` from the
non-error spawn-success ToolResult, and the method did not request
a header/content rebuild. Lost/failed/killed bg agents in this
shape still rendered as `✓ Completed`.

Thread the override through `getDerivedSubagentPhase`, populate
`subagentError` with the friendly failure message so both render
paths share one source of truth, and trigger the same header +
content rebuild that `onSubagentFailed` does. Also include the
override in `hasSubagentState` / the subagent-block early-return
so a replayed solo bg agent (no replayed subagent block, no
sub-tool activity) switches to the subagent-aware layout instead
of the generic `Used Agent` rendering.

Adds two standalone-render regression tests so the path no longer
relies on the grouped snapshot to stay correct.

* feat(agent-core): make resume actionable from the lost-task notification

A backgrounded subagent that ends as `lost`/`failed`/`killed` is
already a soft-recoverable thing — `subagentHost.resume` will
reanimate the persisted Agent instance — but the LLM had to dig
through the original spawn-success ToolResult to find the right id
and figure out the recovery shape on its own. The two look-alike
identifiers (the BackgroundManager `task_id` aka `source_id`, and
the `subagentHost` `agent_id`) regularly got confused in practice.

Surface what the model needs at the moment of decision:

  - Add `agent_id` as a top-level `<notification>` attribute for
    agent-* tasks, so the right id is structural, not buried in
    prose. Render path keeps backward-compat by omitting the
    attribute when no agent_id is known (bash tasks, old sessions).
  - On non-success agent terminal states, append a recovery
    paragraph to the body: the precise `Agent(resume=...)` call,
    the disambiguation between `agent_id` and `source_id`, the
    `run_in_background` option, and what state survives the
    restart vs. what may need to be redone.
  - Tighten the spawn-time `resume_hint` with the same
    disambiguation and an explicit pointer at the
    `task.lost`/`task.failed`/`task.killed` recovery trigger.
  - Persist `agent_id` and `subagent_type` in PersistedTask so the
    recovery body still works after a session restart, where
    in-memory `BackgroundTaskInfo.agentId` would otherwise be
    undefined. Optional fields keep the disk schema
    forward/backward compatible — pre-PR records load without
    them and silently fall back to the original short body.

* fix(tui): route bg-agent terminal events by stable agent_id, not description

`tc.subagentAgentId` is left undefined for every backgrounded agent.
`handleSubagentSpawned` early-returns for `runInBackground` before
calling `tc.onSubagentSpawned`, and the wire replay path drops the
`subagent` block entirely (`toolCallFromReplayMessage` returns only
id/name/args). So the `agentId` branch in
`applyBackgroundTaskTerminalStatus` never matched in practice, every
call fell through to the description-based fallback, and the
persisted `agent_id` we added in the previous commit was effectively
dead. That fallback also has a real failure mode: if a foreground
Agent and a backgrounded Agent share the same `args.description`,
the only candidate found is the live (unrelated) card, which gets
incorrectly relabeled as the lost task's terminal state.

Parse `agent_id: agent-N` out of the AgentTool spawn-success
ToolResult body inside `getSubagentAgentId` so the id is always
recoverable, regardless of whether the in-memory subagent metadata
was ever populated. Foreground and backgrounded Agent cards now
carry distinct ids and route correctly.

Also pipe the real `subagent.failed` error through to the parent
card. The background branch of `handleSubagentFailed` previously
only appended the dedicated transcript entry; the parent Agent
card was left with the generic "Background agent failed" written
by the later `background.task.terminated` event. Add an optional
`errorText` to `setBackgroundTaskTerminalStatus` /
`applyBackgroundTaskTerminalStatus` and pass `event.error` through
on the failed branch — the real reason now reaches both the card
and the entry.

* fix(tui): treat agent_id as authoritative when matching bg terminal events

Previously `applyBackgroundTaskTerminalStatus` always tried agent_id
first and then fell back to description match on miss. That fallback
caused two cross-card bugs:

  1. On resume, `applyTerminalBackgroundAgentStatuses` iterates every
     persisted terminal task, including ones whose tool calls fell
     outside the `REPLAY_TURN_LIMIT` window and were never mounted.
     Description fallback could route an old `lost` status onto an
     unrelated recent Agent card sharing the same `args.description`.

  2. During the live spawn → terminate window, the same card briefly
     lives in both `_pendingToolComponents` and `transcriptContainer`.
     A description-only walk visits the same component twice and flags
     itself ambiguous, dropping the otherwise unambiguous update.

When `args.agentId` is provided we now match only by id and skip on
miss. With `getSubagentAgentId` already parsing `agent_id: agent-N`
out of the spawn-success ToolResult, the id path is reliable for
both live and resume even though `tc.subagentAgentId` is never
populated for backgrounded agents. Description fallback is preserved
solely for old pre-PR sessions whose persisted records lack
`agent_id` — same best-effort behavior as before.
2026-05-29 17:26:27 +08:00
..
background refactor: unify path normalization with pathe (#84) 2026-05-27 11:53:24 +08:00
cron test(agent-core): use deterministic jitter id in cron pending-jitter test (#187) 2026-05-29 12:42:58 +08:00
fixtures refactor(kaos): move Environment into kaos, slim package API (#147) 2026-05-28 16:50:10 +08:00
planning refactor(agent-core): split RuntimeConfig into Kaos and ToolServices (#185) 2026-05-29 12:28:47 +08:00
policies feat: rework permission decision policies (#26) 2026-05-27 20:07:24 +08:00
providers Kimi For Coding 2026-05-22 15:54:50 +08:00
agent.test.ts fix(tui): show real terminal status for background agents (#197) 2026-05-29 17:26:27 +08:00
ask-user.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
bash-env.test.ts refactor(agent-core): split RuntimeConfig into Kaos and ToolServices (#185) 2026-05-29 12:28:47 +08:00
bash-windows-kill.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
bash.test.ts refactor(agent-core): split RuntimeConfig into Kaos and ToolServices (#185) 2026-05-29 12:28:47 +08:00
builtin-current.test.ts refactor(agent-core): split RuntimeConfig into Kaos and ToolServices (#185) 2026-05-29 12:28:47 +08:00
edit.test.ts fix(approval): show file content/diff and open full-screen preview on ctrl+e (#139) 2026-05-28 13:22:33 +08:00
enter-plan-mode.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
exit-plan-mode-options.test.ts feat: rework permission decision policies (#26) 2026-05-27 20:07:24 +08:00
exit-plan-mode.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
fetch-url.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
file-type.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
glob.test.ts refactor: unify path normalization with pathe (#84) 2026-05-27 11:53:24 +08:00
grep.test.ts refactor: unify path normalization with pathe (#84) 2026-05-27 11:53:24 +08:00
input-schema-io.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
list-directory.test.ts refactor: unify path normalization with pathe (#84) 2026-05-27 11:53:24 +08:00
path-guard.test.ts feat: rework permission decision policies (#26) 2026-05-27 20:07:24 +08:00
plan-mode-hard-block.test.ts refactor(agent-core): split RuntimeConfig into Kaos and ToolServices (#185) 2026-05-29 12:28:47 +08:00
read-file.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
read-media-desc.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
read-media.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
read.test.ts feat: rework permission decision policies (#26) 2026-05-27 20:07:24 +08:00
result-builder.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
rg-locator.test.ts refactor: unify path normalization with pathe (#84) 2026-05-27 11:53:24 +08:00
shell-cancel.test.ts refactor(agent-core): split RuntimeConfig into Kaos and ToolServices (#185) 2026-05-29 12:28:47 +08:00
shell-quoting.test.ts refactor(agent-core): split RuntimeConfig into Kaos and ToolServices (#185) 2026-05-29 12:28:47 +08:00
skill-tool-dispatch.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
skill-tool.test.ts feat: add plugin manager and official plugins (#119) 2026-05-27 22:47:33 +08:00
todo-list.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
web-search.test.ts Kimi For Coding 2026-05-22 15:54:50 +08:00
write.test.ts fix(approval): show file content/diff and open full-screen preview on ctrl+e (#139) 2026-05-28 13:22:33 +08:00