diff --git a/package-lock.json b/package-lock.json index 1bf65fd..b74e001 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,15 +10,15 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@ai-sdk/openai": "^2.0.88", - "@ai-sdk/react": "^2.0.118", + "@ai-sdk/openai": "^3.0.0", + "@ai-sdk/react": "^3.0.1", "@phosphor-icons/react": "^2.1.10", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-switch": "^1.2.6", - "agents": "^0.2.35", - "ai": "^5.0.116", + "agents": "^0.3.0", + "ai": "^6.0.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "marked": "^17.0.1", @@ -26,7 +26,7 @@ "react-dom": "^19.2.3", "streamdown": "^1.6.10", "tailwind-merge": "^3.4.0", - "workers-ai-provider": "^2.0.0" + "workers-ai-provider": "^3.0.0" }, "devDependencies": { "@biomejs/biome": "^2.3.10", @@ -48,13 +48,13 @@ } }, "node_modules/@ai-sdk/gateway": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.23.tgz", - "integrity": "sha512-qmX7afPRszUqG5hryHF3UN8ITPIRSGmDW6VYCmByzjoUkgm3MekzSx2hMV1wr0P+llDeuXb378SjqUfpvWJulg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-3.0.0.tgz", + "integrity": "sha512-JcjePYVpbezv+XOxkxPemwnorjWpgDiiKWMYy6FXTCG2rFABIK2Co1bFxIUSDT4vYO6f1448x9rKbn38vbhDiA==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.19", + "@ai-sdk/provider": "3.0.0", + "@ai-sdk/provider-utils": "4.0.0", "@vercel/oidc": "3.0.5" }, "engines": { @@ -65,14 +65,14 @@ } }, "node_modules/@ai-sdk/openai": { - "version": "2.0.88", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-2.0.88.tgz", - "integrity": "sha512-LlOf83haeZIiRUH1Zw1oEmqUfw5y54227CvndFoBpIkMJwQDGAB3VARUeOJ6iwAWDJjXSz06GdnEnhRU67Yatw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-3.0.0.tgz", + "integrity": "sha512-/o2xCQlRA+O0cAXIIBOfMeT35H6Fonzilz9r/IJojPOMQnmIL+0jPQVKOUPr5bouRqCjnwKpwuKEBRqm8jUZkQ==", "license": "Apache-2.0", "peer": true, "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.19" + "@ai-sdk/provider": "3.0.0", + "@ai-sdk/provider-utils": "4.0.0" }, "engines": { "node": ">=18" @@ -82,9 +82,9 @@ } }, "node_modules/@ai-sdk/provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz", - "integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.0.tgz", + "integrity": "sha512-m9ka3ptkPQbaHHZHqDXDF9C9B5/Mav0KTdky1k2HZ3/nrW2t1AgObxIVPyGDWQNS9FXT/FS6PIoSjpcP/No8rQ==", "license": "Apache-2.0", "dependencies": { "json-schema": "^0.4.0" @@ -94,13 +94,13 @@ } }, "node_modules/@ai-sdk/provider-utils": { - "version": "3.0.19", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.19.tgz", - "integrity": "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.0.tgz", + "integrity": "sha512-HyCyOls9I3a3e38+gtvOJOEjuw9KRcvbBnCL5GBuSmJvS9Jh9v3fz7pRC6ha1EUo/ZH1zwvLWYXBMtic8MTguA==", "license": "Apache-2.0", "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@standard-schema/spec": "^1.0.0", + "@ai-sdk/provider": "3.0.0", + "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "engines": { @@ -111,14 +111,14 @@ } }, "node_modules/@ai-sdk/react": { - "version": "2.0.118", - "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-2.0.118.tgz", - "integrity": "sha512-K/5VVEGTIu9SWrdQ0s/11OldFU8IjprDzeE6TaC2fOcQWhG7dGVGl9H8Z32QBHzdfJyMhFUxEyFKSOgA2j9+VQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-3.0.1.tgz", + "integrity": "sha512-XUPDMFgalNtqBQg+Q3UiiEmWE3PC5pAoc+Drs5Z1Mxqe57za+hKCEwViYADuqeZrc0q6PXTzbcFlQb3pjyGjcQ==", "license": "Apache-2.0", "peer": true, "dependencies": { - "@ai-sdk/provider-utils": "3.0.19", - "ai": "5.0.116", + "@ai-sdk/provider-utils": "4.0.0", + "ai": "6.0.1", "swr": "^2.2.5", "throttleit": "2.1.0" }, @@ -126,13 +126,7 @@ "node": ">=18" }, "peerDependencies": { - "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1", - "zod": "^3.25.76 || ^4.1.8" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } + "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "node_modules/@antfu/install-pkg": { @@ -4893,9 +4887,9 @@ } }, "node_modules/agents": { - "version": "0.2.35", - "resolved": "https://registry.npmjs.org/agents/-/agents-0.2.35.tgz", - "integrity": "sha512-e6Ift6X0sFceYgFBIZGK4jQ+vyFq9caSF80ilsAVHzfFHvqb21013UrgGzZac4X+fzAP103YBSgS7C57tjAj8w==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/agents/-/agents-0.3.0.tgz", + "integrity": "sha512-UwhTWs6YPrhHTfV6vvEkYlJnC643nwpCSOvoUmyabWbZvUiHuIvhhAMclmsSh9J0GYQSpg7rKb1tCId2xumvbQ==", "license": "MIT", "dependencies": { "@cfworker/json-schema": "^4.1.1", @@ -4914,9 +4908,9 @@ "agents": "dist/cli/index.js" }, "peerDependencies": { - "@ai-sdk/openai": ">=2.0.0", - "@ai-sdk/react": ">=1.0.0", - "ai": ">=5.0.0", + "@ai-sdk/openai": "^3.0.0", + "@ai-sdk/react": "^3.0.0", + "ai": "^6.0.0", "react": "^19.0.0", "viem": ">=2.0.0", "x402": "^0.7.1", @@ -4941,14 +4935,15 @@ } }, "node_modules/ai": { - "version": "5.0.116", - "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.116.tgz", - "integrity": "sha512-+2hYJ80/NcDWuv9K2/MLP3cTCFgwWHmHlS1tOpFUKKcmLbErAAlE/S2knsKboc3PNAu8pQkDr2N3K/Vle7ENgQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ai/-/ai-6.0.1.tgz", + "integrity": "sha512-g/jPakC6h4vUJKDww0d6+VaJmfMC38UqH3kKsngiP+coT0uvCUdQ7lpFDJ0mNmamaOyRMaY2zwEB2RnTAaJU/w==", "license": "Apache-2.0", + "peer": true, "dependencies": { - "@ai-sdk/gateway": "2.0.23", - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.19", + "@ai-sdk/gateway": "3.0.0", + "@ai-sdk/provider": "3.0.0", + "@ai-sdk/provider-utils": "4.0.0", "@opentelemetry/api": "1.9.0" }, "engines": { @@ -11290,13 +11285,16 @@ } }, "node_modules/workers-ai-provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/workers-ai-provider/-/workers-ai-provider-2.0.0.tgz", - "integrity": "sha512-AoGGy8aOR3lzCzRouSxA6mgrCKuZfrnzxvOHHy9kOzwz4Mm4Hb55a/9G8zz+v0I/mn8bYLs/4I6JABSl/zXJ7w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/workers-ai-provider/-/workers-ai-provider-3.0.0.tgz", + "integrity": "sha512-Pg0cihFGXAhERHsd176z+wbF+z3+Ceyi/HpuJnIkBLJQTSDGF5Fxs4oT6K7bzNcvX1oa6dcZw6J6RcdR6Wz3kA==", "license": "MIT", "dependencies": { - "@ai-sdk/provider": "^2.0.0", - "@ai-sdk/provider-utils": "^3.0.7" + "@ai-sdk/provider": "^3.0.0", + "@ai-sdk/provider-utils": "^4.0.0" + }, + "peerDependencies": { + "ai": "^6.0.0" } }, "node_modules/wrangler": { @@ -11984,6 +11982,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz", "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index cf99bd6..4f7510e 100644 --- a/package.json +++ b/package.json @@ -40,15 +40,15 @@ "wrangler": "4.56.0" }, "dependencies": { - "@ai-sdk/openai": "^2.0.88", - "@ai-sdk/react": "^2.0.118", + "@ai-sdk/openai": "^3.0.0", + "@ai-sdk/react": "^3.0.1", "@phosphor-icons/react": "^2.1.10", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-switch": "^1.2.6", - "agents": "^0.2.35", - "ai": "^5.0.116", + "agents": "^0.3.0", + "ai": "^6.0.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "marked": "^17.0.1", @@ -56,6 +56,6 @@ "react-dom": "^19.2.3", "streamdown": "^1.6.10", "tailwind-merge": "^3.4.0", - "workers-ai-provider": "^2.0.0" + "workers-ai-provider": "^3.0.0" } } diff --git a/src/app.tsx b/src/app.tsx index 696842e..91be562 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,7 +1,7 @@ /** biome-ignore-all lint/correctness/useUniqueElementIds: it's alright */ import { useEffect, useState, useRef, useCallback, use } from "react"; import { useAgent } from "agents/react"; -import { isToolUIPart } from "ai"; +import { isStaticToolUIPart } from "ai"; import { useAgentChat } from "agents/ai-react"; import type { UIMessage } from "@ai-sdk/react"; import type { tools } from "./tools"; @@ -122,7 +122,7 @@ export default function Chat() { const pendingToolCallConfirmation = agentMessages.some((m: UIMessage) => m.parts?.some( (part) => - isToolUIPart(part) && + isStaticToolUIPart(part) && part.state === "input-available" && // Manual check inside the component toolsRequiringConfirmation.includes( @@ -136,7 +136,7 @@ export default function Chat() { }; return ( -
+
@@ -242,7 +242,7 @@ export default function Chat() { }`} > {showAvatar && !isUser ? ( - + ) : ( !isUser &&
)} @@ -295,7 +295,10 @@ export default function Chat() { ); } - if (isToolUIPart(part) && m.role === "assistant") { + if ( + isStaticToolUIPart(part) && + m.role === "assistant" + ) { const toolCallId = part.toolCallId; const toolName = part.type.replace("tool-", ""); const needsConfirmation = @@ -361,7 +364,7 @@ export default function Chat() { ? "Please respond to the tool confirmation above..." : "Send a message..." } - className="flex w-full border border-neutral-200 dark:border-neutral-700 px-3 py-2 ring-offset-background placeholder:text-neutral-500 dark:placeholder:text-neutral-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-300 dark:focus-visible:ring-neutral-700 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-neutral-900 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm min-h-[24px] max-h-[calc(75dvh)] overflow-hidden resize-none rounded-2xl !text-base pb-10 dark:bg-neutral-900" + className="flex w-full border border-neutral-200 dark:border-neutral-700 px-3 py-2 ring-offset-background placeholder:text-neutral-500 dark:placeholder:text-neutral-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-300 dark:focus-visible:ring-neutral-700 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-neutral-900 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm min-h-[24px] max-h-[calc(75dvh)] overflow-hidden resize-none rounded-2xl text-base! pb-10 dark:bg-neutral-900" value={agentInput} onChange={(e) => { handleAgentInputChange(e); diff --git a/src/components/tool-invocation-card/ToolInvocationCard.tsx b/src/components/tool-invocation-card/ToolInvocationCard.tsx index 9bc1604..8240d36 100644 --- a/src/components/tool-invocation-card/ToolInvocationCard.tsx +++ b/src/components/tool-invocation-card/ToolInvocationCard.tsx @@ -51,7 +51,7 @@ export function ToolInvocationCard({ className="w-full flex items-center gap-2 cursor-pointer" >
@@ -78,7 +78,7 @@ export function ToolInvocationCard({
Arguments:
-
+            
               {JSON.stringify(toolUIPart.input, null, 2)}
             
@@ -107,7 +107,7 @@ export function ToolInvocationCard({
Result:
-
+              
                 {(() => {
                   const result = toolUIPart.output;
                   if (isToolResultWithContent(result)) {
diff --git a/src/server.ts b/src/server.ts
index 4aeb119..1a61828 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -68,7 +68,7 @@ ${getSchedulePrompt({ date: new Date() })}
 If the user asks to schedule a task, use the schedule tool to schedule the task.
 `,
 
-          messages: convertToModelMessages(processedMessages),
+          messages: await convertToModelMessages(processedMessages),
           model,
           tools: allTools,
           // Type boundary: streamText expects specific tool types, but base class uses ToolSet
diff --git a/src/utils.ts b/src/utils.ts
index 33ae754..f124bc1 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -6,7 +6,7 @@ import type {
   ToolSet,
   ToolCallOptions
 } from "ai";
-import { convertToModelMessages, isToolUIPart } from "ai";
+import { convertToModelMessages, isStaticToolUIPart } from "ai";
 import { APPROVAL } from "./shared";
 
 function isValidToolName(
@@ -41,8 +41,8 @@ export async function processToolCalls({
 
       const processedParts = await Promise.all(
         parts.map(async (part) => {
-          // Only process tool UI parts
-          if (!isToolUIPart(part)) return part;
+          // Only process static tool UI parts (dynamic tools handled separately)
+          if (!isStaticToolUIPart(part)) return part;
 
           const toolName = part.type.replace(
             "tool-",
@@ -64,7 +64,7 @@ export async function processToolCalls({
             const toolInstance = executions[toolName];
             if (toolInstance) {
               result = await toolInstance(part.input, {
-                messages: convertToModelMessages(messages),
+                messages: await convertToModelMessages(messages),
                 toolCallId: part.toolCallId
               });
             } else {
@@ -109,7 +109,7 @@ export function cleanupMessages(messages: UIMessage[]): UIMessage[] {
 
     // Filter out messages with incomplete tool calls
     const hasIncompleteToolCall = message.parts.some((part) => {
-      if (!isToolUIPart(part)) return false;
+      if (!isStaticToolUIPart(part)) return false;
       // Remove tool calls that are still streaming or awaiting input without results
       return (
         part.state === "input-streaming" ||