Skip to content

Conversation

@joaquim-verges
Copy link
Member

@joaquim-verges joaquim-verges commented Sep 1, 2025


PR-Codex overview

This PR focuses on enhancing the session management for chat interactions within the thirdwebAI SDK, allowing for automatic handling of session IDs and improving the conversation continuity without manual tracking.

Detailed summary

  • Updated API to use id instead of sessionId.
  • Introduced SessionStore class to manage session IDs.
  • Removed manual session ID handling in components.
  • Enhanced thirdwebAI.chat() to support automatic session management.
  • Improved client-side chat handling with automatic tool result sending.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Automatic session handling for continuous AI chats — clients no longer send session IDs; chats resume automatically and can be reset.
    • Provider now maintains per-chat session state with optional chat IDs and a public session API.
    • Tool results are delivered automatically to continue conversations without manual follow-ups.
  • Documentation

    • Updated AI SDK chat docs, links, and UI notes to reflect the id-based/automatic flow.
  • Chores

    • Added changeset for a patch release of the AI SDK provider.

@vercel
Copy link

vercel bot commented Sep 1, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
docs-v2 Ready Ready Preview Comment Sep 1, 2025 5:24am
nebula Ready Ready Preview Comment Sep 1, 2025 5:24am
thirdweb_playground Ready Ready Preview Comment Sep 1, 2025 5:24am
thirdweb-www Ready Ready Preview Comment Sep 1, 2025 5:24am
wallet-ui Ready Ready Preview Comment Sep 1, 2025 5:24am

@changeset-bot
Copy link

changeset-bot bot commented Sep 1, 2025

🦋 Changeset detected

Latest commit: 62565a4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@thirdweb-dev/ai-sdk-provider Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 1, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds provider-level per-chat session tracking and changes ThirdwebProvider.chat to accept an optional chat id. Client and server code remove manual sessionId handling in favor of automatic continuation (useChat sendAutomaticallyWhen + addToolResult); API endpoints now accept id instead of sessionId. Adds a changeset.

Changes

Cohort / File(s) Summary of changes
Release metadata
.changeset/pink-hands-find.md
Adds a patch changeset for @thirdweb-dev/ai-sdk-provider with note "Auto handle session ids".
Playground Web — AI chat UI
apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
Removes local sessionId state/propagation; switches useChat to sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls; sends user messages via sendMessage({ text }) without session payload; removes sessionId from SignTransactionButton/SignSwapButton props and handlers; addToolResult used for tool-result flow; error handlers send plain error text only.
Playground Web — Chat page
apps/playground-web/src/app/ai/ai-sdk/page.tsx
Removes sessionId state/onFinish and wrapper that forwarded sessionId; server POST handler reads { messages, id } and calls thirdwebAI.chat(id) (no context.session_id); client uses sendMessage directly and drops status from useChat return.
Playground Web — Chat API route
apps/playground-web/src/app/api/chat/route.ts
Request body now { messages, id }; calls thirdwebAI.chat(id) instead of contextual chat; removes context.session_id and the custom messageMetadata that emitted session_id; streaming and message conversion logic preserved.
Portal — AI SDK docs/example
apps/portal/src/app/ai/chat/ai-sdk/page.mdx
Updates docs/example to automatic session handling: replace sessionId with id; remove manual onFinish/send wrappers; retype RenderMessage to drop sessionId and accept addToolResult (UseChatHelpers type); document thirdwebAI.session.clearSessionId() for resets; remove follow-up message behavior for tool sign_transaction.
AI SDK Provider — Session support
packages/ai-sdk-provider/src/provider.ts
Adds an internal SessionStore and wires it into language model and provider flows; changes ThirdwebProvider.chat(settings)ThirdwebProvider.chat(id?, settings); ThirdwebLanguageModel now accepts sessionStore and optional chatId, persists/reads session_id to/from the store, generates chat ids, always includes context.session_id from the store, and updates the store from streaming SSE init events; adds helpers getSessionId, setSessionId, clearSessionId, and generateRandomChatId; streaming path sets session id from SSE init event.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as Chat UI (useChat)
  participant Auto as sendAutomaticallyWhen / addToolResult
  participant SDK as thirdwebAI.chat(id)
  participant Provider as ThirdwebProvider (SessionStore)
  participant Backend as Backend (SSE)

  Note over UI,Auto: Automatic continuation via lastAssistantMessageIsCompleteWithToolCalls
  UI->>SDK: sendMessage({ text })
  SDK->>Provider: instantiate model (chatId = id or generated)
  Provider->>Provider: context.session_id = SessionStore.get(chatId)
  Provider->>Backend: POST chat (includes session_id)
  Backend-->>Provider: SSE init { session_id }
  Provider->>Provider: SessionStore.set(chatId, session_id)
  Backend-->>Provider: SSE tokens / tool call events
  Provider-->>UI: Streamed assistant message / tool call events

  alt Tool call required
    UI->>Auto: addToolResult(toolResult)
    Auto->>SDK: auto-continue with tool result
    SDK->>Provider: reuse chatId and context.session_id
    Provider->>Backend: POST chat (continues session)
    Backend-->>Provider: SSE stream (follow-up)
    Provider-->>UI: Streamed assistant continuation
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch _AI_SDK_Provider_Auto_handle_session_ids

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added Playground Changes involving the Playground codebase. Portal Involves changes to the Portal (docs) codebase. packages labels Sep 1, 2025
Copy link
Member Author


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codecov
Copy link

