Skip to content

Upgrade TanStack AI to 1.0, type tool parts, merge client tools on the server - #6

Open
AlemTuzlak wants to merge 2 commits into
mainfrom
feat/tanstack-ai-v1-typed-tools
Open

AlemTuzlak wants to merge 2 commits into
mainfrom
feat/tanstack-ai-v1-typed-tools

Conversation

@AlemTuzlak

Copy link
Copy Markdown
Collaborator

What changed

TanStack AI 1.0

  • All @tanstack/ai* packages bumped to 1.0.0; the 20 tracked exercise lockfiles regenerated (each passes npm ci --dry-run).
  • 1.0 requires a threadId on useChat and chat(). Every chat panel keeps one stable id per mount with useState(() => crypto.randomUUID()); every route passes threadId through. Docs and instructor notes updated.

Typed tool parts (02.tools and 03.structured-replies)

  • Tool definitions are split from server code: app/tools/products.ts + products.server.ts, variations.ts + variations.server.ts. The browser imports definitions only.
  • product-chat.tsx passes the server tools' definitions plus the .client() tools to useChat({ tools }). Each tool-call part is now a union on part.name with a typed output, rendered with a switch and the components in the new app/components/tool-parts.tsx. The part.output as {...} and ProductCard casts are gone.
  • Attendees write the switch starting in 02.01 and add one case per step. The components are imported and the line to uncomment is in each 🐨 comment.

Server merges client tools (02.02 onward)

  • chat({ tools: mergeAgentTools([...serverTools], clientTools) }), with tools: clientTools from chatParamsFromRequest. Taught in 02.02, including why a plain [...server, ...client] spread is wrong: the browser sends parameters but chat() reads inputSchema, and it would duplicate the server tools.
  • The shared definitions stay listed on the server. The browser only sends a name, description and input schema, so needsApproval, lazy and the output schema come from the server's copy. Checked with a mock adapter: if the server only has the browser's copy of addToCart, the browser runs it without asking for approval (only a console warning shows).

Problem apps no longer 500

  • The 02.02 and 02.03 problem apps returned HTTP 500 on every page before the attendee had written anything: the browser imported navigateToDef / addToCartDef before they existed. The 🐨 comments now say to add that import after building the definition.

Review guide

  1. exercises/02.tools/04.solution.make-tools-lazy: the finished pattern.
  2. 02.01 problem vs solution: what attendees write first.
  3. exercises/02.tools/02.problem.taking-the-user-around: where the merge is taught.
  4. exercises/03.structured-replies/* copies the 02.04 solution's chat, tool-parts and tool files unchanged.

Verification

  • typecheck in all 20 apps: solutions are clean except the existing app/epicshop.tsx error. Problem apps show only the intended "not built yet" errors.
  • node ./epicshop/test.ts ..s: all 10 solution apps pass.
  • Client build checked for server code leaks; the problem apps load and the chat opens with no console errors.
  • Mock-adapter run of the merge: approve runs the tool and continues; deny skips it and sets approval.approved === false.
  • Not tested against a real model: the local OpenRouter key is revoked.

Not in this PR

  • The app/epicshop.tsx type error (from @epic-web/workshop-utils).
  • npm run build failing on the top-level await prisma.$connect().
  • The chat panel shows nothing when a run errors.

🤖 Generated with Claude Code

- Bump @tanstack/ai, ai-client, ai-react, ai-openrouter, ai-event-client
  and react-ai-devtools to 1.0.0 and refresh the tracked exercise lockfiles.
- 1.0 requires a threadId on useChat and chat(). The chat panels keep one
  stable id per mounted chat with useState(() => crypto.randomUUID()).
- Add threadId to the basic-setup and structured-replies docs, the 01.02
  instructions, and the instructor notes.
- Split each tool's definition from its server code (products.ts +
  products.server.ts, variations.ts + variations.server.ts) so the browser
  can import definitions without pulling in database code.
- The chat panel passes the server tools' definitions and the client tools
  to useChat, so every tool-call part is a union on part.name with a typed
  output. Render it with a switch and the components in tool-parts.tsx
  instead of casting part.output.
- From 02.02 on, the server merges the tools the browser declares with
  mergeAgentTools(serverTools, clientTools). The shared definitions stay
  listed on the server: the browser's copy carries no needsApproval or
  output schema, and without the server's copy addToCart runs without
  asking for approval.
- Attendees write the switch from 02.01 and add a case per step, with the
  ready-made components imported and the line to uncomment in each comment.
- Problem files no longer import a definition the attendee hasn't exported
  yet. Doing that returned a 500 on every page of the store.
- Update the tools READMEs and the "If you get stuck" entries to match.
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