Skip to content

web: carry the tool line's result as colour, and hear a call start before it reports - #175

Open
adityak74 wants to merge 1 commit into
mainfrom
feat/web-tool-line-status-colour
Open

web: carry the tool line's result as colour, and hear a call start before it reports#175
adityak74 wants to merge 1 commit into
mainfrom
feat/web-tool-line-status-colour

Conversation

@adityak74

Copy link
Copy Markdown
Contributor

What

The browser's tool line no longer writes its status word (exited 0, timed out, created a.md (3 lines)) beside the phrase. The result is the bullet's colour, from exactly one of three classes on the .activity-line: activity-ok, activity-fail, activity-running. The word stays reachable: it is the line's title, and for a shell call it also sits under the verbatim command in the closed details. The verify line keeps its word and takes the same classes.

The in-progress state is real. Renderer::tool_starting(name, description) is a new trait method with an empty default, so the CLI and every test renderer are untouched. Agent::run_tool calls it after approval has let a call through and immediately before Registry::dispatch, so a denied call never draws as running and no line pulses under an open approval card. WebRenderer sends it as a tool_started frame carrying the same name and phrase the tool frame will carry; the browser appends a running line on the first and settles it in place on the second, matching on the name. A replayed session has every result, so no replayed line is in progress. A turn that ends with a line still pending fails it, with the title saying the turn ended before the call reported.

The status mapping

stateForStatus in web/src/activity-line.ts is the one mapping. exited 0 and passed are ok. A non-zero exit, timed out, cancelled, failed, error, denied, unknown tool, a withheld result, a patch of which nothing applied, and the subagent tool's stopped states are failures. Everything else, including an empty status, is ok. The brief said unknown non-empty words should be failures, but the non-shell tools summarise a success in their own words (a.txt (12 lines), 'q' (4 matches), started PID 512), so that rule would paint a working session red. The failure vocabulary is the smaller and more stable list, and it is the split the agent loop already uses for its own succeeded. See the 2026-09-05 entry in docs/DECISIONS.md.

Tests

  • agent.rs: tool_starting arrives before tool_described for the same call, and is not sent for a call approval denied.
  • zorp-web/src/renderer.rs: the tool_started frame serialises with type: "tool_started", the phrase key present only when the model gave one.
  • web/test/activity-line.test.ts: the status mapping over the tools' real vocabulary, status absent from the line's text and present in its title and details, exactly one state class per line, a pending line settled in place by the matching result, an abandoned line failed with the reason, and the CSS for the bullet colours and the reduced-motion pulse.

Checks

cargo fmt --all, cargo build --workspace, cargo test --workspace, cargo test -p zorp-agent --features research (803 passed), cargo test -p zorp-web --features research (255 passed), cargo clippy --workspace --all-targets --locked -- -D warnings; from web/: npm run check, npm test (366 passed), npm run build.

Docs

New docs/DECISIONS.md entry dated 2026-09-05. The tool-line bullet in CLAUDE.md and AGENTS.md amended identically.

https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp

…it reports

The browser's tool line no longer writes its status word beside the phrase. The result is the bullet's colour, from exactly one of activity-ok, activity-fail or activity-running on the line, with the word kept in the line's title and, for a shell call, under the verbatim command in the details. stateForStatus in web/src/activity-line.ts is the one mapping: exit 0 and passed are ok, the tools' failure vocabulary is fail, and the other tools' own success summaries stay ok, the same split the agent loop uses for succeeded. The verify line keeps its word and takes the same classes.

Renderer::tool_starting is a new trait method with an empty default, called from Agent::run_tool after approval and before dispatch, so a denied call never draws as running. WebRenderer sends it as a tool_started frame with the name and phrase the tool frame will carry; the browser appends a running line on the first and settles it in place on the second. A replayed session has every result, so no replayed line is in progress, and a turn that ends with a line pending fails it with the reason in its title.

Claude-Session: https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant