Skip to content

feat: Upgrade AI SDK to v6#497

Merged
lixun910 merged 39 commits intomainfrom
feat/ai-sdk-v6
Apr 16, 2026
Merged

feat: Upgrade AI SDK to v6#497
lixun910 merged 39 commits intomainfrom
feat/ai-sdk-v6

Conversation

@mihajlo-stojkovic
Copy link
Copy Markdown
Collaborator

@mihajlo-stojkovic mihajlo-stojkovic commented Mar 24, 2026

Summary

Upgrades AI SDK from v5 to v6 ([email protected]) across all packages and examples.

The core change is replacing streamText with ToolLoopAgent — tool execution now happens server-side inside an agent loop instead of being orchestrated client-side via onChatToolCall. This removes ~120 lines of dead plumbing (waitForToolOutput, pendingToolCallResolvers, onChatToolCall) and simplifies the transport layer significantly.

Sub-agent composition follows the same pattern: processAgentStream is replaced by streamSubAgent, which wraps a ToolLoopAgent + createAgentUIStream.

The other major addition is native support for the v6 needsApproval approval flow. Tools with needsApproval: true now pause the agent loop, stream an approval-requested state to the client, and resume when the user confirms or denies. This replaces our custom approval wiring.

Note: The needsApproval mechanism in the Vercel AI SDK works by pausing the chat-level loop and emitting an approval-requested state in the UI message parts. But createAgentUIStream / ToolLoopAgent runs its own internal loop, and it doesn't know how to pause and wait for user approval.

The solution to support needsApproval for nested agent is:

Add sub-agent approval infrastructure to AgentUtils.ts: Extend AgentStreamStore and streamSubAgent to detect tool-approval-request chunks, surface them via the store, wait for user response, and restart the stream with the approval response.

Add approval state/methods to AiSlice.ts: A pendingSubAgentApprovals map and methods to request/resolve them.

Update ToolPartRenderer.tsx: Make AgentToolCallEntry render the approval UI for sub-agent tools with pending approvals.

Update BookHotelApprovalRenderer.tsx: Make it work with the sub-agent approval mechanism.

Renames: addToolResultaddToolOutput, processAgentStreamstreamSubAgent.

Breaking changes

  • addToolResultaddToolOutput with new signature: {tool, toolCallId, output}
  • processAgentStreamstreamSubAgent(agent, prompt, abortSignal)
  • Tool renderers may receive new states: approval-requested, approval-responded, output-denied
  • Remote transport routes must migrate to ToolLoopAgent + createAgentUIStreamResponse

See docs/upgrade-guide.md section 0.29.0 for full migration instructions with code examples.

Summary by CodeRabbit

  • Documentation

    • Updated upgrade guide for AI SDK v6 migration with new agent-driven streaming, server request fields (instructions, maxSteps, temperature), renderer changes, and revised examples.
  • New Features

    • Added three tool-call approval states to support approval workflows.
    • Enabled composing sub-agents and server-controlled agent parameters for streamed agent execution.
  • Refactor

    • Upgraded examples/projects to AI SDK v6 and renamed the tool result helper to a new tool-output API.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 24, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces AI SDK v5 streaming/execution with AI SDK v6 ToolLoopAgent/streamSubAgent, renames addToolResult → addToolOutput, adds approval-related tool states and approval APIs, updates transports/types/components/hooks/examples/docs, and fixes toModelOutput parameter shapes.

Changes

Cohort / File(s) Summary
Docs
docs/upgrade-guide.md
Documented AI SDK v6 migration: ToolLoopAgent/streamSubAgent, addToolResultaddToolOutput, new approval states, remote transport changes, and corrected toModelOutput param shape.
Dependency bumps (examples & packages)
examples/*/package.json, packages/*/package.json, apps/*/package.json
Bumped ai from ^5.0.155^6.0.138; bumped @ai-sdk/react in packages/ai-core/package.json.
Agent examples
examples/ai-agent/src/agents/WeatherAgent.ts, examples/ai-agent/package.json
Replaced Experimental_Agent/processAgentStream with ToolLoopAgent + streamSubAgent; removed toolCallId plumbing; updated example dependency.
Next.js example
examples/ai-nextjs/src/app/api/chat/route.ts, examples/ai-nextjs/package.json
Switched server streaming from streamTextToolLoopAgent + createAgentUIStreamResponse; introduced server-controlled instructions,maxSteps,temperature; removed inline UI stream merge.
Core state & transport
packages/ai-core/src/AiSlice.ts, packages/ai-core/src/chatTransport.ts
Renamed addToolResultaddToolOutput; removed waitForToolResult/onChatToolCall; added AddToolApprovalResponse APIs; transports now use ToolLoopAgent and require getInstructions, include instructions,maxSteps,temperature.
Agent utilities & exports
packages/ai-core/src/agents/AgentUtils.ts, packages/ai-core/src/index.ts, packages/ai/src/index.ts
Removed processAgentStream and chunk types; added streamSubAgent and updateAgentToolCallData; updated exported types (AddToolOutput, AgentToolCallAdditionalData).
Types & schema
packages/ai-core/src/types.ts, packages/ai-config/src/schema/UIMessageSchema.ts, packages/ai-config/src/index.ts
Renamed AddToolResultAddToolOutput; added AddToolApprovalResponse; extended ToolRendererProps and UI message schemas with approval-requested,approval-responded,output-denied; exported DynamicToolUIPart.
Components
packages/ai-core/src/components/...
Expanded tool state unions to include approval states; removed isCompleted prop; updated rendering flows and passed approvalId; minor UI tweaks (icon width, error logging).
Hooks & utils
packages/ai-core/src/hooks/*, packages/ai-core/src/utils.ts
Switched auto-send gating to approval-aware check, added shouldEndAnalysis, updated store sync for addToolOutput/approval responses, treated approval-responded as completed.
Tool adapters
packages/ai-rag/src/createRagTool.tsx, packages/ai/src/tools/*, packages/vega/src/VegaChartTool.tsx
Changed toModelOutput callbacks to destructure {output}; adjusted Rag tool result destructuring.
Misc / small refactors
packages/pivot/src/pivotExecution.ts, packages/ai-core/README.md
Minor Array.from refactor; README updated to mention streamSubAgent.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant Agent as ToolLoopAgent
    participant UIStream as Agent UI Stream
    participant Tools as Tools/Models
    participant Approval as Approval Handler
    participant Renderer as UI Renderer

    App->>Agent: create(instructions, tools, temperature, stopWhen)
    Agent->>Tools: invoke toolCall
    Tools-->>Agent: return output / error
    Agent->>UIStream: emit UI chunks (text-delta, tool-*-events)
    UIStream-->>Renderer: stream chunks → update UI/tool state

    alt approval requested
        Agent->>UIStream: emit approval-requested (id)
        UIStream-->>Renderer: show approval UI
        Approval->>Agent: submit approval response (id, approved)
        Agent->>UIStream: emit approval-responded
    end

    alt approval denied
        Agent->>UIStream: emit output-denied
    else success
        Agent->>UIStream: emit final text-delta
    end

    Agent->>Agent: check stopWhen(stepCountIs(maxSteps))
    Agent-->>App: return final accumulated text
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • lixun910
  • ilyabo
  • dmitriy-kostianetskiy

"🐰
Hopped from v5 to v6 tonight,
ToolLoopAgent guiding light,
Streams now ask for approval votes,
Outputs renamed in tidy notes,
I nibble changes, take a bite ✨"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Upgrade AI SDK to v6' is clear, concise, and directly summarizes the primary change across the entire changeset—upgrading the AI SDK from version 5 to version 6.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ai-sdk-v6

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

# Conflicts:
#	examples/app-builder/package.json
#	packages/ai-core/src/AiSlice.ts
#	pnpm-lock.yaml
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Upgrades the monorepo to AI SDK v6 ([email protected]) and migrates the chat/tool streaming architecture from streamText + client-orchestrated tool calls to ToolLoopAgent + agent-loop streaming, with additional schema/type updates to support v6 approval states.

Changes:

  • Bumps ai / @ai-sdk/react dependencies to v6/v3 across packages, examples, and lockfile.
  • Reworks transports and agent utilities to use ToolLoopAgent + createAgentUIStreamResponse/createAgentUIStream, and updates public exports/renames (processAgentStreamstreamSubAgent, addToolResultaddToolOutput).
  • Extends UI message schemas/types and tool rendering to recognize v6 approval-related tool states (approval-requested, approval-responded, output-denied), and updates docs/example routes accordingly.

Reviewed changes

Copilot reviewed 32 out of 33 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
pnpm-lock.yaml Locks upgraded AI SDK + related dependency graph changes.
packages/vega/src/VegaChartTool.tsx Updates toModelOutput signature to v6 tool output wrapper shape.
packages/vega/package.json Pins ai dependency to 6.0.132.
packages/mosaic/package.json Reorders deps (no functional change).
packages/ai/src/tools/query/queryTool.ts Updates toModelOutput signature to v6 wrapper shape.
packages/ai/src/index.ts Updates public exports/types to new agent/tool APIs and renames.
packages/ai/package.json Pins ai dependency to 6.0.132.
packages/ai-rag/src/createRagTool.tsx Updates tool output mapping signature; removes unused output destructuring.
packages/ai-rag/package.json Pins ai dependency to 6.0.132.
packages/ai-core/src/utils.ts Adds shouldEndAnalysis; updates tool-call completion logic for approval states.
packages/ai-core/src/types.ts Replaces AddToolResult with AddToolOutput and adds approval response typing; expands tool renderer states.
packages/ai-core/src/index.ts Re-exports new utilities/types (streamSubAgent, updateAgentToolCallData, approval types, etc.).
packages/ai-core/src/hooks/useSessionChat.ts Migrates to v6 useChat API surface (addToolOutput, addToolApprovalResponse) and new auto-send helper.
packages/ai-core/src/hooks/useAssistantMessageParts.ts Adjusts message parts typing to align with updated schemas.
packages/ai-core/src/components/tools/ToolResult.tsx Extends accepted tool states for approval flow.
packages/ai-core/src/components/ToolPartRenderer.tsx Adds approval-state rendering path and passes approvalId into tool renderers.
packages/ai-core/src/components/ToolCallInfo.tsx Extends state union to include approval states; simplifies props usage.
packages/ai-core/src/chatTransport.ts Replaces streamText pipeline with ToolLoopAgent + createAgentUIStreamResponse; updates remote request body shape.
packages/ai-core/src/agents/AgentUtils.ts Replaces processAgentStream with streamSubAgent using v6 agent UI stream.
packages/ai-core/src/AiSlice.ts Removes client-side tool-call plumbing; adds per-session output/approval function registration; switches deep copy to structuredClone.
packages/ai-core/package.json Upgrades ai and @ai-sdk/react dependency versions.
packages/ai-core/README.md Updates docs to reference streamSubAgent instead of processAgentStream.
packages/ai-config/src/schema/UIMessageSchema.ts Updates Zod schemas for AI SDK v6 UIMessage/tool states (incl. approval states).
packages/ai-config/src/index.ts Exports DynamicToolUIPart type alongside existing UI message part types.
examples/app-builder/package.json Pins ai dependency to 6.0.132.
examples/ai/package.json Pins ai dependency to 6.0.132.
examples/ai-rag/package.json Pins ai dependency to 6.0.132.
examples/ai-nextjs/src/app/api/chat/route.ts Migrates Next.js route to ToolLoopAgent + createAgentUIStreamResponse and new request params.
examples/ai-nextjs/package.json Pins ai dependency to 6.0.132.
examples/ai-core/package.json Pins ai dependency to 6.0.132.
examples/ai-agent/src/agents/WeatherAgent.ts Migrates sub-agent tool to ToolLoopAgent + streamSubAgent.
examples/ai-agent/package.json Pins ai dependency to 6.0.132.
docs/upgrade-guide.md Adds 0.29.0 migration guide covering ToolLoopAgent, addToolOutput, approval states, and remote transport changes.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/ai-core/src/AiSlice.ts Outdated
Comment thread packages/ai-core/src/utils.ts
Comment thread packages/ai-core/src/utils.ts Outdated
Comment thread packages/ai-core/src/components/ToolCallInfo.tsx
Comment thread packages/ai-core/src/components/tools/ToolResult.tsx
Comment thread packages/ai-core/src/components/ToolCallInfo.tsx
Comment thread packages/ai-core/src/agents/AgentUtils.ts Outdated
Comment thread packages/ai-core/src/agents/AgentUtils.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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/ai-core/src/AiSlice.ts (1)

600-610: ⚠️ Potential issue | 🟡 Minor

Missing cleanup for sessionAddToolApprovalResponses in deleteSession.

The deleteSession method cleans up sessionAddToolOutputs but doesn't clean up the new sessionAddToolApprovalResponses Map, which could cause a memory leak for approval response handlers.

🛠️ Proposed fix
         sessionChatStops.delete(sessionId);
         sessionChatSendMessages.delete(sessionId);
         sessionAddToolOutputs.delete(sessionId);
+        sessionAddToolApprovalResponses.delete(sessionId);
         const now = Date.now();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/AiSlice.ts` around lines 600 - 610, deleteSession
currently clears several per-session maps but misses removing entries from
sessionAddToolApprovalResponses, causing potential memory leaks; update the
deleteSession method to also call
sessionAddToolApprovalResponses.delete(sessionId) (or clear the map entry)
alongside sessionAddToolOutputs.delete(sessionId) and the other
sessionXXX.delete(sessionId) calls so all per-session handlers are cleaned up
when deleteSession runs.
🧹 Nitpick comments (4)
packages/ai-core/src/components/ToolPartRenderer.tsx (1)

183-188: Remove unused isCompleted prop.

As noted in ToolCallInfo.tsx, the isCompleted prop is no longer used. Consider removing it from this call site.

♻️ Proposed fix
         <ToolCallInfo
           toolName={toolName}
           input={input}
-          isCompleted={isCompleted}
           state={state}
         />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/components/ToolPartRenderer.tsx` around lines 183 - 188,
Remove the now-unused isCompleted prop from the ToolCallInfo invocation in
ToolPartRenderer: update the JSX that renders <ToolCallInfo ... /> by deleting
the isCompleted={isCompleted} prop so the component is called with only
toolName, input, and state; verify ToolCallInfo props type (in ToolCallInfo.tsx)
matches and run type checks to ensure no other references to isCompleted remain
in ToolPartRenderer.
examples/ai-nextjs/src/app/api/chat/route.ts (1)

11-18: Consider validating request payload.

The route destructures the request body without validation. While the defaults handle missing values, invalid types (e.g., non-number maxSteps) could cause unexpected behavior. Consider adding Zod validation for the incoming payload.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/ai-nextjs/src/app/api/chat/route.ts` around lines 11 - 18, Add a Zod
schema and validate the parsed body immediately after the await req.json() call
in the API route handler in route.ts: define a schema for messages,
modelProvider, model, instructions, maxSteps (number), temperature (number) with
appropriate defaults/required flags, parse/parseAsync the incoming payload, and
if validation fails return a 400 response with the error details; then use the
validated/parsed values (instead of raw destructuring) so downstream logic
(e.g., any function expecting numeric maxSteps or temperature) receives correct
types.
packages/ai-core/src/components/ToolCallInfo.tsx (1)

13-25: Remove unused isCompleted prop from type definition.

The isCompleted prop is declared in ToolCallInfoProps (line 16) but is not destructured or used in the component (lines 40-43). The completion state is now derived directly from the state prop (line 51). While ToolPartRenderer.tsx still passes isCompleted={isCompleted} (line 186), this prop is ignored.

♻️ Proposed fix to remove unused prop
 type ToolCallInfoProps = {
   toolName: string;
   input: unknown;
-  isCompleted: boolean;
   state:
     | 'input-streaming'
     | 'input-available'
     | 'output-available'
     | 'output-error'
     | 'approval-requested'
     | 'approval-responded'
     | 'output-denied';
 };

Also update the JSDoc at lines 36-37 to remove the @param props.isCompleted line, and remove the prop from ToolPartRenderer.tsx line 186.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/components/ToolCallInfo.tsx` around lines 13 - 25,
ToolCallInfoProps declares an unused isCompleted prop — remove the isCompleted
field from the ToolCallInfoProps type declaration and update the ToolCallInfo
component JSDoc to delete the `@param` props.isCompleted entry; then remove the
isCompleted={isCompleted} prop passed from ToolPartRenderer (so ToolPartRenderer
no longer forwards that unused prop). Ensure you only change the type, JSDoc,
and the prop usage (references: ToolCallInfoProps, isCompleted,
ToolPartRenderer) so the component derives completion from the existing state
prop.
packages/ai-core/src/agents/AgentUtils.ts (1)

73-114: Consider returning tool call state alongside final text.

The streamSubAgent function maintains toolEditState internally but only returns finalText. If callers need visibility into tool call progress (e.g., for logging or debugging), consider returning both:

return { text: finalText, toolCalls: toolEditState };

This is optional since the current API may be intentionally minimal for the sub-agent use case.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/agents/AgentUtils.ts` around lines 73 - 114,
streamSubAgent currently accumulates tool call state in toolEditState but only
returns finalText; change streamSubAgent to return both the text and the tool
call state (e.g., { text: string, toolCalls: Map<string,AgentToolCall> }) by
updating the function return type and final return value, preserve building
toolEditState inside the function, and update all callers of streamSubAgent (and
any type annotations) to handle the new object shape so callers can access
toolCalls for logging/debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ai-core/src/hooks/useSessionChat.ts`:
- Around line 107-108: Delete the unused ref declaration and assignment for
addToolOutputRef: remove the const addToolOutputRef =
useRef<AddToolOutput>(null!) declaration and any subsequent assignment to
addToolOutputRef, since addToolOutput is already registered with the store (the
addToolOutput function is used directly) and the ref is redundant; ensure any
imports (e.g., useRef) that become unused are cleaned up.

In `@packages/ai-core/src/utils.ts`:
- Around line 308-349: The tail tool-detection in shouldEndAnalysis currently
only checks part.type and can miss tool parts that are waiting for approval;
update the tailHasTool predicate inside shouldEndAnalysis to also treat a tool
part as pending when its state === 'approval-requested' (e.g., check part.state
=== 'approval-requested' alongside type checks), mirroring the pattern used in
fixIncompleteToolCalls; ensure this integrates with the existing use of
lastAssistantMessageIsCompleteWithToolCalls and keep behavior consistent with
lastAssistantMessageIsCompleteWithApprovalResponses for approval flows.

---

Outside diff comments:
In `@packages/ai-core/src/AiSlice.ts`:
- Around line 600-610: deleteSession currently clears several per-session maps
but misses removing entries from sessionAddToolApprovalResponses, causing
potential memory leaks; update the deleteSession method to also call
sessionAddToolApprovalResponses.delete(sessionId) (or clear the map entry)
alongside sessionAddToolOutputs.delete(sessionId) and the other
sessionXXX.delete(sessionId) calls so all per-session handlers are cleaned up
when deleteSession runs.

---

Nitpick comments:
In `@examples/ai-nextjs/src/app/api/chat/route.ts`:
- Around line 11-18: Add a Zod schema and validate the parsed body immediately
after the await req.json() call in the API route handler in route.ts: define a
schema for messages, modelProvider, model, instructions, maxSteps (number),
temperature (number) with appropriate defaults/required flags, parse/parseAsync
the incoming payload, and if validation fails return a 400 response with the
error details; then use the validated/parsed values (instead of raw
destructuring) so downstream logic (e.g., any function expecting numeric
maxSteps or temperature) receives correct types.

In `@packages/ai-core/src/agents/AgentUtils.ts`:
- Around line 73-114: streamSubAgent currently accumulates tool call state in
toolEditState but only returns finalText; change streamSubAgent to return both
the text and the tool call state (e.g., { text: string, toolCalls:
Map<string,AgentToolCall> }) by updating the function return type and final
return value, preserve building toolEditState inside the function, and update
all callers of streamSubAgent (and any type annotations) to handle the new
object shape so callers can access toolCalls for logging/debugging.

In `@packages/ai-core/src/components/ToolCallInfo.tsx`:
- Around line 13-25: ToolCallInfoProps declares an unused isCompleted prop —
remove the isCompleted field from the ToolCallInfoProps type declaration and
update the ToolCallInfo component JSDoc to delete the `@param` props.isCompleted
entry; then remove the isCompleted={isCompleted} prop passed from
ToolPartRenderer (so ToolPartRenderer no longer forwards that unused prop).
Ensure you only change the type, JSDoc, and the prop usage (references:
ToolCallInfoProps, isCompleted, ToolPartRenderer) so the component derives
completion from the existing state prop.

In `@packages/ai-core/src/components/ToolPartRenderer.tsx`:
- Around line 183-188: Remove the now-unused isCompleted prop from the
ToolCallInfo invocation in ToolPartRenderer: update the JSX that renders
<ToolCallInfo ... /> by deleting the isCompleted={isCompleted} prop so the
component is called with only toolName, input, and state; verify ToolCallInfo
props type (in ToolCallInfo.tsx) matches and run type checks to ensure no other
references to isCompleted remain in ToolPartRenderer.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1d32e015-3c6e-4248-a664-355e233d5a64

📥 Commits

Reviewing files that changed from the base of the PR and between 1bf099a and 973019c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (32)
  • docs/upgrade-guide.md
  • examples/ai-agent/package.json
  • examples/ai-agent/src/agents/WeatherAgent.ts
  • examples/ai-core/package.json
  • examples/ai-nextjs/package.json
  • examples/ai-nextjs/src/app/api/chat/route.ts
  • examples/ai-rag/package.json
  • examples/ai/package.json
  • examples/app-builder/package.json
  • packages/ai-config/src/index.ts
  • packages/ai-config/src/schema/UIMessageSchema.ts
  • packages/ai-core/README.md
  • packages/ai-core/package.json
  • packages/ai-core/src/AiSlice.ts
  • packages/ai-core/src/agents/AgentUtils.ts
  • packages/ai-core/src/chatTransport.ts
  • packages/ai-core/src/components/ToolCallInfo.tsx
  • packages/ai-core/src/components/ToolPartRenderer.tsx
  • packages/ai-core/src/components/tools/ToolResult.tsx
  • packages/ai-core/src/hooks/useAssistantMessageParts.ts
  • packages/ai-core/src/hooks/useSessionChat.ts
  • packages/ai-core/src/index.ts
  • packages/ai-core/src/types.ts
  • packages/ai-core/src/utils.ts
  • packages/ai-rag/package.json
  • packages/ai-rag/src/createRagTool.tsx
  • packages/ai/package.json
  • packages/ai/src/index.ts
  • packages/ai/src/tools/query/queryTool.ts
  • packages/mosaic/package.json
  • packages/vega/package.json
  • packages/vega/src/VegaChartTool.tsx

Comment thread packages/ai-core/src/hooks/useSessionChat.ts Outdated
Comment thread packages/ai-core/src/utils.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/ai-core/src/AiSlice.ts (3)

214-214: ⚠️ Potential issue | 🟠 Major

getMaxStepsFromSettings() currently masks the settings value.

Because maxSteps is defaulted to 50 at Line 214, the first branch here always wins when the caller does not pass an override. That makes aiSettings.config.modelParameters.maxSteps unreachable, so the new agent loop ignores the user-configured limit.

🔧 Minimal fix
-    maxSteps = 50,
+    maxSteps,
...
         getMaxStepsFromSettings: () => {
           const store = get();
           // First try the maxSteps parameter if provided
-          if (maxSteps && Number.isFinite(maxSteps) && maxSteps > 0) {
+          if (
+            maxSteps !== undefined &&
+            Number.isFinite(maxSteps) &&
+            maxSteps > 0
+          ) {
             return maxSteps;
           }

           // Fall back to settings
           if (hasAiSettingsConfig(store)) {
             const settingsMaxSteps =
               store.aiSettings.config.modelParameters.maxSteps;
             if (Number.isFinite(settingsMaxSteps) && settingsMaxSteps > 0) {
               return settingsMaxSteps;
             }
           }
           return 50;
         },

Also applies to: 739-754

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/AiSlice.ts` at line 214, The function
getMaxStepsFromSettings currently sets its parameter maxSteps = 50 which causes
the first branch to always win and ignores
aiSettings.config.modelParameters.maxSteps; change the parameter so it does not
default to 50 (e.g. accept undefined/null) and implement a proper fallback: if
an explicit maxSteps argument is provided use it, otherwise read
aiSettings.config.modelParameters.maxSteps (and if that is missing use 50 as the
final default). Update getMaxStepsFromSettings and any other occurrences (same
pattern around the block handling lines ~739-754) to follow this precedence:
explicit arg -> aiSettings.config.modelParameters.maxSteps -> 50.

651-674: ⚠️ Potential issue | 🟡 Minor

Don’t report a successful UI-message save when nothing was written.

If the session lookup misses, this still returns true even though no uiMessages were persisted. The transport callers in packages/ai-core/src/chatTransport.ts at Line 236 and Line 290 currently ignore the boolean, so this failure mode stays silent and makes the new contract unreliable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/AiSlice.ts` around lines 651 - 674, setSessionUiMessages
currently returns true even when no session is found and nothing is written;
update the implementation of setSessionUiMessages to detect whether a matching
session was located and only return true when uiMessages were actually
persisted. Specifically, locate the session lookup in the produce callback (the
draft.ai.config.sessions.find call inside setSessionUiMessages) and add a
boolean flag (e.g., "updated") that is set to true when session.uiMessages is
assigned; call set(...) only when necessary or run it but return the flag value
(false if no session matched). Ensure the function still catches errors and
returns false on exceptions but does not report success when no session was
modified.

603-613: ⚠️ Potential issue | 🟡 Minor

Clean up sessionAddToolApprovalResponses on session deletion.

The new approval-response map is the only per-session callback store not cleared in deleteSession(). That keeps a stale closure alive after the session is gone and makes teardown inconsistent with the other session-scoped callbacks.

🧹 Minimal fix
           sessionAbortControllers.delete(sessionId);
           sessionChatStops.delete(sessionId);
           sessionChatSendMessages.delete(sessionId);
           sessionAddToolOutputs.delete(sessionId);
+          sessionAddToolApprovalResponses.delete(sessionId);
           const now = Date.now();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/AiSlice.ts` around lines 603 - 613, deleteSession
currently fails to remove the per-session approval-response map, leaving
sessionAddToolApprovalResponses entries and closures alive; update the
deleteSession implementation to mirror the other per-session cleanup
(sessionChatStops, sessionChatSendMessages, etc.) by calling
sessionAddToolApprovalResponses.delete(sessionId) when a session is deleted so
the approval-response callbacks are released.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/ai-core/src/AiSlice.ts`:
- Line 214: The function getMaxStepsFromSettings currently sets its parameter
maxSteps = 50 which causes the first branch to always win and ignores
aiSettings.config.modelParameters.maxSteps; change the parameter so it does not
default to 50 (e.g. accept undefined/null) and implement a proper fallback: if
an explicit maxSteps argument is provided use it, otherwise read
aiSettings.config.modelParameters.maxSteps (and if that is missing use 50 as the
final default). Update getMaxStepsFromSettings and any other occurrences (same
pattern around the block handling lines ~739-754) to follow this precedence:
explicit arg -> aiSettings.config.modelParameters.maxSteps -> 50.
- Around line 651-674: setSessionUiMessages currently returns true even when no
session is found and nothing is written; update the implementation of
setSessionUiMessages to detect whether a matching session was located and only
return true when uiMessages were actually persisted. Specifically, locate the
session lookup in the produce callback (the draft.ai.config.sessions.find call
inside setSessionUiMessages) and add a boolean flag (e.g., "updated") that is
set to true when session.uiMessages is assigned; call set(...) only when
necessary or run it but return the flag value (false if no session matched).
Ensure the function still catches errors and returns false on exceptions but
does not report success when no session was modified.
- Around line 603-613: deleteSession currently fails to remove the per-session
approval-response map, leaving sessionAddToolApprovalResponses entries and
closures alive; update the deleteSession implementation to mirror the other
per-session cleanup (sessionChatStops, sessionChatSendMessages, etc.) by calling
sessionAddToolApprovalResponses.delete(sessionId) when a session is deleted so
the approval-response callbacks are released.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59d83cef-596e-42f9-ac76-56b19433be53

📥 Commits

Reviewing files that changed from the base of the PR and between 973019c and 4a518f5.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • docs/upgrade-guide.md
  • packages/ai-core/README.md
  • packages/ai-core/src/AiSlice.ts
  • packages/ai-core/src/types.ts
  • packages/pivot/src/pivotExecution.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/ai-core/README.md
  • packages/pivot/src/pivotExecution.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/upgrade-guide.md

…packages

fix: enhance security in POST request handling and improve state management in components
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/ai-core/src/AiSlice.ts (1)

603-613: ⚠️ Potential issue | 🟡 Minor

Clear reverse tool-call mappings during session teardown.

This cleanup removes the session-keyed callbacks, but any toolCallToSessionId entries that still point at sessionId survive. Late tool-stream events can still resolve the deleted session, and the map will grow monotonically over time.

🧹 Proposed fix
           sessionChatSendMessages.delete(sessionId);
           sessionAddToolOutputs.delete(sessionId);
           sessionAddToolApprovalResponses.delete(sessionId);
+          for (const [toolCallId, mappedSessionId] of toolCallToSessionId) {
+            if (mappedSessionId === sessionId) {
+              toolCallToSessionId.delete(toolCallId);
+            }
+          }
           const now = Date.now();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/AiSlice.ts` around lines 603 - 613, The deleteSession
function currently removes per-session state but leaves entries in
toolCallToSessionId that still map toolCallIds to the deleted sessionId; update
deleteSession to scan the toolCallToSessionId map (or use an index) and delete
any entries whose value === sessionId so late tool-stream events cannot resolve
the removed session and the map does not leak; locate the deleteSession
implementation and remove matching keys from toolCallToSessionId for the given
sessionId.
🧹 Nitpick comments (1)
packages/ai-core/src/components/ToolPartRenderer.tsx (1)

132-145: Use the same ToolComponent predicate for branching and rendering.

The new approval path activates on any truthy ToolComponent, but the JSX below still renders only plain function components. A memoized or forwardRef renderer will therefore enter this branch and return an empty wrapper, which hides the approval UI. Please align those checks, or type the registry as a React component map and render directly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-core/src/components/ToolPartRenderer.tsx` around lines 132 - 145,
The conditional that chooses to return the approval/UI wrapper uses a looser
predicate (checking ToolComponent truthiness) than the JSX renderer (which only
renders when ToolComponent is a plain function), causing memoized/forwardRef
components to be skipped; update the branch to use the same predicate as
rendering (or vice-versa) so both use an identical check for renderability —
e.g., ensure the if condition mirrors the JSX guard that checks ToolComponent &&
typeof ToolComponent === 'function' (or change both to
React.isValidElementType/explicit registry typing) when evaluating
isApprovalState and hasExecute in ToolPartRenderer (the conditional around
ToolComponent, isApprovalState, hasExecute and the JSX that renders
<ToolComponent/>).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ai-core/src/agents/AgentUtils.ts`:
- Around line 8-14: The AgentToolCall.type currently restricts state to
'pending' | 'success' | 'error', which omits the new approval-related states;
update the AgentToolCall definition (symbol: AgentToolCall and its state field)
to include 'approval-requested', 'approval-responded', and 'output-denied' in
the state union so tool renderers and approval flows type-check correctly and
handle these new statuses.
- Around line 98-108: The loop in AgentUtils.ts that consumes the streaming
response only appends 'text-delta' chunks and silently ignores
'tool-output-error' and 'tool-input-error' chunks; update the for-await loop
that processes "stream" (and uses throwIfAborted and finalText) to detect error
chunk types (e.g., 'tool-output-error', 'tool-input-error') and immediately
propagate them by throwing an Error (or rethrowing contained error payload)
including the tool error details so the caller sees sub-agent failures instead
of returning partial finalText; ensure the catch block continues to call
throwIfAborted before rethrowing.

In `@packages/ai-core/src/components/ToolCallInfo.tsx`:
- Around line 49-55: The JSX in ToolCallInfo currently treats
'approval-requested' like other in-progress states and renders Loader2
(spinner); change the conditional so 'approval-requested' is excluded from the
spinner branch and instead render a distinct, non-animating indicator for that
state (e.g., use a PauseIcon or a static CircleArrowRightIcon variant) so it
reads as “paused awaiting user action.” Update the conditional logic around the
state check in the ToolCallInfo component (the spots referencing state, Loader2,
and CircleArrowRightIcon) to add an explicit branch for 'approval-requested'
rendering the chosen static icon/class names and remove 'approval-requested'
from the spinner condition.

In `@packages/ai-core/src/hooks/useSessionChat.ts`:
- Around line 120-135: The current seeding of useChat (id, transport, messages:
initialMessages) is losing pending approval requests because
fixIncompleteToolCalls rewrites trailing "approval-requested" parts to
"output-error"; update the flow so approval-requested parts are preserved across
reloads—either by changing fixIncompleteToolCalls (in
packages/ai-core/src/utils.ts) to treat trailing parts with type
"approval-requested" as complete and leave them untouched, or by skipping
fixIncompleteToolCalls for messages that contain an "approval-requested" part
before passing initialMessages into useChat; ensure this touches the helper
fixIncompleteToolCalls and the call site that prepares initialMessages (the code
that seeds useChat) and keep lastAssistantMessageIsCompleteWithApprovalResponses
and isAbortedRef logic unchanged.

---

Outside diff comments:
In `@packages/ai-core/src/AiSlice.ts`:
- Around line 603-613: The deleteSession function currently removes per-session
state but leaves entries in toolCallToSessionId that still map toolCallIds to
the deleted sessionId; update deleteSession to scan the toolCallToSessionId map
(or use an index) and delete any entries whose value === sessionId so late
tool-stream events cannot resolve the removed session and the map does not leak;
locate the deleteSession implementation and remove matching keys from
toolCallToSessionId for the given sessionId.

---

Nitpick comments:
In `@packages/ai-core/src/components/ToolPartRenderer.tsx`:
- Around line 132-145: The conditional that chooses to return the approval/UI
wrapper uses a looser predicate (checking ToolComponent truthiness) than the JSX
renderer (which only renders when ToolComponent is a plain function), causing
memoized/forwardRef components to be skipped; update the branch to use the same
predicate as rendering (or vice-versa) so both use an identical check for
renderability — e.g., ensure the if condition mirrors the JSX guard that checks
ToolComponent && typeof ToolComponent === 'function' (or change both to
React.isValidElementType/explicit registry typing) when evaluating
isApprovalState and hasExecute in ToolPartRenderer (the conditional around
ToolComponent, isApprovalState, hasExecute and the JSX that renders
<ToolComponent/>).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: de031c0d-494d-4273-b23d-36251fd1acbb

📥 Commits

Reviewing files that changed from the base of the PR and between 4a518f5 and 0186900.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • examples/ai-agent/package.json
  • examples/ai-core/package.json
  • examples/ai-nextjs/package.json
  • examples/ai-nextjs/src/app/api/chat/route.ts
  • examples/ai-rag/package.json
  • examples/ai/package.json
  • packages/ai-core/package.json
  • packages/ai-core/src/AiSlice.ts
  • packages/ai-core/src/agents/AgentUtils.ts
  • packages/ai-core/src/components/ToolCallInfo.tsx
  • packages/ai-core/src/components/ToolPartRenderer.tsx
  • packages/ai-core/src/components/tools/ToolResult.tsx
  • packages/ai-core/src/hooks/useSessionChat.ts
  • packages/ai-core/src/utils.ts
  • packages/ai-rag/package.json
  • packages/ai/package.json
  • packages/vega/package.json
✅ Files skipped from review due to trivial changes (8)
  • packages/vega/package.json
  • examples/ai/package.json
  • packages/ai-rag/package.json
  • examples/ai-rag/package.json
  • examples/ai-core/package.json
  • examples/ai-nextjs/package.json
  • packages/ai-core/package.json
  • examples/ai-agent/package.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/ai/package.json
  • packages/ai-core/src/utils.ts
  • packages/ai-core/src/components/tools/ToolResult.tsx
  • examples/ai-nextjs/src/app/api/chat/route.ts

Comment thread packages/ai-core/src/agents/AgentUtils.ts Outdated
Comment thread packages/ai-core/src/agents/AgentUtils.ts Outdated
Comment thread packages/ai-core/src/components/ToolCallInfo.tsx Outdated
Comment thread packages/ai-core/src/hooks/useSessionChat.ts
@mihajlo-stojkovic mihajlo-stojkovic linked an issue Mar 27, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ai-core/src/agents/AgentUtils.ts`:
- Around line 94-104: Move the awaited createAgentUIStream call into the try
block and call throwIfAborted() immediately before awaiting it so pre-stream
aborts are normalized; specifically, inside the function where you currently
await createAgentUIStream(...) (creating the const stream), remove that await
from before the try, then inside the try call throwIfAborted() and then await
createAgentUIStream(...) to assign stream, so any abort during stream creation
is caught and converted to the ToolAbortError(TOOL_CALL_CANCELLED) handling
path.

In `@packages/ai-core/src/components/ToolPartRenderer.tsx`:
- Around line 132-137: The current ToolPartRenderer returns null when
isApprovalState is true but ToolComponent is missing, which silently hides
approval requests; change this to render a minimal fallback UI (e.g., an inline
ApprovalFallback) that visibly displays the toolName and the approval prompt and
wires into the existing approval handlers so the user can approve/deny; update
the branch that checks isApprovalState && !ToolComponent to return this fallback
element (or call a new renderApprovalFallback function/component) instead of
null and ensure it uses the same props/callback signatures as the real
ToolComponent so the agent loop can continue.

In `@packages/ai-core/src/hooks/useSessionChat.ts`:
- Around line 113-135: The sendAutomaticallyWhen callback only checks
lastAssistantMessageIsCompleteWithApprovalResponses so sessions stall when a
tool returns client-provided output via addToolOutput (no execute); import
lastAssistantMessageIsCompleteWithToolCalls and change sendAutomaticallyWhen to
return true when either
lastAssistantMessageIsCompleteWithApprovalResponses(options) OR
lastAssistantMessageIsCompleteWithToolCalls(options) is true (keeping the
existing isAbortedRef.current guard), so both approval-driven and
tool-output-driven auto-resubmits continue the chat.

In `@packages/ai-core/src/utils.ts`:
- Around line 398-402: The cleanup logic around toolPart state incorrectly
converts valid input-waiting states to 'output-error' when finishing normally;
update fixIncompleteToolCalls (and its callers such as the normal-finish path in
chatTransport.ts) to accept a flag like preserveInputStates or a mode ('abort'
vs 'finish') and, when in the normal finish mode, skip converting states that
start with 'input' (e.g. 'input-streaming', 'input-available') so tools awaiting
client addToolOutput remain unchanged; reference the isCompleted check and
ensure callers using useChat/createAgentUIStreamResponse pass the appropriate
mode so only abort/error flows perform aggressive cancellation.
🪄 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: 8d95a8c5-5ec5-421d-9f88-707e7ad2a4ea

📥 Commits

Reviewing files that changed from the base of the PR and between 1aeced5 and 2fb78a5.

📒 Files selected for processing (8)
  • docs/upgrade-guide.md
  • packages/ai-config/src/schema/UIMessageSchema.ts
  • packages/ai-core/src/AiSlice.ts
  • packages/ai-core/src/agents/AgentUtils.ts
  • packages/ai-core/src/chatTransport.ts
  • packages/ai-core/src/components/ToolPartRenderer.tsx
  • packages/ai-core/src/hooks/useSessionChat.ts
  • packages/ai-core/src/utils.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/upgrade-guide.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ai-core/src/AiSlice.ts

Comment thread packages/ai-core/src/agents/AgentUtils.ts Outdated
Comment thread packages/ai-core/src/components/ToolPartRenderer.tsx
Comment thread packages/ai-core/src/hooks/useSessionChat.ts
Comment thread packages/ai-core/src/utils.ts
@lixun910
Copy link
Copy Markdown
Collaborator

lixun910 commented Apr 7, 2026

  • render sub-tools within sub-agents
  • support needsApproval in sub-tools within sub-agents
Screenshot 2026-04-07 at 11 04 16 AM

@lixun910
Copy link
Copy Markdown
Collaborator

lixun910 commented Apr 9, 2026

Add token usage and summarization current session to a new session. Adjust the UI for nested agents/tools

Untitled.mp4

@lixun910 lixun910 merged commit bd17a5f into main Apr 16, 2026
3 checks passed
@lixun910 lixun910 deleted the feat/ai-sdk-v6 branch April 16, 2026 17:44
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.

Update Vercel AI SDK from v5 to v6 and fix breaking changes

4 participants