Skip to content

feat(ai): structured tool-call display (AI Elements–style) - #99

Merged
os-zhuang merged 1 commit into
mainfrom
feat/ai-tool-display
Jun 10, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
feat/ai-tool-display

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

What

Replaces the one-line Ran query_data caption with a collapsible, structured tool block — a React Native take on Vercel AI Elements' Tool component (which is web/DOM-only, so it can't be ported directly).

  • lib/ai-chat.ts — the SSE parser now captures rich ToolInvocation objects ({ id, name, input, output, state }) by merging tool-input-available + tool-output-available events keyed by toolCallId (was: just names). onUpdate streams the live tools; toolCalls: string[] kept for back-compat.
  • components/ui/ToolInvocations.tsx — per-tool collapsible row: tool name + running/done status, expanding to reveal the input args and the result (mono, scrollable).
  • store messages carry tools: ToolInvocation[]; app/ai.tsx renders the block under assistant turns.

Why custom (not the library objectui uses)

Confirmed from objectui's source: its chat UI is Vercel AI Elements (vendored MIT, shadcn/DOM) on top of @ai-sdk/react useChat. Neither ports to React Native — AI Elements is web-only (<div>/Radix/streamdown/shiki), and useChat hits a React 19.2.0 peer gap on Expo 55. So we mirror the design in custom RN components.

Tests

  • Parser captures {input, output, state} keyed by toolCallId — asserted against the real captured SSE tool format.
  • ToolInvocations component: collapsed-by-default, expand reveals input/result, running hides result, one row per tool.
  • Screen integration + store carry-through.
  • npm run lint 0 errors; jest 1255/1255 (153 suites).

Verification note: tested at every layer against the real server's SSE shape; the visual block itself is standard NativeWind (not screenshotted this round — MMKV/native-gated screens aren't browser-testable, but this one could be device-verified).

🤖 Generated with Claude Code

Replaces the one-line "Ran query_data" caption with a collapsible,
structured tool block — a React Native take on Vercel AI Elements' Tool
component (which is web/DOM-only, so it can't be ported directly).

- lib/ai-chat.ts: the SSE parser now captures rich ToolInvocation objects
  ({ id, name, input, output, state }) by merging tool-input-available +
  tool-output-available events keyed by toolCallId (was: just names).
  onUpdate streams the live tools; `toolCalls: string[]` kept for back-compat.
- components/ui/ToolInvocations.tsx: per-tool collapsible row — name +
  running/done status, expanding to show input args and the result.
- store message carries `tools: ToolInvocation[]`; app/ai.tsx renders the
  block under assistant turns.

Tested against the real captured SSE tool format (input/output/state by
toolCallId) + component + screen integration. Suite 1255/1255, lint clean.

Context: confirmed objectui's chat UI is Vercel AI Elements (vendored MIT,
shadcn/DOM) + @ai-sdk/react useChat — neither ports to RN (Elements is
web-only; useChat hits a React 19.2.0 peer gap on Expo 55). So we mirror
the *design* in custom RN components instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@os-zhuang
os-zhuang merged commit 56dca39 into main Jun 10, 2026
@os-zhuang
os-zhuang deleted the feat/ai-tool-display branch June 10, 2026 11:13
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