Skip to content

feat(webui): redesign tool-call rendering with inline diffs, group summaries, and cheap-model purpose titles#103748

Merged
steipete merged 1 commit into
mainfrom
claude/tool-calls-webui-redesign-04de3c
Jul 10, 2026
Merged

feat(webui): redesign tool-call rendering with inline diffs, group summaries, and cheap-model purpose titles#103748
steipete merged 1 commit into
mainfrom
claude/tool-calls-webui-redesign-04de3c

Conversation

@steipete

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #103554.

Tool calls in the Control UI chat were opaque: groups collapsed to "Activity: N tools", expanded calls dumped raw "Tool input"/"Tool output" JSON, file edits had no diff view, and shell commands had no terminal presentation. Two pairing bugs made it worse: transcript results whose call id lives on the message (not the block) rendered as a second bare "Tool" row, and parallel calls (call, call, result, result) never paired because coalescing was adjacent-only.

Why This Change Was Made

Requested redesign toward coding-agent-style activity rendering: scannable verb-first rows, inline diffs, and cheap-model purpose titles so long sessions read like a work log instead of a JSON dump.

User Impact

  • Kind-aware rows: $ command with display-only syntax highlighting (harness sh -lc '…' wrappers stripped), Edited protocol.md +2 -1 with colored diffstat, Read file.ts, Wrote new-file.ts +14, Searched pattern, plus a failed badge on errors.
  • Inline diffs: edits render the edit tool's persisted details.diff (real file line numbers) as add/remove tinted rows; foreign-harness edits (old_string/new_string, Codex apply_patch) fall back to a locally computed bounded line diff; writes show an all-added preview. Raw output stays behind the existing "Raw details" toggle.
  • Group summaries: consecutive calls collapse into a bordered card labeled e.g. "Ran 13 commands, read 6 files, edited 9 files, created a file · 1 failed"; while a run is live the newest running call names the group and running rows pulse.
  • AI purpose titles: complex calls (long commands, argument-heavy plugin/MCP tools) get short titles like "Ran linked list tests" through the new batched chat.toolTitles RPC. Model selection is cheap-only: per-agent/default utilityModel when configured, else openai/gpt-5.6-luna — and the Luna default applies only when the agent's primary model already routes to OpenAI, so tool arguments never reach a provider the session was not already using. Titles never fall through to the expensive primary model. Titles cache in the per-agent SQLite cache_entries (scope tool-call-titles), so reopening sessions never re-bills. If no cheap model is usable the RPC returns nothing and rows keep deterministic labels.
  • Pairing fixes: result blocks now inherit the call id/name/details at merge time, and results pair with any open call in the current tool run (bounded window), so parallel calls render as single rows.
  • Generic tools with simple object args render key–value rows instead of a JSON block; reads/searches no longer repeat their args as JSON.

New protocol surface is additive: chat.toolTitles (params/result schemas + validator), registered with operator.write scope because cache misses spend utility-model tokens.

Before / After

Before After (light) After (dark)
before after light after dark

Collapsed before: before collapsed

Live gateway session (real run, gpt-5.5, real chat.toolTitles round-trip producing "Ran linked list tests"):

live collapsed
live expanded
live running

Evidence

  • Unit/DOM tests: 281 tests across 8 affected files green on Blacksmith Testbox (new: tool-call-diff.test.ts, tool-call-view.test.ts, tool-call-grouping.test.ts, tool-titles.test.ts, src/gateway/chat-tool-titles.test.ts; updated: chat-tool-cards.test.ts, chat-message.test.ts, chat-thread.test.ts incl. new interleaved-pair and user-boundary regressions). Testbox run: https://github.com/openclaw/openclaw/actions/runs/29077207952
  • Targeted e2e ui/src/e2e/chat-tool-turn-outcome.e2e.test.ts green with a strengthened semantic assertion (error row keeps error class after a later turn recovers).
  • pnpm check:changed green on Testbox (exit=0: conflict/changelog/dependency guards, typecheck core, typecheck core tests, lint core). The last few review-fix commits after that run are covered by local focused tests + scoped oxlint; PR CI reruns the full gates.
  • Structured second-model review (Codex gpt-5.5, branch mode vs origin/main) ran through 11 rounds; every accepted finding was fixed (NUL-byte source file, unbounded patch parsing, Luna egress gating to OpenAI-primary agents, split-pane session/agent/client capture for title batches, stale view cache on late diff details, lit-guard repaint for arriving titles, live-vs-historical running state, streaming-output completion, arg auditability on expand). Final run: "autoreview clean: no accepted/actionable findings". One finding was consciously rejected: per-run provider provenance for titles on sessions whose primary later switched to OpenAI — the full transcript flows to the new provider on the next turn anyway, so a decorative-title-only gate would not change real egress.
  • Live proof: isolated dev gateway (OPENCLAW_STATE_DIR copy, port 19789) ran a real multi-tool coding task twice; screenshots above show unwrapped commands, merged parallel reads, group summaries, and a real Luna-generated title ("Ran linked list tests") arriving via chat.toolTitles and rendering on the command row.
  • Docs updated: docs/gateway/protocol.md (chat.toolTitles), docs/web/control-ui.md (tool rendering + titles).

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui gateway Gateway runtime size: XL maintainer Maintainer-authored PR labels Jul 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c9fa76403

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// allowed only when the agent already sends its turns to OpenAI. Tool args
// must not reach a new provider just for decorative titles.
const useUtility = hasConfiguredUtilityModel(params.cfg, params.agentId);
if (!useUtility && !agentPrimaryUsesOpenAI(params.cfg, params.agentId)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Gate Luna titles on the session model

When a chat session has a per-session model override away from OpenAI, this egress check still consults only the agent's configured primary model. The existing chat paths resolve the effective session provider from the loaded session entry via resolveSessionModelRef before sending a turn, but chat.toolTitles never loads that entry; with an OpenAI-default agent and an Anthropic-overridden session, cache misses still send tool names/inputs to openai/gpt-5.6-luna for decorative titles even though that session is not using OpenAI and no utilityModel was explicitly configured.

Useful? React with 👍 / 👎.

// Args already represented in the collapsed row / header detail for kinds that
// summarize their primary target; everything else stays auditable on expand.
const ROW_SUMMARIZED_ARG_KEYS: Partial<Record<ToolCallView["kind"], ReadonlySet<string>>> = {
read: new Set(["path", "file_path", "filePath", "notebook_path", "offset", "limit"]),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep read slice arguments visible

For read tools that include offset or limit, these keys are treated as already summarized, but the collapsed/read row only renders the file target and directory. Because extraArgsBeyondRowTarget drops all keys in this set, expanding a sliced read hides whether the agent read the full file or only a window, which removes important audit context for partial read_file/notebook reads.

Useful? React with 👍 / 👎.

@steipete steipete self-assigned this Jul 10, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. labels Jul 10, 2026
@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed July 10, 2026, 11:53 AM ET / 15:53 UTC.

Summary
This PR redesigns Control UI tool-call rendering, fixes interleaved call/result pairing, and adds cached model-generated purpose titles through a new gateway RPC.

PR surface: Source +2259, Tests +966, Docs +2. Total +3227 across 35 files.

Reproducibility: yes. An OpenAI-default agent with a non-OpenAI session override follows the provider-mismatch path, and a large edits array repeatedly invokes bounded quadratic LCS work before concatenating every section.

Review metrics: 2 noteworthy metrics.

  • Gateway API surface: 1 additive write-scoped RPC. Cache misses spend model tokens and transmit tool-call inputs, so provider selection and authorization matter before merge.
  • Persistent cache surface: 1 new per-agent cache scope. Generated title text persists beyond the current browser view and therefore needs an explicit ownership and privacy contract.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/chat-tool-titles.test.ts, serialized state: ui/src/lib/chat/tool-call-view.ts, serialized state: ui/src/pages/chat/tool-titles.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #103554
Summary: This PR is the linked candidate fix for the canonical Control UI tool-rendering issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Gate implicit Luna on the loaded session's effective model and add a non-OpenAI session-override regression test.
  • Bound aggregate multi-edit LCS work and rendered rows with a large-payload regression test.

Risk before merge

  • [P1] Merging as written can send transcript-derived tool names and arguments to OpenAI when the active session is explicitly overridden to another provider.
  • [P1] A valid transcript containing many large multi-edit replacements can amplify individually bounded diffs into excessive browser CPU, memory, and DOM work, potentially stalling the chat view.
  • [P1] The permanent policy for explicitly configured utility models crossing the active session's provider boundary is not yet maintainer-confirmed.

Maintainer options:

  1. Repair and retain purpose titles (recommended)
    Use the effective session model for implicit fallback eligibility and cap aggregate multi-edit work before merge.
  2. Split the provider-sensitive feature
    Land bounded deterministic rendering and pairing while deferring the model-title RPC to a narrower follow-up.
  3. Pause the broad feature
    Hold the PR if maintainers do not want display-only model spending and transcript-derived provider egress.

Next step before merge

  • The likely Control UI owner should decide the provider-egress policy and request fixes for the two line-level blockers before another exact-head review.

Maintainer decision needed

  • Question: Should decorative tool titles permit an explicitly configured utility model across providers, while limiting the implicit Luna fallback to sessions whose effective model is OpenAI?
  • Rationale: This display-only feature spends model tokens and transmits transcript-derived tool inputs, so the allowed cross-provider behavior requires explicit maintainer intent beyond the mechanical routing fix.
  • Likely owner: Peter Steinberger — He is the strongest history-based owner for the current Control UI chat surface and is assigned to this feature.
  • Options:
    • Gate implicit fallback by session (recommended): Allow explicitly configured utility models, but permit implicit Luna only when the loaded session's effective model routes to OpenAI.
    • Require explicit utility configuration: Remove implicit Luna and generate titles only when the operator has configured a utility model.
    • Defer model-generated titles: Land deterministic rendering and pairing while moving AI purpose titles to a later product-approved change.

Security
Needs attention: The implicit title fallback can transmit transcript-derived tool inputs across the active session's provider boundary.

Review findings

  • [P1] Gate Luna on the effective session model — src/gateway/chat-tool-titles.ts:220-224
  • [P2] Cap aggregate multi-edit diff work — ui/src/lib/chat/tool-call-view.ts:137-142
Review details

Best possible solution:

Keep the demonstrated deterministic rendering and pairing improvements, derive implicit Luna eligibility from the loaded session's effective model, impose one aggregate computation and rendered-row budget across multi-edit fallback diffs, and document the approved explicit-utility-model egress policy.

Do we have a high-confidence way to reproduce the issue?

Yes. An OpenAI-default agent with a non-OpenAI session override follows the provider-mismatch path, and a large edits array repeatedly invokes bounded quadratic LCS work before concatenating every section.

Is this the best way to solve the issue?

No, not yet. The UX and deterministic pairing approach are strong, but the maintainable solution must respect effective session routing and enforce one aggregate browser-work limit.

Full review comments:

  • [P1] Gate Luna on the effective session model — src/gateway/chat-tool-titles.ts:220-224
    Load the selected session entry and resolve its effective model before allowing the implicit Luna fallback. With an OpenAI agent default and a non-OpenAI session override, cache misses still send tool names and inputs to OpenAI even though the active session does not route there.
    Confidence: 0.98
  • [P2] Cap aggregate multi-edit diff work — ui/src/lib/chat/tool-call-view.ts:137-142
    Apply one total edit/count/cell and rendered-row budget before mapping every replacement through the fallback LCS. The per-section limits still allow a valid large edits array to allocate many 601×601 tables and mount thousands of rows, which can freeze the chat view.
    Confidence: 0.97

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 4d004e2054ba.

Label changes

Label changes:

  • add merge-risk: 🚨 availability: Aggregate multi-edit fallback diff work can stall the browser while rendering a valid large transcript.

Label justifications:

  • P2: This is a valuable Control UI improvement with two concrete merge blockers but no emergency or release-blocking user impact.
  • merge-risk: 🚨 auth-provider: The new title RPC can send tool inputs to OpenAI despite a non-OpenAI effective session model.
  • merge-risk: 🚨 availability: Aggregate multi-edit fallback diff work can stall the browser while rendering a valid large transcript.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (screenshot): Inspected live screenshots directly show after-fix grouped tool rows, inline diffs, terminal output, running state, and a real generated purpose title in the Control UI.
  • proof: sufficient: Contributor real behavior proof is sufficient. Inspected live screenshots directly show after-fix grouped tool rows, inline diffs, terminal output, running state, and a real generated purpose title in the Control UI.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. Inspected live screenshots directly show after-fix grouped tool rows, inline diffs, terminal output, running state, and a real generated purpose title in the Control UI.
Evidence reviewed

PR surface:

Source +2259, Tests +966, Docs +2. Total +3227 across 35 files.

View PR surface stats
Area Files Added Removed Net
Source 22 2335 76 +2259
Tests 11 1013 47 +966
Docs 2 3 1 +2
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 35 3351 124 +3227

Security concerns:

  • [medium] Use the effective session provider for fallback eligibility — src/gateway/chat-tool-titles.ts:221
    The fallback checks agent-level model selection rather than the loaded session's effective model, so a session override can unexpectedly send decorative-title inputs to OpenAI.
    Confidence: 0.98

Acceptance criteria:

  • [P1] pnpm test src/gateway/chat-tool-titles.test.ts.
  • [P1] pnpm test ui/src/lib/chat/tool-call-view.test.ts.
  • [P1] pnpm test ui/src/pages/chat/components/chat-tool-cards.test.ts.
  • [P1] pnpm test ui/src/pages/chat/chat-thread.test.ts.

What I checked:

  • Session override omitted from title generation: The new handler validates the session and agent, but calls generateToolCallTitles with only configuration, resolved agent id, and items; it never loads the session entry or supplies its effective model selection. (src/gateway/server-methods/chat.ts:3337, bb4a9ce8e928)
  • Implicit Luna gate uses agent defaults: Without an explicit utilityModel, fallback eligibility is based on resolveSimpleCompletionSelectionForAgent rather than the active session's effective model, so an OpenAI-default agent with a non-OpenAI session override still permits Luna. (src/gateway/chat-tool-titles.ts:220, bb4a9ce8e928)
  • Existing effective-model contract: Current main loads the persisted session entry and calls resolveSessionModelRef when behavior depends on the effective provider/model, including explicit persisted overrides. (src/gateway/server-methods/tools-effective.ts:504, 4d004e2054ba)
  • Unbounded aggregate multi-edit work: The view resolver maps every replacement through computeLineDiff and joins every result; each section is bounded individually, but the number of LCS tables and combined rendered rows is not bounded. (ui/src/lib/chat/tool-call-view.ts:137, bb4a9ce8e928)
  • Per-section limits do not cap the combined result: computeLineDiff can allocate a 601-by-601 LCS table per replacement, while joinDiffSections concatenates all sections without a total row limit. (ui/src/lib/chat/tool-call-diff.ts:87, bb4a9ce8e928)
  • Prior and current review continuity: The session-provider finding from the previous review remains unresolved on the current head; the latest current-head Codex review also identifies the aggregate multi-edit cost. (src/gateway/chat-tool-titles.ts:221, bb4a9ce8e928)

Likely related people:

  • Peter Steinberger: Current-main blame and feature history strongly associate the tool-card and chat-rendering surfaces with his merged work, and he is assigned to this feature. (role: introduced and recently maintained Control UI chat behavior; confidence: high; commits: 7b03a2ae201a; files: ui/src/pages/chat/components/chat-tool-cards.ts, ui/src/pages/chat/chat-thread.ts, src/gateway/server-methods/chat.ts)
  • JC: Recent merged work on GPT-5.6 and Codex runtime selection touched the simple-completion model surface used by the new title generator. (role: adjacent model-routing contributor; confidence: medium; commits: 59e95fe3fd8d; files: src/agents/simple-completion-runtime.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-10T15:14:02.077Z sha 9c9fa76 :: found issues before merge. :: [P1] Gate Luna titles on the selected session model

@steipete
steipete force-pushed the claude/tool-calls-webui-redesign-04de3c branch from 9c9fa76 to bb4a9ce Compare July 10, 2026 15:29

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb4a9ce8e9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +140 to +141
const sections = pairs.map((pair) => computeLineDiff(pair.oldText, pair.newText));
const joined = joinDiffSections(sections);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound multi-edit diff work across all edits

When a multi_edit/edits payload contains many replacements, this maps every pair through the quadratic LCS diff and then joinDiffSections keeps up to 400 rows per edit, so a large but valid transcript can allocate millions of cells and mount thousands of diff rows during chat rendering. The existing caps only apply per replacement; cap the number of pairs or the total diff rows before computing/rendering the fallback diff.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. label Jul 10, 2026
…mmaries, and cheap-model purpose titles

Kind-aware tool rows (terminal-style commands with wrapper stripping and
display highlighting, file edits with inline numbered diffs and diffstat,
write previews, key-value args), aggregate group summaries with live run
status, and a new batched chat.toolTitles gateway RPC that titles complex
calls via the configured utilityModel or the OpenAI Luna default (gated to
OpenAI-primary agents, cached in the per-agent SQLite cache_entries).

Also fixes two transcript pairing bugs: result blocks now inherit call
id/name/details at merge time, and results pair with any open call in the
current tool run so parallel calls render as single rows.

Fixes #103554
@steipete
steipete force-pushed the claude/tool-calls-webui-redesign-04de3c branch from bb4a9ce to 19a4322 Compare July 10, 2026 16:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19a43225fd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
if (changed) {
titlesVersion += 1;
head.notify?.();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Notify every pane in a title batch

In split-pane views of the same session/agent, queued items from different panes are batched together because the grouping only compares client, sessionKey, and agentId, but this only calls the first item's notify callback. Titles generated for the other pane(s) update the global store and titlesVersion, yet those panes do not request a render, so their rows stay on deterministic labels until some unrelated UI update happens.

Useful? React with 👍 / 👎.

titlesByKey.set(item.key, title);
changed = true;
} else {
failedKeys.add(item.key);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope title misses to request context

When a title request returns no title for an item, this records the digest in a process-global failedKeys set even though misses are context-dependent: for example, the first pane/session may have no eligible cheap model, while another agent/session later has a utility model or OpenAI primary for the exact same command. Because scheduleTitleRequest suppresses any key in failedKeys, that later eligible context never asks the gateway and the title is permanently disabled for the rest of the tab.

Useful? React with 👍 / 👎.

@steipete
steipete merged commit fc2afc8 into main Jul 10, 2026
99 checks passed
@steipete
steipete deleted the claude/tool-calls-webui-redesign-04de3c branch July 10, 2026 16:26
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 11, 2026
…mmaries, and cheap-model purpose titles (openclaw#103748)

Kind-aware tool rows (terminal-style commands with wrapper stripping and
display highlighting, file edits with inline numbered diffs and diffstat,
write previews, key-value args), aggregate group summaries with live run
status, and a new batched chat.toolTitles gateway RPC that titles complex
calls via the configured utilityModel or the OpenAI Luna default (gated to
OpenAI-primary agents, cached in the per-agent SQLite cache_entries).

Also fixes two transcript pairing bugs: result blocks now inherit call
id/name/details at merge time, and results pair with any open call in the
current tool run so parallel calls render as single rows.

Fixes openclaw#103554
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal backlog priority with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: XL status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Control UI: tool calls render as opaque JSON cards — no diffs, no purpose, unpaired parallel calls

1 participant