Live tool status, flat activity view, instant activation, real markdown typography - #147
Conversation
…markdown typography
Four UX fixes from dev-testing the operator, all applying to every chat surface:
- Live 'Using {tool}...' status: consume the backend's new tool_call SSE
event (name only, emitted right before each tool executes). Tool names
previously arrived only in the turn-end toolTrace, so the status line said
'Thinking...' through entire tool-using turns. New liveToolCalls list in
both stores, preferred by ChatActivity over the lagging trace.
- End-user resting view: the header now leads with '{N} tool calls - {dur}'
and expands to a flat list of the calls themselves. The old shape ('1 step
- 59.2s - 8 tool calls' over a langchain task row that had to be expanded
again) was three layers of pipeline plumbing around the only content that
mattered. Errors and cascades still break through; debug surface unchanged.
- Activation blocks on deterministic checks only: gate read-back plus the
gate-dry-run classification (fail-closed rollback as before). The LLM
probes - read canary and live write probe - run in the BACKGROUND via
runPostActivationProbes after the operator is already usable; they were the
bulk of a minute-long activation wait, and an inconclusive outcome proved
nothing anyway. The write probe still tears the operator down on a PROVEN
gate breach (write executed without pausing). enforceWriteCanaryGate split
into enforceGateDryRun (blocking) + runBackgroundWriteProbe (reporting).
Semantic change: unknown-on-old-backend now warns instead of rolling back.
- Markdown finally renders properly: the prose classes every chat surface
already wears were inert - @tailwindcss/typography was never installed, so
preflight-stripped headings/lists/tables stayed unstyled. Plugin added,
chat table styling (borders, padding, self-contained horizontal scroll),
bold-repair now moves illegal inner whitespace outside the delimiters
instead of swallowing it, and the operator prompt gains a strict-markdown
rule so the model stops emitting '**bold **' in the first place.
|
Warning Review limit reached
Next review available in: 93 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (33)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…deps npm ci on CI refused the previous lock: the typography install on Windows skipped @emnapi/* (platform-conditional transitive deps), leaving the lock out of sync with package.json on Linux runners.
npm 11 (local) omits lock entries for a bundled optional dep's own dependencies; npm 10 (CI, node 20) requires them and refused npm ci. Lock now written by npm@10 so both accept it.
There was a problem hiding this comment.
Pull request overview
Improves operator/chat UX with live tool status, simplified activity details, faster activation, and styled Markdown.
Changes:
- Handles live
tool_callSSE events across chat surfaces. - Moves LLM activation probes to the background.
- Adds Markdown typography, table styling, formatting repair, tests, and translations.
Reviewed changes
Copilot reviewed 33 out of 34 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/pages/operator.tsx |
Starts background probes and surfaces results. |
src/lib/operator/write-canary.ts |
Splits deterministic and background write checks. |
src/lib/operator/system-prompt.ts |
Adds strict Markdown guidance. |
src/lib/operator/__tests__/write-canary.test.ts |
Tests split probe behavior. |
src/lib/api/chat.ts |
Adds the tool_call SSE type. |
src/index.css |
Enables typography and table styling. |
src/i18n/locales/zh.json |
Updates Chinese activation text. |
src/i18n/locales/th.json |
Updates Thai activation text. |
src/i18n/locales/pt.json |
Updates Portuguese activation text. |
src/i18n/locales/ko.json |
Updates Korean activation text. |
src/i18n/locales/ja.json |
Updates Japanese activation text. |
src/i18n/locales/hi.json |
Updates Hindi activation text. |
src/i18n/locales/fr.json |
Updates French activation text. |
src/i18n/locales/es.json |
Updates Spanish activation text. |
src/i18n/locales/en.json |
Updates canonical activation text. |
src/i18n/locales/de.json |
Updates German activation text. |
src/i18n/locales/ar.json |
Updates Arabic activation text. |
src/hooks/use-operator.ts |
Runs post-activation probes asynchronously. |
src/hooks/use-operator-chat.ts |
Tracks operator live tool calls. |
src/hooks/use-debug-events.ts |
Stores current-turn tool names. |
src/hooks/use-chat.ts |
Processes live tool-call events. |
src/hooks/__tests__/use-operator-activation.test.tsx |
Tests non-blocking activation. |
src/components/operator/operator-drawer.tsx |
Passes live tool state to chat. |
src/components/operator/operator-chat.tsx |
Displays live operator activity. |
src/components/operator/operator-activation.tsx |
Revises activation progress and warnings. |
src/components/operator/__tests__/operator-activation.test.tsx |
Tests revised activation messaging. |
src/components/groups/group-utils.ts |
Repairs malformed bold spacing. |
src/components/groups/__tests__/format-markdown-text.test.ts |
Tests Markdown repairs. |
src/components/chat/chat-panel.tsx |
Shows live tool activity. |
src/components/chat/chat-drawer.tsx |
Shows live tool activity in the drawer. |
src/components/chat/chat-activity.tsx |
Adds flat tool details and live status. |
src/components/chat/__tests__/chat-activity.test.tsx |
Tests activity summaries and live calls. |
package.json |
Adds Tailwind Typography. |
package-lock.json |
Locks the new dependency graph. |
Suppressed comments (1)
src/lib/operator/write-canary.ts:490
- A
resetOperatorrejection does not prove the operator is still deployed. That function deletes the agent before clearing the config, so if onlyclearOperatorConfig()fails, this branch reportstornDown: falseand tells the admin to remove an agent that is already gone while leaving the real problem—a stale config pointer—unreported. Preserve teardown progress or verify agent/config state before constructing this report.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| try { | ||
| await resetOperator(config); |
| toast.error( | ||
| t("operator.toast.writeProbeFailed", "The approval gate did not hold — the operator was removed."), | ||
| ); |
…nest teardown toast Both Copilot findings on #147, both correct: - The write probe runs detached from activation, so a breach verdict can land after the operator was reconfigured (this page, another tab, another admin). resetOperator unconditionally cleared the shared platform.operator variable — run stale, that erased the REPLACEMENT operator's config. The teardown now clears shared state only when the stored config still names the probe's agent; a stale probe (or one that cannot READ the stored config — never clear shared state on a guess) removes only its own agent. - The teardown-failed path warned 'still deployed - remove it manually' in report.message while the toast said 'the operator was removed'. The toast can be the only visible result after navigation; it now carries the report's own disposition.
Four UX fixes from dev-testing the operator, applying to every chat surface (main chat, drawer, operator page + drawer):
Live "Using {tool}…" status
Consumes the backend's new
tool_callSSE event (EDDI#672, commit 9a5bfd874): the tool NAME is emitted right before each tool executes. Previously tool names arrived only in the turn-endtoolTrace, so the status line said "Thinking…" through entire tool-using turns. NewliveToolCallslist in both chat stores;ChatActivityprefers it over the lagging trace. Backends without the event fall back to the old trace scan.Flat end-user resting view
The resting header now leads with {N} tool calls · {duration} and expands to a flat list of the calls themselves (args + status + copyable detail). The old shape — "1 step · 59.2s · 8 tool calls" over a
langchaintask row that had to be expanded again — was three layers of pipeline plumbing around the only content that mattered. Failed steps and cascade traces still break through and auto-expand; the debug surface is unchanged.Activation blocks on deterministic checks only
Activation now ends at the gate read-back + gate-dry-run classification (both still fail-closed with rollback). The LLM probes — read canary and live write probe — run in the background via
runPostActivationProbesonce the operator is already usable; they were the bulk of a minute-long activation wait, and an inconclusive outcome proved nothing anyway. The write probe retains its power to tear the operator down on a proven gate breach (its write executed without pausing).enforceWriteCanaryGateis split intoenforceGateDryRun(blocking) andrunBackgroundWriteProbe(reporting, never throws). Deliberate semantic change: an inconclusive probe against an old backend (no gate-dry-run) now warns instead of rolling back a deployed operator.Markdown finally renders properly
The
proseclasses every chat surface already wears were inert —@tailwindcss/typographywas never installed, so preflight-stripped headings, lists and tables stayed unstyled and every long reply rendered as a crowded wall. Also:**bold **→**bold**) now moves illegal inner whitespace outside the delimiters instead of swallowing it (**Panel ** |stays a valid table cell)**bold **at the sourceTests
5212 passing (22 new/reworked: live tool_call rendering, flat resting list, dry-run/background-probe split, activation-without-probes, i18n parity across 11 locales).
🤖 Generated with Claude Code