feat(ai): add typed runtime context#628
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR adds typed runtime context support (TContext) across TanStack AI's core APIs, framework integrations, tools, middleware, documentation, examples, and end-to-end tests. Runtime context is request-scoped typed application state passed to tool implementations and middleware via ChangesTyped Runtime Context Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed: lockfile failed supply-chain policy check. Run 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 |
5b10d74 to
fd36fac
Compare
🚀 Changeset Version PreviewNo changeset entries found. Merging this PR will not cause a version bump for any packages. |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/typescript/ai/src/activities/chat/middleware/types.ts (1)
384-387:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPropagate
TContextintoonStructuredOutputConfig(and its runner)
packages/typescript/ai/src/activities/chat/middleware/types.tsstill typesonStructuredOutputConfigasctx: ChatMiddlewareContext(non-generic), andpackages/typescript/ai/src/activities/chat/middleware/compose.tsstill typesrunOnStructuredOutputConfigasctx: ChatMiddlewareContext, dropping theTContextparameter fromChatMiddleware<TContext>for this hook.Update both signatures to use
ChatMiddlewareContext<TContext>so the hook receives the correctly typed context.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/typescript/ai/src/activities/chat/middleware/types.ts` around lines 384 - 387, Update the generic context propagation for the structured-output hook: change the type of onStructuredOutputConfig in the ChatMiddleware<TContext> interface to accept ctx: ChatMiddlewareContext<TContext> (not the non-generic ChatMiddlewareContext), and likewise update the runner function runOnStructuredOutputConfig in compose (and any helper/runner types it uses) to accept ctx: ChatMiddlewareContext<TContext> so the TContext parameter is preserved and the hook receives the correctly typed context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/ts-react-chat/src/routes/api.tanchat.ts`:
- Around line 164-166: The console.log in the onStart middleware is emitting raw
PII (ctx.context.userId and ctx.context.tenantId); change the log to avoid raw
identifiers by applying a deterministic mask or hash instead (e.g., introduce a
helper like hashIdentifier(id: string) or redactIdentifier(id: string) and call
it for ctx.context.userId and ctx.context.tenantId before logging), or drop
those fields entirely and only log non-PII such as ctx.context.loyaltyTier;
update the console.log invocation in the onStart handler to use the new helper
or redacted values.
In `@examples/ts-react-chat/src/routes/example.runtime-context.tsx`:
- Around line 198-203: The ReactMarkdown instance in example.runtime-context.tsx
incorrectly places the remark plugin remarkGfm in the rehypePlugins list; move
remarkGfm into the remarkPlugins prop so it's applied by remark instead of
rehype (locate the ReactMarkdown component where rehypePlugins is defined and
change the plugin arrays accordingly, keeping rehypeRaw, rehypeSanitize,
rehypeHighlight in rehypePlugins and adding remarkGfm to remarkPlugins).
---
Outside diff comments:
In `@packages/typescript/ai/src/activities/chat/middleware/types.ts`:
- Around line 384-387: Update the generic context propagation for the
structured-output hook: change the type of onStructuredOutputConfig in the
ChatMiddleware<TContext> interface to accept ctx:
ChatMiddlewareContext<TContext> (not the non-generic ChatMiddlewareContext), and
likewise update the runner function runOnStructuredOutputConfig in compose (and
any helper/runner types it uses) to accept ctx: ChatMiddlewareContext<TContext>
so the TContext parameter is preserved and the hook receives the correctly typed
context.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 601a7093-ba6a-4a21-874d-32f0d2abde34
📒 Files selected for processing (60)
docs/advanced/middleware.mddocs/advanced/runtime-context.mddocs/api/ai-client.mddocs/api/ai-preact.mddocs/api/ai-react.mddocs/api/ai-solid.mddocs/api/ai-svelte.mddocs/api/ai-vue.mddocs/api/ai.mddocs/config.jsondocs/migration/ag-ui-compliance.mddocs/migration/migration-from-vercel-ai.mddocs/tools/client-tools.mddocs/tools/server-tools.mdexamples/ts-code-mode-web/src/lib/execute-prompt.tsexamples/ts-code-mode-web/src/lib/structured-output.tsexamples/ts-react-chat/src/components/Header.tsxexamples/ts-react-chat/src/lib/guitar-tools.tsexamples/ts-react-chat/src/routeTree.gen.tsexamples/ts-react-chat/src/routes/api.tanchat.tsexamples/ts-react-chat/src/routes/example.runtime-context.tsxpackages/typescript/ai-client/src/chat-client.tspackages/typescript/ai-client/src/index.tspackages/typescript/ai-client/src/types.tspackages/typescript/ai-client/tests/chat-client-context.test.tspackages/typescript/ai-client/tests/tool-types.test.tspackages/typescript/ai-code-mode/src/types.tspackages/typescript/ai-code-mode/tests/create-code-mode-tool.test.tspackages/typescript/ai-preact/src/types.tspackages/typescript/ai-preact/src/use-chat.tspackages/typescript/ai-react/src/types.tspackages/typescript/ai-react/src/use-chat.tspackages/typescript/ai-react/tests/use-chat-types.test.tspackages/typescript/ai-solid/src/types.tspackages/typescript/ai-solid/src/use-chat.tspackages/typescript/ai-svelte/src/create-chat.svelte.tspackages/typescript/ai-svelte/src/types.tspackages/typescript/ai-svelte/tests/create-chat-types.test.tspackages/typescript/ai-vue/src/types.tspackages/typescript/ai-vue/src/use-chat.tspackages/typescript/ai/src/activities/chat/index.tspackages/typescript/ai/src/activities/chat/middleware/compose.tspackages/typescript/ai/src/activities/chat/middleware/types.tspackages/typescript/ai/src/activities/chat/tools/tool-calls.tspackages/typescript/ai/src/activities/chat/tools/tool-definition.tspackages/typescript/ai/src/types.tspackages/typescript/ai/src/utilities/chat-params.tspackages/typescript/ai/tests/middleware-context.test.tspackages/typescript/ai/tests/tool-call-manager-context.test.tspackages/typescript/ai/tests/tool-calls-context.test.tspackages/typescript/ai/tests/tool-context.test.tspackages/typescript/ai/tests/type-check.test.tstesting/e2e/fixtures/tools-test/client-context.jsontesting/e2e/fixtures/tools-test/client-server-context.jsontesting/e2e/fixtures/tools-test/server-context.jsontesting/e2e/src/lib/tools-test-tools.tstesting/e2e/src/routes/api.tools-test.tstesting/e2e/src/routes/tools-test.tsxtesting/e2e/tests/tools-test/helpers.tstesting/e2e/tests/tools-test/runtime-context.spec.ts
|
View your CI Pipeline Execution ↗ for commit c182c9a
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-anthropic
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-devtools-core
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-openrouter
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/typescript/ai/src/activities/chat/middleware/types.ts (1)
349-387:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
onStructuredOutputConfigstill drops typed runtime context
ChatMiddleware<TContext>threadsTContextthrough other hooks, butonStructuredOutputConfigkeepsctx: ChatMiddlewareContext(unknowncontext), so typed context is lost exactly in this phase.Proposed fix
onStructuredOutputConfig?: ( - ctx: ChatMiddlewareContext, + ctx: ChatMiddlewareContext<TContext>, config: StructuredOutputMiddlewareConfig, ) =>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/typescript/ai/src/activities/chat/middleware/types.ts` around lines 349 - 387, The onStructuredOutputConfig hook currently types its context as ChatMiddlewareContext (losing the generic TContext); update the signature on ChatMiddleware<TContext> so onStructuredOutputConfig receives ctx: ChatMiddlewareContext<TContext> (and keep the existing StructuredOutputMiddlewareConfig type for the second parameter) so the generic runtime context is preserved through this hook; locate the ChatMiddleware interface and change the onStructuredOutputConfig parameter type accordingly (referencing ChatMiddleware, onStructuredOutputConfig, ChatMiddlewareContext, and StructuredOutputMiddlewareConfig).
🧹 Nitpick comments (1)
packages/typescript/ai/tests/middleware-context.test.ts (1)
47-47: ⚡ Quick winAssert reference identity instead of deep equality.
Line 47 currently checks structural equality, so it won’t fail if middleware/tool receive cloned context objects. If the contract is “same runtime context instance,” assert identity with
toBe.Proposed change
- expect(seen).toEqual([context, context]) + expect(seen).toHaveLength(2) + expect(seen[0]).toBe(context) + expect(seen[1]).toBe(context)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/typescript/ai/tests/middleware-context.test.ts` at line 47, The test currently uses structural equality (expect(seen).toEqual([context, context])) which allows cloned objects to pass; change it to assert reference identity by replacing that assertion with identity checks such as expect(seen[0]).toBe(context) and expect(seen[1]).toBe(context) so both captured entries are the exact same runtime context instance.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@testing/e2e/tests/tools-test/helpers.ts`:
- Around line 94-107: The current page.evaluate in helpers.ts treats any
non-empty `#messages-json-content` as a started run and causes false positives
when fixtures are preloaded; update the check to compare the current messages
array length against the prior message count captured before clicking so we only
return true when a new run actually produced additional messages. Concretely: in
runTest() capture the preClickCount by parsing
document.getElementById('messages-json-content')?.textContent (default []), then
call page.evaluate with that preClickCount and inside the evaluated function
parse the messages once, return true if metadata.getAttribute('data-is-loading')
=== 'true' OR (Array.isArray(messages) && messages.length > preClickCount);
reference page.evaluate, '`#messages-json-content`', and the runTest() caller to
locate and implement this change.
---
Outside diff comments:
In `@packages/typescript/ai/src/activities/chat/middleware/types.ts`:
- Around line 349-387: The onStructuredOutputConfig hook currently types its
context as ChatMiddlewareContext (losing the generic TContext); update the
signature on ChatMiddleware<TContext> so onStructuredOutputConfig receives ctx:
ChatMiddlewareContext<TContext> (and keep the existing
StructuredOutputMiddlewareConfig type for the second parameter) so the generic
runtime context is preserved through this hook; locate the ChatMiddleware
interface and change the onStructuredOutputConfig parameter type accordingly
(referencing ChatMiddleware, onStructuredOutputConfig, ChatMiddlewareContext,
and StructuredOutputMiddlewareConfig).
---
Nitpick comments:
In `@packages/typescript/ai/tests/middleware-context.test.ts`:
- Line 47: The test currently uses structural equality
(expect(seen).toEqual([context, context])) which allows cloned objects to pass;
change it to assert reference identity by replacing that assertion with identity
checks such as expect(seen[0]).toBe(context) and expect(seen[1]).toBe(context)
so both captured entries are the exact same runtime context instance.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6bb95160-469b-4912-9470-f4089a8b533b
📒 Files selected for processing (60)
docs/advanced/middleware.mddocs/advanced/runtime-context.mddocs/api/ai-client.mddocs/api/ai-preact.mddocs/api/ai-react.mddocs/api/ai-solid.mddocs/api/ai-svelte.mddocs/api/ai-vue.mddocs/api/ai.mddocs/config.jsondocs/migration/ag-ui-compliance.mddocs/migration/migration-from-vercel-ai.mddocs/tools/client-tools.mddocs/tools/server-tools.mdexamples/ts-code-mode-web/src/lib/execute-prompt.tsexamples/ts-code-mode-web/src/lib/structured-output.tsexamples/ts-react-chat/src/components/Header.tsxexamples/ts-react-chat/src/lib/guitar-tools.tsexamples/ts-react-chat/src/routeTree.gen.tsexamples/ts-react-chat/src/routes/api.tanchat.tsexamples/ts-react-chat/src/routes/example.runtime-context.tsxpackages/typescript/ai-client/src/chat-client.tspackages/typescript/ai-client/src/index.tspackages/typescript/ai-client/src/types.tspackages/typescript/ai-client/tests/chat-client-context.test.tspackages/typescript/ai-client/tests/tool-types.test.tspackages/typescript/ai-code-mode/src/types.tspackages/typescript/ai-code-mode/tests/create-code-mode-tool.test.tspackages/typescript/ai-preact/src/types.tspackages/typescript/ai-preact/src/use-chat.tspackages/typescript/ai-react/src/types.tspackages/typescript/ai-react/src/use-chat.tspackages/typescript/ai-react/tests/use-chat-types.test.tspackages/typescript/ai-solid/src/types.tspackages/typescript/ai-solid/src/use-chat.tspackages/typescript/ai-svelte/src/create-chat.svelte.tspackages/typescript/ai-svelte/src/types.tspackages/typescript/ai-svelte/tests/create-chat-types.test.tspackages/typescript/ai-vue/src/types.tspackages/typescript/ai-vue/src/use-chat.tspackages/typescript/ai/src/activities/chat/index.tspackages/typescript/ai/src/activities/chat/middleware/compose.tspackages/typescript/ai/src/activities/chat/middleware/types.tspackages/typescript/ai/src/activities/chat/tools/tool-calls.tspackages/typescript/ai/src/activities/chat/tools/tool-definition.tspackages/typescript/ai/src/types.tspackages/typescript/ai/src/utilities/chat-params.tspackages/typescript/ai/tests/middleware-context.test.tspackages/typescript/ai/tests/tool-call-manager-context.test.tspackages/typescript/ai/tests/tool-calls-context.test.tspackages/typescript/ai/tests/tool-context.test.tspackages/typescript/ai/tests/type-check.test.tstesting/e2e/fixtures/tools-test/client-context.jsontesting/e2e/fixtures/tools-test/client-server-context.jsontesting/e2e/fixtures/tools-test/server-context.jsontesting/e2e/src/lib/tools-test-tools.tstesting/e2e/src/routes/api.tools-test.tstesting/e2e/src/routes/tools-test.tsxtesting/e2e/tests/tools-test/helpers.tstesting/e2e/tests/tools-test/runtime-context.spec.ts
✅ Files skipped from review due to trivial changes (14)
- testing/e2e/fixtures/tools-test/client-server-context.json
- docs/tools/server-tools.md
- testing/e2e/tests/tools-test/runtime-context.spec.ts
- docs/migration/ag-ui-compliance.md
- packages/typescript/ai-code-mode/tests/create-code-mode-tool.test.ts
- docs/api/ai-vue.md
- docs/api/ai-react.md
- docs/api/ai-solid.md
- examples/ts-code-mode-web/src/lib/structured-output.ts
- docs/migration/migration-from-vercel-ai.md
- docs/advanced/middleware.md
- docs/api/ai-preact.md
- docs/tools/client-tools.md
- examples/ts-react-chat/src/routeTree.gen.ts
- propagate ChatMiddlewareContext<TContext> through compose, structured output, and stream processor - thread TContext through tool registry, tool-call manager, code-mode bindings, and ai-client - add type-level tests for typed client context in ai-solid, ai-svelte, ai-vue, ai-preact, and ai-code-mode - mask user/tenant identifiers in ts-react-chat runtime-context middleware logging - fix runTest helper false-positive when fixtures are pre-populated by baselining the message count - update docs and runtime-context example for context typing changes
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
- `onBeforeToolCall` decisions of type `skip` push `skipResult` directly and call `onAfterToolCall` with `ok: true` without applying the tool’s `outputSchema` validation (server execution path validates `tool.outputSchema`), so middleware can cause invalid output to be treated as success.packages/typescript/ai/src/activities/chat/tools/tool-calls.ts (2)
441-463:⚠️ Potential issue | 🟠 Major | ⚡ Quick winValidate middleware
skipresults with the tool'soutputSchema.The
skipbranch pushesdecision.resultstraight intoresults, so middleware short-circuits bypass the output validation/normalization thatexecuteServerTool()andbuildClientToolResult()now apply. A skipped tool can therefore return an invalid “successful” result.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/typescript/ai/src/activities/chat/tools/tool-calls.ts` around lines 441 - 463, The skip branch currently pushes decision.result directly and calls middlewareHooks.onAfterToolCall, bypassing the tool output validation/normalization; update the handling for decision.type === 'skip' to run the skipResult through the same normalization/validation used by executeServerTool()/buildClientToolResult() (apply the tool's outputSchema and safeJsonParse as needed) and use that normalized value when pushing into results and when invoking middlewareHooks.onAfterToolCall (keep toolCallId/toolName/duration:0 and ok:true), so skipped results are validated before being recorded or reported.
604-615:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix executeToolCalls typing/runtime contract for tool context + middleware skip validation
executeToolCalls<TContext>keepsuserContext?: TContextand then casts it toToolExecutionContext<TContext>, soexecuteToolCalls<MyContext>(...)can omituserContexteven thoughToolExecuteFunctionrequirescontextwhenundefinedisn’t part ofTContext(tool implementations will seecontextas required).🔧 Proposed fix
export async function* executeToolCalls<TContext = unknown>( toolCalls: Array<ToolCall>, tools: ReadonlyArray<AnyTool>, approvals: Map<string, boolean> = new Map(), clientResults: Map<string, any> = new Map(), createCustomEventChunk?: ( eventName: string, value: Record<string, any>, ) => CustomEvent, middlewareHooks?: ToolExecutionMiddlewareHooks, - userContext?: TContext, + ...contextArgs: undefined extends TContext + ? [userContext?: TContext] + : [userContext: TContext] ): AsyncGenerator<CustomEvent, ExecuteToolCallsResult, void> { + const userContext = contextArgs[0] const results: Array<ToolResult> = [] const needsApproval: Array<ApprovalRequest> = [] const needsClientExecution: Array<ClientToolRequest> = []
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/api/ai-client.md`:
- Around line 362-364: The docs are inconsistent: the state union is documented
as "streaming" | "complete" | "error" but the addToolResult example still uses
"output-available"; update the addToolResult example to use one of the
documented states (e.g., replace "output-available" with "complete" or
"streaming" as appropriate) so the addToolResult example aligns with the state
union, and ensure any descriptive text around addToolResult references the same
state names.
---
Outside diff comments:
In `@packages/typescript/ai/src/activities/chat/tools/tool-calls.ts`:
- Around line 441-463: The skip branch currently pushes decision.result directly
and calls middlewareHooks.onAfterToolCall, bypassing the tool output
validation/normalization; update the handling for decision.type === 'skip' to
run the skipResult through the same normalization/validation used by
executeServerTool()/buildClientToolResult() (apply the tool's outputSchema and
safeJsonParse as needed) and use that normalized value when pushing into results
and when invoking middlewareHooks.onAfterToolCall (keep
toolCallId/toolName/duration:0 and ok:true), so skipped results are validated
before being recorded or reported.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 26354e21-c8ef-42ca-867c-021e7e823e0c
📒 Files selected for processing (45)
docs/advanced/runtime-context.mddocs/api/ai-client.mddocs/api/ai.mddocs/migration/ag-ui-compliance.mddocs/reference/functions/chatParamsFromRequest.mddocs/reference/functions/chatParamsFromRequestBody.mddocs/tools/client-tools.mdexamples/ts-react-chat/src/routes/api.tanchat.tsexamples/ts-react-chat/src/routes/example.runtime-context.tsxexamples/ts-react-chat/src/routes/issue-176-tool-result.tsxpackages/typescript/ai-client/src/chat-client.tspackages/typescript/ai-client/src/types.tspackages/typescript/ai-client/tests/chat-client-context.test.tspackages/typescript/ai-client/tests/tool-types.test.tspackages/typescript/ai-code-mode-skills/src/code-mode-with-skills.tspackages/typescript/ai-code-mode-skills/src/create-skill-management-tools.tspackages/typescript/ai-code-mode-skills/src/skills-to-tools.tspackages/typescript/ai-code-mode-skills/src/storage/file-storage.tspackages/typescript/ai-code-mode-skills/src/storage/memory-storage.tspackages/typescript/ai-code-mode/src/bindings/tool-to-binding.tspackages/typescript/ai-code-mode/src/types.tspackages/typescript/ai-code-mode/tests/code-mode-types.test.tspackages/typescript/ai-code-mode/tests/create-code-mode-tool.test.tspackages/typescript/ai-code-mode/tests/tool-to-binding.test.tspackages/typescript/ai-preact/tests/use-chat-types.test.tspackages/typescript/ai-solid/tests/use-chat-types.test.tspackages/typescript/ai-svelte/tests/create-chat-types.test.tspackages/typescript/ai-vue/tests/use-chat-types.test.tspackages/typescript/ai/src/activities/chat/index.tspackages/typescript/ai/src/activities/chat/middleware/compose.tspackages/typescript/ai/src/activities/chat/middleware/types.tspackages/typescript/ai/src/activities/chat/stream/processor.tspackages/typescript/ai/src/activities/chat/tools/tool-calls.tspackages/typescript/ai/src/activities/chat/tools/tool-definition.tspackages/typescript/ai/src/index.tspackages/typescript/ai/src/tool-registry.tspackages/typescript/ai/src/types.tspackages/typescript/ai/src/utilities/chat-params.tspackages/typescript/ai/tests/chat-params.test.tspackages/typescript/ai/tests/chat.test.tspackages/typescript/ai/tests/middleware-context.test.tspackages/typescript/ai/tests/stream-processor.test.tspackages/typescript/ai/tests/tool-call-manager.test.tspackages/typescript/ai/tests/type-check.test.tstesting/e2e/tests/tools-test/helpers.ts
✅ Files skipped from review due to trivial changes (6)
- packages/typescript/ai-code-mode-skills/src/storage/memory-storage.ts
- packages/typescript/ai-code-mode-skills/src/storage/file-storage.ts
- docs/tools/client-tools.md
- docs/migration/ag-ui-compliance.md
- docs/reference/functions/chatParamsFromRequest.md
- docs/advanced/runtime-context.md
| | "streaming" | ||
| | "complete" | ||
| | "error"; |
There was a problem hiding this comment.
Align tool-result state docs with the addToolResult example.
Line 362 introduces "streaming" | "complete" | "error", but this page still demonstrates "output-available" in the addToolResult section, which is contradictory for readers. Please update one side so the documented state model is consistent end-to-end.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/api/ai-client.md` around lines 362 - 364, The docs are inconsistent: the
state union is documented as "streaming" | "complete" | "error" but the
addToolResult example still uses "output-available"; update the addToolResult
example to use one of the documented states (e.g., replace "output-available"
with "complete" or "streaming" as appropriate) so the addToolResult example
aligns with the state union, and ensure any descriptive text around
addToolResult references the same state names.
…ntext-pr # Conflicts: # docs/migration/ag-ui-compliance.md # docs/tools/client-tools.md # examples/ts-react-chat/src/routes/api.tanchat.ts # packages/ai-client/src/chat-client.ts # packages/ai-client/src/types.ts # packages/ai-client/tests/chat-client-context.test.ts # packages/ai-code-mode/tests/code-mode-types.test.ts # packages/ai-preact/src/types.ts # packages/ai-preact/src/use-chat.ts # packages/ai-preact/tests/use-chat-types.test.ts # packages/ai-react/src/types.ts # packages/ai-react/src/use-chat.ts # packages/ai-solid/src/types.ts # packages/ai-solid/src/use-chat.ts # packages/ai-svelte/src/create-chat.svelte.ts # packages/ai-svelte/src/types.ts # packages/ai-vue/src/types.ts # packages/ai-vue/src/use-chat.ts # packages/ai/tests/middleware-context.test.ts # packages/ai/tests/tool-call-manager-context.test.ts # packages/ai/tests/tool-calls-context.test.ts # packages/ai/tests/tool-context.test.ts
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/ts-react-chat/src/routes/api.tanchat.ts (1)
258-313:⚠️ Potential issue | 🟠 Major | ⚡ Quick winProvider-specific model defaults are currently unreachable.
modelis pre-filled before adapter selection, so each(model || '...')always resolves tomodel. This makes per-provider defaults ineffective and can send an incompatible default to non-OpenAI adapters.🔧 Suggested fix
- const model: string = - typeof params.forwardedProps.model === 'string' - ? params.forwardedProps.model - : 'gpt-4o' + const forwardedModel = + typeof params.forwardedProps.model === 'string' && + params.forwardedProps.model.trim() !== '' + ? params.forwardedProps.model + : undefined ... - adapter: anthropicText( - (model || 'claude-sonnet-4-6') as 'claude-sonnet-4-6', - ), + adapter: anthropicText( + (forwardedModel ?? 'claude-sonnet-4-6') as 'claude-sonnet-4-6', + ), ... - adapter: geminiText( - (model || 'gemini-3.1-pro-preview') as 'gemini-3.1-pro-preview', - ), + adapter: geminiText( + (forwardedModel ?? + 'gemini-3.1-pro-preview') as 'gemini-3.1-pro-preview', + ), ... - adapter: geminiTextInteractions( - (model || 'gemini-3.1-pro-preview') as 'gemini-3.1-pro-preview', - ), + adapter: geminiTextInteractions( + (forwardedModel ?? + 'gemini-3.1-pro-preview') as 'gemini-3.1-pro-preview', + ), ... - adapter: grokText((model || 'grok-4.20') as 'grok-4.20'), + adapter: grokText((forwardedModel ?? 'grok-4.20') as 'grok-4.20'), ... - adapter: groqText( - (model || 'openai/gpt-oss-120b') as 'openai/gpt-oss-120b', - ), + adapter: groqText( + (forwardedModel ?? + 'openai/gpt-oss-120b') as 'openai/gpt-oss-120b', + ), ... - adapter: ollamaText((model || 'gpt-oss:20b') as 'gpt-oss:20b'), + adapter: ollamaText( + (forwardedModel ?? 'gpt-oss:20b') as 'gpt-oss:20b', + ), ... - adapter: openaiText((model || 'gpt-5.2') as 'gpt-5.2'), + adapter: openaiText((forwardedModel ?? 'gpt-5.2') as 'gpt-5.2'),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/ts-react-chat/src/routes/api.tanchat.ts` around lines 258 - 313, The per-provider default model strings are never used because the code checks (model || '...') where model is pre-filled; change the logic so each branch computes a providerDefault and uses (model ?? providerDefault) (or equivalent) when calling adapters in createChatOptions; update branches that call openRouterText, geminiText, geminiTextInteractions, grokText, groqText, ollamaText, openaiText, etc., to pass model ?? '<provider-default>' instead of (model || '<provider-default>') so provider-specific defaults are applied only when model is undefined/null.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@examples/ts-react-chat/src/routes/api.tanchat.ts`:
- Around line 258-313: The per-provider default model strings are never used
because the code checks (model || '...') where model is pre-filled; change the
logic so each branch computes a providerDefault and uses (model ??
providerDefault) (or equivalent) when calling adapters in createChatOptions;
update branches that call openRouterText, geminiText, geminiTextInteractions,
grokText, groqText, ollamaText, openaiText, etc., to pass model ??
'<provider-default>' instead of (model || '<provider-default>') so
provider-specific defaults are applied only when model is undefined/null.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 13247677-3167-41a2-b998-f2e027007d3a
📒 Files selected for processing (10)
docs/advanced/middleware.mddocs/api/ai-vue.mddocs/config.jsondocs/migration/ag-ui-compliance.mddocs/reference/functions/chatParamsFromRequest.mddocs/reference/functions/chatParamsFromRequestBody.mddocs/tools/client-tools.mdexamples/ts-react-chat/src/components/Header.tsxexamples/ts-react-chat/src/routeTree.gen.tsexamples/ts-react-chat/src/routes/api.tanchat.ts
💤 Files with no reviewable changes (1)
- docs/migration/ag-ui-compliance.md
✅ Files skipped from review due to trivial changes (4)
- docs/reference/functions/chatParamsFromRequestBody.md
- docs/reference/functions/chatParamsFromRequest.md
- docs/tools/client-tools.md
- examples/ts-react-chat/src/routeTree.gen.ts
Merge auto-resolution left duplicate EventType (value) and StreamChunk (type) imports, causing Vite pre-transform to fail with "Crawling result not available" and timing out the entire E2E suite.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
testing/e2e/src/routes/api.tools-test.ts (1)
174-175:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winValidate
aimockPortbefore passing it to the adapter.On Line 175,
Number(fp.aimockPort)can becomeNaNfor invalid input and then flows intocreateTextAdapter(...). Please reject non-finite values with a400(or coerce toundefined) to avoid turning bad input into internal failures.Suggested patch
- const aimockPort: number | undefined = - fp.aimockPort != null ? Number(fp.aimockPort) : undefined + const parsedAimockPort = + fp.aimockPort != null ? Number(fp.aimockPort) : undefined + if (parsedAimockPort != null && !Number.isFinite(parsedAimockPort)) { + return new Response('Invalid aimockPort', { status: 400 }) + } + const aimockPort: number | undefined = parsedAimockPort🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@testing/e2e/src/routes/api.tools-test.ts` around lines 174 - 175, The computed aimockPort variable can become NaN and then be passed into createTextAdapter; validate it after parsing by using Number(fp.aimockPort) and checking Number.isFinite(value) (or Number.isInteger/within port range) and if invalid either set aimockPort = undefined before calling createTextAdapter or immediately return a 400 response; update the code around the aimockPort assignment and the call site to use the validated value (referencing the aimockPort variable and the createTextAdapter(...) invocation) so bad input does not flow into the adapter.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@testing/e2e/src/routes/api.tools-test.ts`:
- Around line 174-175: The computed aimockPort variable can become NaN and then
be passed into createTextAdapter; validate it after parsing by using
Number(fp.aimockPort) and checking Number.isFinite(value) (or
Number.isInteger/within port range) and if invalid either set aimockPort =
undefined before calling createTextAdapter or immediately return a 400 response;
update the code around the aimockPort assignment and the call site to use the
validated value (referencing the aimockPort variable and the
createTextAdapter(...) invocation) so bad input does not flow into the adapter.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2e55c43e-44ae-442a-9d3c-34aa986b2690
📒 Files selected for processing (1)
testing/e2e/src/routes/api.tools-test.ts
Summary
useChatwrappers without breaking untyped middleware/tools.chat()and client-local context throughChatClientso tool and middleware implementations can access typed runtime data.ts-react-chatruntime context route.Test Plan
git diff --cached --checkpnpm --filter @tanstack/ai-event-client buildpnpm --filter @tanstack/ai test:typespnpm --filter @tanstack/ai buildpnpm --filter @tanstack/ai-client test:typespnpm --filter @tanstack/ai test:lib -- run tests/tool-context.test.ts tests/tool-calls-context.test.ts tests/tool-call-manager-context.test.ts tests/middleware-context.test.ts tests/type-check.test.tspnpm --filter @tanstack/ai-client test:lib -- run tests/chat-client-context.test.ts tests/tool-types.test.tspnpm --filter @tanstack/ai-client buildpnpm --filter @tanstack/ai-react test:typespnpm --filter @tanstack/ai-solid test:typespnpm --filter @tanstack/ai-vue test:typespnpm --filter @tanstack/ai-svelte test:typespnpm --filter @tanstack/ai-preact test:typespnpm --filter @tanstack/ai-code-mode test:typespnpm --filter @tanstack/ai-react test:lib -- run tests/use-chat-types.test.tspnpm --filter @tanstack/ai-svelte test:lib -- run tests/create-chat-types.test.tspnpm --filter @tanstack/ai-utils buildpnpm --filter @tanstack/openai-base build@tanstack/ai-openai,@tanstack/ai-anthropic,@tanstack/ai-gemini,@tanstack/ai-grok,@tanstack/ai-groq,@tanstack/ai-elevenlabs,@tanstack/ai-ollama,@tanstack/ai-openrouterpnpm --filter @tanstack/ai-e2e test:e2e -- tests/tools-test/runtime-context.spec.tsNotes: Vite/svelte-check emitted the existing missing
.svelte-kit/tsconfig.jsonwarning forexamples/ts-svelte-chat; the commands above exited successfully where listed.Summary by CodeRabbit