codecov bot commented Sep 1, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.52%. Comparing base (89eeac1) to head (62565a4).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7956      +/-   ##
==========================================
- Coverage   56.53%   56.52%   -0.02%     
==========================================
  Files         904      904              
  Lines       58623    58623              
  Branches     4146     4146              
==========================================
- Hits        33144    33138       -6     
- Misses      25373    25380       +7     
+ Partials      106      105       -1     
Flag Coverage Δ
packages 56.52% <ø> (-0.02%) ⬇️
see 2 files with indirect coverage changes
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 1, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 64.01 KB (0%) 1.3 s (0%) 219 ms (+169.37% 🔺) 1.5 s
thirdweb (cjs) 357.32 KB (0%) 7.2 s (0%) 673 ms (+9.86% 🔺) 7.9 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 94 ms (+2159.23% 🔺) 209 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 60 ms (+4059.73% 🔺) 71 ms
thirdweb/react (minimal + tree-shaking) 19.15 KB (0%) 383 ms (0%) 70 ms (+509.91% 🔺) 453 ms

Copy link
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: 5

Caution

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

⚠️ Outside diff range comments (1)
apps/portal/src/app/ai/chat/ai-sdk/page.mdx (1)

120-171: Close the switch and map blocks properly.

There’s a missing closing brace for the switch (and consequently the .map callback).

       default:
         return null;
-      })}
+        }
+      })}

Also consider removing the unused i param from map:

-      {message.parts.map((part, i) => {
+      {message.parts.map((part) => {
🧹 Nitpick comments (7)
packages/ai-sdk-provider/src/provider.ts (4)

73-79: Consider adding null checks for defensive programming.

While the current implementation should work, adding defensive checks would make the code more robust.

Apply this diff for safer session handling:

private getSessionId() {
-  return this.sessionStore.getSessionId(this.chatId);
+  return this.sessionStore?.getSessionId(this.chatId) ?? null;
}

private setSessionId(sessionId: string) {
+  if (!sessionId || !this.sessionStore) return;
  this.sessionStore.setSessionId(this.chatId, sessionId);
}

81-101: Security consideration for the fallback ID generation.

The fallback random ID generation using Math.random() is not cryptographically secure. While this is likely acceptable for chat IDs, consider documenting this limitation.

Consider adding a comment about the security implications:

private generateRandomChatId(): string {
  // Use crypto.randomUUID if available (modern browsers and Node.js 14.17+)
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
    return crypto.randomUUID();
  }

-  // Fallback for older environments - generate a random string
+  // Fallback for older environments - generate a random string
+  // Note: This uses Math.random() which is not cryptographically secure
+  // but is acceptable for chat session IDs
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

579-593: Add JSDoc documentation for the SessionStore class.

The SessionStore class is a key component but lacks documentation. Consider adding JSDoc comments to explain its purpose and methods.

+/**
+ * Manages session IDs for multiple chat conversations.
+ * Each chat is identified by a unique chatId and can have an associated sessionId.
+ */
class SessionStore {
  private sessionId: Map<string, string> = new Map();

+  /**
+   * Retrieves the session ID for a given chat.
+   * @param chatId - The unique identifier for the chat
+   * @returns The session ID or null if not found
+   */
  getSessionId(chatId: string) {
    return this.sessionId.get(chatId) || null;
  }

+  /**
+   * Sets the session ID for a given chat.
+   * @param chatId - The unique identifier for the chat
+   * @param sessionId - The session ID to associate with the chat
+   */
  setSessionId(chatId: string, sessionId: string) {
    this.sessionId.set(chatId, sessionId);
  }

+  /**
+   * Removes the session ID for a given chat.
+   * @param chatId - The unique identifier for the chat
+   */
  clearSessionId(chatId: string) {
    this.sessionId.delete(chatId);
  }
}

545-553: Consider adding TypeScript return type annotation.

The chat method should have an explicit return type for better type safety.

-chat(id?: string, settings: ThirdwebSettings = {}) {
+chat(id?: string, settings: ThirdwebSettings = {}): ThirdwebLanguageModel {
  return new ThirdwebLanguageModel(
    "t0-latest",
    settings,
    this.config,
    this.session,
    id,
  );
}
apps/portal/src/app/ai/chat/ai-sdk/page.mdx (3)

41-41: Consider backward compatibility for id/sessionId.

If any existing clients still post sessionId, read both and prefer id to avoid breaking older UIs.

-  const { messages, id } = await req.json();
+  const { messages, id, sessionId } = await req.json();

And pass the resolved value:

-    model: thirdwebAI.chat(id, {
+    model: thirdwebAI.chat(id ?? sessionId, {

84-87: Nit: wording and robustness.

  • Prefer “Vercel AI Elements” (proper case).
  • Avoid implying parts[0]; tool parts can appear in any index—“when a tool part arrives (iterate message.parts) …”.
-// Use your own UI or the vercel ai elements UI components
-// When a tool part arrives (e.g., message.parts[0].type === "tool-sign_transaction"),
+// Use your own UI or the Vercel AI Elements UI components
+// When a tool part arrives (iterate message.parts and check part.type === "tool-sign_transaction"),

155-157: Surface tool execution failures to the model (optional).

Beyond logging, consider sending an error tool result so the assistant can recover gracefully (e.g., suggest retries or alternatives).

-                onError={(error) => {
-                  // in case of error, show error UI or send the error message to the model
-                 console.error(error);
-                }}
+                onError={(error) => {
+                  console.error(error);
+                  // Optionally, send an error tool result back to the model to continue the convo
+                  addToolResult({
+                    tool: "sign_transaction",
+                    toolCallId: part.toolCallId,
+                    output: { error: String(error?.message ?? error) },
+                  });
+                }}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 596aaa5 and 1933c3f.

📒 Files selected for processing (6)
  • .changeset/pink-hands-find.md (1 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (6 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx (2 hunks)
  • apps/playground-web/src/app/api/chat/route.ts (1 hunks)
  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx (5 hunks)
  • packages/ai-sdk-provider/src/provider.ts (8 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

.changeset/*.md: Each change in packages/* must include a changeset for the appropriate package
Version bump rules: patch for non‑API changes; minor for new/modified public API

Files:

  • .changeset/pink-hands-find.md
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/api/chat/route.ts
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
  • packages/ai-sdk-provider/src/provider.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/api/chat/route.ts
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
  • packages/ai-sdk-provider/src/provider.ts
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/api/chat/route.ts
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
🧠 Learnings (1)
📚 Learning: 2025-08-28T20:33:35.123Z
Learnt from: joaquim-verges
PR: thirdweb-dev/js#7922
File: packages/ai-sdk-provider/README.md:92-101
Timestamp: 2025-08-28T20:33:35.123Z
Learning: The Vercel AI SDK's DefaultChatTransport uses `body` (not `data`) for the transport payload when calling sendMessage with additional data like sessionId.

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
🧬 Code graph analysis (1)
packages/ai-sdk-provider/src/provider.ts (1)
packages/ai-sdk-provider/src/types.ts (2)
  • ThirdwebSettings (31-50)
  • ThirdwebConfig (12-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Size
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (16)
.changeset/pink-hands-find.md (1)

1-5: LGTM!

The changeset correctly documents this as a patch release for the AI SDK provider package, which is appropriate for internal implementation improvements that don't break the public API.

apps/playground-web/src/app/api/chat/route.ts (1)

17-17: LGTM! Clean implementation of the chat method.

The simplified API with thirdwebAI.chat(id) is much cleaner than the previous session context approach.

apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (2)

5-8: LGTM! Good use of AI SDK's automatic continuation.

Using lastAssistantMessageIsCompleteWithToolCalls for automatic message sending is the correct approach for handling tool results automatically.


37-43: Ensure sendAutomaticallyWhen does not trigger unintended messages
No other occurrences of sendAutomaticallyWhen were found in the repo; review the logic in lastAssistantMessageIsCompleteWithToolCalls and add tests for edge cases to prevent unexpected automatic sends.

packages/ai-sdk-provider/src/provider.ts (3)

29-46: LGTM! Well-structured session management initialization.

The session store integration and initial session ID handling are implemented correctly.


258-258: Good use of self reference for async callback context.

Using const self = this to maintain the correct context in the async stream handler is a good pattern.


397-397: LGTM! Session ID correctly updated from stream.

The session ID is properly extracted from the init event and stored via the self reference.

apps/playground-web/src/app/ai/ai-sdk/page.tsx (2)

32-32: LGTM! Documentation link updated correctly.

The docs link has been properly updated to point to the AI SDK chat documentation.


114-127: LGTM! Client code example simplified.

The removal of session management from the client code example makes it cleaner and easier to understand.

apps/portal/src/app/ai/chat/ai-sdk/page.mdx (7)

44-50: Model invocation looks correct.

Passing id into thirdwebAI.chat(id, ...) aligns with the new provider API.


61-62: Verify the API name for resetting sessions.

Please confirm the method is thirdwebAI.session.clearSessionId() (and not a different name like reset() or clear()), and whether it’s server-only. If the public API differs, update the docs accordingly.


71-73: Confirm helper export name and source.

Double-check that lastAssistantMessageIsCompleteWithToolCalls is the current helper name and exported from ai (not a renamed helper in your installed AI SDK version).


79-81: Good: automatic tool-result continuation.

Using sendAutomaticallyWhen with the “complete with tool calls” predicate is the right pattern here.


90-94: Passing addToolResult down is correct.

Stable key={message.id} is also good.


96-96: Confirm ChatInputBox prop name.

Ensure your ChatInputBox component expects send (not onSend/onSubmit).


144-148: Correct use of toolCallId.

Echoing back tool and toolCallId is required for continuation. Looks good.

Copy link
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: 0

Caution

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

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

188-197: Persist session_id for non-streamed calls.

Without storing data.session_id, follow-up calls won’t continue the session. Save it when present.

     const data = (await response.json()) as {
       message?: string;
       request_id?: string;
       session_id?: string;
       actions?: unknown[];
     };
 
-    // TODO (ai): handle actions
+    // persist session for subsequent turns
+    if (data.session_id) {
+      this.setSessionId(data.session_id);
+    }
+
+    // TODO (ai): handle actions

470-477: Emit structured tool input (not JSON string).

AI SDK tool calls expect structured input; stringifying breaks downstream consumers (e.g. UI reading part.input.chain_id).

                           controller.enqueue({
                             type: "tool-call",
                             toolCallId,
                             toolName,
-                            input: JSON.stringify(input),
+                            input,
                             providerExecuted: false,
                           });

398-401: Use request_id for response-metadata.id and include session_id under providerMetadata.

Vercel AI SDK’s response-metadata only supports id, model (or modelId), timestamp, headers, and a top-level providerMetadata object—there is no metadata field. Update the enqueue call accordingly:

- controller.enqueue({
-   type: "response-metadata",
-   id: parsed.session_id || "",
- });
+ controller.enqueue({
+   type: "response-metadata",
+   id: parsed.request_id ?? "",
+   providerMetadata: {
+     // replace PROVIDER_NAME with your provider’s name constant
+     [PROVIDER_NAME]: { session_id: parsed.session_id },
+   },
+ });
♻️ Duplicate comments (2)
apps/portal/src/app/ai/chat/ai-sdk/page.mdx (2)

98-100: Remove stray semicolon after JSX.

This breaks compilation: );;);.

-  );;
+  );

115-121: Fix RenderMessage props typing and destructure.

Use UseChatHelpers for the prop type and remove undeclared sendMessage.

 export function RenderMessage(props: {
   message: ThirdwebAiMessage;
-  addToolResult: ReturnType<typeof useChat<ThirdwebAiMessage>>["addToolResult"];
+  addToolResult: UseChatHelpers<ThirdwebAiMessage>["addToolResult"];
 }) {
-  const { message, addToolResult, sendMessage } = props;
+  const { message, addToolResult } = props;

Add missing import (outside this hunk):

import type { UseChatHelpers } from "@ai-sdk/react";
🧹 Nitpick comments (4)
packages/ai-sdk-provider/src/provider.ts (4)

73-80: Add explicit return types per TS guidelines.

-  private getSessionId() {
+  private getSessionId(): string | null {
     return this.sessionStore.getSessionId(this.chatId);
   }
 
-  private setSessionId(sessionId: string) {
+  private setSessionId(sessionId: string): void {
     this.sessionStore.setSessionId(this.chatId, sessionId);
   }

81-101: Harden chat id generation and typing.

Use globalThis.crypto?.randomUUID() and a stronger fallback (getRandomValues) to avoid relying on Math.random.

-  private generateRandomChatId(): string {
-    // Use crypto.randomUUID if available (modern browsers and Node.js 14.17+)
-    if (typeof crypto !== "undefined" && crypto.randomUUID) {
-      return crypto.randomUUID();
-    }
+  private generateRandomChatId(): string {
+    // Prefer Web Crypto
+    if (typeof globalThis !== "undefined" && globalThis.crypto?.randomUUID) {
+      return globalThis.crypto.randomUUID();
+    }
 
-    // Fallback for older environments - generate a random string
-    const chars =
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-    let result = "";
-
-    // Generate timestamp prefix for uniqueness
-    const timestamp = Date.now().toString(36);
-
-    // Add random suffix
-    for (let i = 0; i < 8; i++) {
-      result += chars.charAt(Math.floor(Math.random() * chars.length));
-    }
-
-    return `chat_${timestamp}_${result}`;
+    // Fallback: timestamp + random bytes (if available) else Math.random
+    const timestamp = Date.now().toString(36);
+    let suffix = "";
+    if (globalThis.crypto?.getRandomValues) {
+      const bytes = new Uint8Array(8);
+      globalThis.crypto.getRandomValues(bytes);
+      suffix = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
+    } else {
+      suffix = Math.random().toString(36).slice(2, 10);
+    }
+    return `chat_${timestamp}_${suffix}`;
   }

545-566: Type explicit return types on provider methods.

-  chat(id?: string, settings: ThirdwebSettings = {}) {
+  chat(id?: string, settings: ThirdwebSettings = {}): LanguageModelV2 {
     return new ThirdwebLanguageModel(
       "t0-latest",
       settings,
       this.config,
       this.session,
       id,
     );
   }
@@
-  tools() {
+  tools(): ReturnType<typeof createTools> {
     return createTools(this.config);
   }
@@
-  languageModel(modelId: string, settings: ThirdwebSettings = {}) {
+  languageModel(modelId: string, settings: ThirdwebSettings = {}): LanguageModelV2 {
     return new ThirdwebLanguageModel(
       modelId,
       settings,
       this.config,
       this.session,
     );
   }

579-593: Type SessionStore methods explicitly.

 class SessionStore {
   private sessionId: Map<string, string> = new Map();
 
-  getSessionId(chatId: string) {
+  getSessionId(chatId: string): string | null {
     return this.sessionId.get(chatId) || null;
   }
 
-  setSessionId(chatId: string, sessionId: string) {
+  setSessionId(chatId: string, sessionId: string): void {
     this.sessionId.set(chatId, sessionId);
   }
 
-  clearSessionId(chatId: string) {
+  clearSessionId(chatId: string): void {
     this.sessionId.delete(chatId);
   }
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2f0b0c6 and 66b6143.

📒 Files selected for processing (6)
  • .changeset/pink-hands-find.md (1 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (6 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx (3 hunks)
  • apps/playground-web/src/app/api/chat/route.ts (1 hunks)
  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx (5 hunks)
  • packages/ai-sdk-provider/src/provider.ts (8 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .changeset/pink-hands-find.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/playground-web/src/app/api/chat/route.ts
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • packages/ai-sdk-provider/src/provider.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • packages/ai-sdk-provider/src/provider.ts
🧠 Learnings (4)
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Write idiomatic TypeScript with explicit function declarations and return types

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to **/*.{ts,tsx} : Use explicit function declarations and explicit return types in TypeScript

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
📚 Learning: 2025-08-28T20:33:35.123Z
Learnt from: joaquim-verges
PR: thirdweb-dev/js#7922
File: packages/ai-sdk-provider/README.md:92-101
Timestamp: 2025-08-28T20:33:35.123Z
Learning: The Vercel AI SDK's DefaultChatTransport uses `body` (not `data`) for the transport payload when calling sendMessage with additional data like sessionId.

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
🧬 Code graph analysis (1)
packages/ai-sdk-provider/src/provider.ts (1)
packages/ai-sdk-provider/src/types.ts (2)
  • ThirdwebSettings (31-50)
  • ThirdwebConfig (12-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)

Copy link
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-sdk-provider/src/provider.ts (1)

191-200: Persist session_id for non-streaming calls.

doGenerate ignores the returned session_id, so follow-up turns won’t be linked.

-    const data = (await response.json()) as {
+    const data = (await response.json()) as {
       message?: string;
       request_id?: string;
       session_id?: string;
       actions?: unknown[];
     };
 
     // TODO (ai): handle actions
+    if (data.session_id) {
+      this.setSessionId(data.session_id);
+    }

Also applies to: 200-220

♻️ Duplicate comments (1)
packages/ai-sdk-provider/src/provider.ts (1)

582-596: Unbounded SessionStore may grow indefinitely.

Re-flagging prior feedback: add TTL/eviction to prevent memory growth under load.

🧹 Nitpick comments (9)
apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (5)

36-43: Add explicit return types for components.

Align with repo guidelines for TS/TSX explicit returns.

-export function ChatContainer() {
+export function ChatContainer(): JSX.Element {
...
-const SignTransactionButton = (props: SignTransactionButtonProps) => {
+const SignTransactionButton = (props: SignTransactionButtonProps): JSX.Element => {
...
-const SignSwapButton = (props: SignSwapButtonProps) => {
+const SignSwapButton = (props: SignSwapButtonProps): JSX.Element => {

Also applies to: 156-156, 225-225


99-101: Remove debug log from render path.

Avoid noisy console logs in production UIs.

-                      case "tool-sign_swap":
-                        console.log("---sign_swap", part);
+                      case "tool-sign_swap":

180-183: Replace inline styles with Tailwind.

Playground apps should use Tailwind only.

-      <TransactionButton
-        style={{
-          width: "100%",
-        }}
+      <TransactionButton
+        className="w-full"

(Apply in both buttons.)

Also applies to: 251-254


203-204: Don’t echo raw error messages back into the model.

Sanitize to avoid leaking internal details; log locally instead.

-          sendMessage({ text: `Transaction failed: ${error.message}` });
+          console.error(error);
+          sendMessage({ text: "Transaction failed. Please try again." });

(Apply in both handlers.)

Also applies to: 274-275


36-140: Consider splitting child components into files.

This file now hosts three components; extracting SignTransactionButton/SignSwapButton improves single‑responsibility and reusability.

packages/ai-sdk-provider/src/provider.ts (1)

169-174: Avoid sending session_id: null in context.

Only include session_id when present to keep payloads clean and avoid ambiguous nulls.

-      context: { ...this.settings.context, session_id: this.getSessionId() },
+      context: this.getSessionId()
+        ? { ...this.settings.context, session_id: this.getSessionId()! }
+        : { ...this.settings.context },

(Apply in both doGenerate and doStream.)

Also applies to: 232-236

apps/playground-web/src/app/ai/ai-sdk/page.tsx (3)

25-40: Add explicit return types.

Match TS guideline for explicit returns.

-export default function Page() {
+export default function Page(): JSX.Element {
@@
-function ServerCodeExample() {
+function ServerCodeExample(): JSX.Element {
@@
-function ChatExample() {
+function ChatExample(): JSX.Element {

Also applies to: 42-57, 99-136


82-83: Fix grammar in comment.

-    tools: thirdwebAI.tools(), // optional, to use handle transactions and swaps
+    tools: thirdwebAI.tools(), // optional, to handle transactions and swaps

109-117: Prefer import type for types in snippet.

Avoids emitting an unused runtime import in TS projects.

-import { ThirdwebAiMessage } from '@thirdweb-dev/ai-sdk-provider';
+import type { ThirdwebAiMessage } from '@thirdweb-dev/ai-sdk-provider';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e3a2ae2 and 6e25976.

📒 Files selected for processing (6)
  • .changeset/pink-hands-find.md (1 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (6 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx (3 hunks)
  • apps/playground-web/src/app/api/chat/route.ts (1 hunks)
  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx (5 hunks)
  • packages/ai-sdk-provider/src/provider.ts (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • .changeset/pink-hands-find.md
  • apps/playground-web/src/app/api/chat/route.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • packages/ai-sdk-provider/src/provider.ts
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • packages/ai-sdk-provider/src/provider.ts
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
🧠 Learnings (3)
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Write idiomatic TypeScript with explicit function declarations and return types

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to **/*.{ts,tsx} : Use explicit function declarations and explicit return types in TypeScript

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
🧬 Code graph analysis (2)
packages/ai-sdk-provider/src/provider.ts (1)
packages/ai-sdk-provider/src/types.ts (2)
  • ThirdwebSettings (31-50)
  • ThirdwebConfig (12-29)
apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (1)
packages/ai-sdk-provider/src/types.ts (1)
  • ThirdwebAiMessage (52-71)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Size
🔇 Additional comments (6)
apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (2)

42-43: Good switch to automatic tool-result continuation.

Using sendAutomaticallyWhen with lastAssistantMessageIsCompleteWithToolCalls keeps the flow simple.


151-153: Prop types fix looks good.

Using UseChatHelpers for addToolResult/sendMessage is correct and future‑proof.

Also applies to: 221-223, 157-158, 226-227

apps/portal/src/app/ai/chat/ai-sdk/page.mdx (2)

41-45: Server changes LGTM.

Reading id from the body and calling thirdwebAI.chat(id, …) matches the new API.

Also applies to: 55-59


70-81: Great: aligned React client to auto tool flow and correct typing.

Using lastAssistantMessageIsCompleteWithToolCalls and UseChatHelpers types is correct.

Also applies to: 115-120

packages/ai-sdk-provider/src/provider.ts (1)

81-89: Good robustness on randomUUID detection.

The typeof check prevents runtime errors on older environments.

apps/playground-web/src/app/ai/ai-sdk/page.tsx (1)

71-88: Server example update looks correct.

Using id and thirdwebAI.chat(id, …) matches provider behavior.

Copy link
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: 1

Caution

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

⚠️ Outside diff range comments (2)
apps/portal/src/app/ai/chat/ai-sdk/page.mdx (1)

122-171: Syntax fix: missing closing brace for switch.

The switch block isn’t closed before ending the callback. Add a } to close switch.

           default:
             return null;
-      })}
+        }
+      })}
packages/ai-sdk-provider/src/provider.ts (1)

473-481: Do not stringify tool inputs (breaks consumer typings).

Docs and UI expect part.input to be an object. Emitting a string forces consumers to JSON-parse and breaks types.

                           controller.enqueue({
                             type: "tool-call",
                             toolCallId,
                             toolName,
-                            input: JSON.stringify(input),
+                            input,
                             providerExecuted: false,
                           });
♻️ Duplicate comments (3)
apps/portal/src/app/ai/chat/ai-sdk/page.mdx (1)

115-120: Fixed invalid prop type; now correct.

Switch to UseChatHelpers<ThirdwebAiMessage>["addToolResult"] resolves the earlier TS issue.

packages/ai-sdk-provider/src/provider.ts (2)

81-89: Robust UUID check is correct.

typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" avoids runtime errors in older environments.


582-596: SessionStore can leak memory; add TTL-based eviction.

Unbounded Map grows indefinitely. Add a TTL and expire on access; cheap, no timers required.

-class SessionStore {
-  private sessionId: Map<string, string> = new Map();
-
-  getSessionId(chatId: string) {
-    return this.sessionId.get(chatId) || null;
-  }
-
-  setSessionId(chatId: string, sessionId: string) {
-    this.sessionId.set(chatId, sessionId);
-  }
-
-  clearSessionId(chatId: string) {
-    this.sessionId.delete(chatId);
-  }
-}
+class SessionStore {
+  // store value + expiry to bound growth
+  private sessionId = new Map<string, { value: string; exp: number }>();
+  private readonly TTL_MS = 24 * 60 * 60 * 1000; // 24h
+
+  getSessionId(chatId: string) {
+    const entry = this.sessionId.get(chatId);
+    if (!entry) return null;
+    if (entry.exp <= Date.now()) {
+      this.sessionId.delete(chatId);
+      return null;
+    }
+    return entry.value;
+  }
+
+  setSessionId(chatId: string, sessionId: string) {
+    this.sessionId.set(chatId, { value: sessionId, exp: Date.now() + this.TTL_MS });
+  }
+
+  clearSessionId(chatId: string) {
+    this.sessionId.delete(chatId);
+  }
+}
🧹 Nitpick comments (4)
apps/portal/src/app/ai/chat/ai-sdk/page.mdx (1)

61-62: Clarify continuity vs. new chats (serverless nuance).

Continuity requires reusing the same id across requests; omitting it generates an ephemeral id that may not persist across serverless invocations. Suggested copy update:

-Continuous conversations are handled automatically. You can create a new conversation by passing a new `id` to the `thirdwebAI.chat()` function.
+To continue a conversation across requests, reuse the same `id` you pass to `thirdwebAI.chat(id, …)`.  
+To start fresh, pass a new `id`. If you omit `id`, the server may generate an ephemeral one that won’t persist across serverless invocations.
packages/ai-sdk-provider/src/provider.ts (3)

230-236: Stream: avoid session_id: null in context.

Mirror the guarded assignment used in doGenerate.

-    const body = {
-      messages,
-      stream: true,
-      context: { ...this.settings.context, session_id: this.getSessionId() },
-    };
+    const sessionId = this.getSessionId();
+    const body = {
+      messages,
+      stream: true,
+      context: {
+        ...this.settings.context,
+        ...(sessionId ? { session_id: sessionId } : {}),
+      },
+    };

562-569: Optional: allow languageModel to accept an id like chat.

Keeps API consistent for callers that prefer explicit model IDs.

-  languageModel(modelId: string, settings: ThirdwebSettings = {}) {
-    return new ThirdwebLanguageModel(
-      modelId,
-      settings,
-      this.config,
-      this.session,
-    );
-  }
+  languageModel(modelId: string, settings: ThirdwebSettings = {}, id?: string) {
+    return new ThirdwebLanguageModel(modelId, settings, this.config, this.session, id);
+  }

73-80: Add explicit return types to private helpers.

Matches repo TS guidelines and improves API readability.

-  private getSessionId() {
+  private getSessionId(): string | null {
     return this.sessionStore.getSessionId(this.chatId);
   }
 
-  private setSessionId(sessionId: string) {
+  private setSessionId(sessionId: string): void {
     this.sessionStore.setSessionId(this.chatId, sessionId);
   }

Additionally (outside the changed range), consider:

  • private getHeaders(): Record<string, string>
  • private convertMessages(...): Array<{ role: string; content: string }>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6e25976 and 0e7def9.

📒 Files selected for processing (6)
  • .changeset/pink-hands-find.md (1 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx (6 hunks)
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx (3 hunks)
  • apps/playground-web/src/app/api/chat/route.ts (1 hunks)
  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx (5 hunks)
  • packages/ai-sdk-provider/src/provider.ts (8 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .changeset/pink-hands-find.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/playground-web/src/app/api/chat/route.ts
  • apps/playground-web/src/app/ai/ai-sdk/page.tsx
  • apps/playground-web/src/app/ai/ai-sdk/components/chat-container.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • packages/ai-sdk-provider/src/provider.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • packages/ai-sdk-provider/src/provider.ts
🧠 Learnings (3)
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Write idiomatic TypeScript with explicit function declarations and return types

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to **/*.{ts,tsx} : Use explicit function declarations and explicit return types in TypeScript

Applied to files:

  • apps/portal/src/app/ai/chat/ai-sdk/page.mdx
🧬 Code graph analysis (1)
packages/ai-sdk-provider/src/provider.ts (1)
packages/ai-sdk-provider/src/types.ts (2)
  • ThirdwebSettings (31-50)
  • ThirdwebConfig (12-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Size
  • GitHub Check: Build Packages
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
apps/portal/src/app/ai/chat/ai-sdk/page.mdx (4)

41-45: Server: id handling looks correct.

Switching to { id } and passing it to thirdwebAI.chat(id, …) aligns with the new API.


71-81: Good use of sendAutomaticallyWhen.

Importing DefaultChatTransport and lastAssistantMessageIsCompleteWithToolCalls and wiring them into useChat is spot on.


90-97: Message rendering props look right.

Using key={message.id} and passing addToolResult into RenderMessage matches the provider/tool flow.


144-157: Tool result flow is correct.

Using toolCallId={part.toolCallId} and addToolResult matches the AI SDK contract.

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

Labels

packages Playground Changes involving the Playground codebase. Portal Involves changes to the Portal (docs) codebase.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants