diff --git a/TYPE_FIX_SUMMARY.md b/TYPE_FIX_SUMMARY.md new file mode 100644 index 00000000..f11e3ad2 --- /dev/null +++ b/TYPE_FIX_SUMMARY.md @@ -0,0 +1,63 @@ +# AI SDK v6 Type Error Fix Summary + +## Problem +The build fails with TypeScript errors after upgrading to AI SDK v6. The main issues are: +1. `ToolCallPart` type now requires `input` field (not optional), but stored data may only have deprecated `args` field +2. Tool-result output types missing newer types like `execution-denied` and extended content types +3. Generated component types out of sync with updated validators + +## Changes Made + +### 1. Fixed `tool-call` Part Handling (src/mapping.ts) +- Updated `toModelMessageContent()` to ensure `input` is always present by falling back to `args` or `{}` +- Updated `serializeContent()` and `fromModelMessageContent()` to handle both `input` and legacy `args` fields +- This fixes the core issue where AI SDK v6's `ToolCallPart` expects non-nullable `input` + +### 2. Fixed Tool Approval Response Handling (src/client/search.ts) +- Updated `filterOutOrphanedToolMessages()` to handle tool-approval-response parts that don't have `toolCallId` +- Tool-approval-response only has `approvalId`, not `toolCallId` + +### 3. Updated Generated Component Types (src/component/_generated/component.ts) +Made manual updates to sync with validators (normally done via `convex codegen`): +- Added `input: any` field to all tool-call type definitions +- Made `args` optional (`args?: any`) in tool-call types +- Added `execution-denied` output type to tool-result +- Added extended content types: `file-data`, `file-url`, `file-id`, `image-data`, `image-url`, `image-file-id`, `custom` +- Added `providerOptions` to text types in content values + +## Remaining Issues (5 TypeScript errors) + +The remaining errors are due to a structural mismatch in the generated component types: +- Generated types have BOTH `experimental_content` (deprecated) and `output` (new) fields on tool-result +- Our validators only define `output`, not `experimental_content` +- TypeScript is comparing our new output types against the old experimental_content types +- This cannot be fixed manually - requires proper component regeneration + +### To Complete the Fix: +1. Run `convex codegen --component-dir ./src/component` with a valid Convex deployment +2. This will regenerate `src/component/_generated/component.ts` from the validators +3. The regenerated types will: + - Remove the deprecated `experimental_content` field + - Use only the `output` field with correct types + - Properly match the validator definitions + +### Error Locations: +- `src/client/index.ts:1052` - addMessages call +- `src/client/index.ts:1103` - addMessages call +- `src/client/index.ts:1169` - updateMessage call +- `src/client/messages.ts:141` - addMessages call +- `src/client/start.ts:265` - addMessages call + +All errors have the same root cause: content value types in tool-result output don't match experimental_content expectations. + +## Testing Plan +Once component types are regenerated: +1. Run `npm run build` - should complete without errors +2. Run `npm test` - ensure no regressions +3. Test with actual AI SDK v6 workflow - verify tool-call handling works with both new `input` and legacy `args` fields + +## Notes +- The mapping functions in `src/mapping.ts` correctly handle both old and new formats +- Data with only `args` will be converted to have `input` (with `args` as fallback) +- Data with `input` will work directly +- This provides backward compatibility while supporting AI SDK v6's requirements diff --git a/src/client/files.ts b/src/client/files.ts index 6ee78506..ae56581e 100644 --- a/src/client/files.ts +++ b/src/client/files.ts @@ -92,7 +92,7 @@ export async function storeFile( storageId: newStorageId, hash, filename, - mimeType: blob.type, + mediaType: blob.type, }); const url = (await ctx.storage.getUrl(storageId as Id<"_storage">))!; if (storageId !== newStorageId) { @@ -142,8 +142,10 @@ export async function getFile( if (!url) { throw new Error(`File not found in storage: ${file.storageId}`); } + // Support both mediaType (preferred) and mimeType (deprecated) + const mediaType = file.mediaType ?? file.mimeType ?? ""; return { - ...getParts(url, file.mimeType, file.filename), + ...getParts(url, mediaType, file.filename), file: { fileId, url, diff --git a/src/client/index.test.ts b/src/client/index.test.ts index f6e97269..9a2c4e18 100644 --- a/src/client/index.test.ts +++ b/src/client/index.test.ts @@ -193,6 +193,7 @@ describe("filterOutOrphanedToolMessages", () => { type: "tool-call", toolCallId: "1", toolName: "tool1", + input: { test: "test" }, args: { test: "test" }, }, ], diff --git a/src/client/search.test.ts b/src/client/search.test.ts index c2749c92..3a9b9b86 100644 --- a/src/client/search.test.ts +++ b/src/client/search.test.ts @@ -159,6 +159,7 @@ describe("search.ts", () => { type: "tool-call", toolCallId: "call_123", toolName: "test", + input: {}, args: {}, }, ], @@ -202,6 +203,7 @@ describe("search.ts", () => { type: "tool-call", toolCallId: "call_orphaned", toolName: "test", + input: {}, args: {}, }, ], diff --git a/src/client/search.ts b/src/client/search.ts index 05cf42d5..5c970932 100644 --- a/src/client/search.ts +++ b/src/client/search.ts @@ -267,9 +267,14 @@ export function filterOutOrphanedToolMessages(docs: MessageDoc[]) { }); } } else if (doc.message?.role === "tool") { - const content = doc.message.content.filter((c) => - toolCallIds.has(c.toolCallId), - ); + const content = doc.message.content.filter((c) => { + // tool-result parts have toolCallId + if (c.type === "tool-result") { + return toolCallIds.has(c.toolCallId); + } + // tool-approval-response parts don't have toolCallId, so include them + return true; + }); if (content.length) { result.push({ ...doc, diff --git a/src/component/_generated/component.ts b/src/component/_generated/component.ts index 228108ff..f6708edc 100644 --- a/src/component/_generated/component.ts +++ b/src/component/_generated/component.ts @@ -56,7 +56,8 @@ export type ComponentApi = { filename?: string; hash: string; - mimeType: string; + mediaType?: string; + mimeType?: string; storageId: string; }, { fileId: string; storageId: string }, @@ -86,7 +87,8 @@ export type ComponentApi = filename?: string; hash: string; lastTouchedAt: number; - mimeType: string; + mediaType?: string; + mimeType?: string; refcount: number; storageId: string; }, @@ -114,7 +116,8 @@ export type ComponentApi = filename?: string; hash: string; lastTouchedAt: number; - mimeType: string; + mediaType?: string; + mimeType?: string; refcount: number; storageId: string; }>; @@ -182,6 +185,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record< string, @@ -192,7 +196,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -226,7 +231,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -262,8 +268,25 @@ export type ComponentApi = >; type: "redacted-reasoning"; } + | { + args?: any; + input: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args: any; + input?: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -289,19 +312,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -349,38 +473,167 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; providerOptions?: Record>; role: "tool"; } @@ -485,6 +738,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record< string, @@ -495,7 +749,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -529,7 +784,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -565,8 +821,25 @@ export type ComponentApi = >; type: "redacted-reasoning"; } + | { + args?: any; + input: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args: any; + input?: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -592,19 +865,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -652,38 +1026,167 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; providerOptions?: Record>; role: "tool"; } @@ -839,6 +1342,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record>; type: "image"; @@ -846,7 +1350,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -874,7 +1379,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -902,7 +1408,8 @@ export type ComponentApi = type: "redacted-reasoning"; } | { - args: any; + args?: any; + input: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -913,6 +1420,22 @@ export type ComponentApi = toolName: string; type: "tool-call"; } + | { + args: any; + input?: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args?: any; experimental_content?: Array< @@ -921,19 +1444,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -972,88 +1596,214 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record>; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; - providerOptions?: Record>; - role: "tool"; - } - | { - content: string; - providerOptions?: Record>; - role: "system"; - }; - model?: string; - order: number; - provider?: string; - providerMetadata?: Record>; - providerOptions?: Record>; - reasoning?: string; - reasoningDetails?: Array< - | { - providerMetadata?: Record>; - providerOptions?: Record>; - signature?: string; - text: string; - type: "reasoning"; - } - | { signature?: string; text: string; type: "text" } - | { data: string; type: "redacted" } - >; - sources?: Array< - | { - id: string; - providerMetadata?: Record>; - providerOptions?: Record>; - sourceType: "url"; - title?: string; - type?: "source"; - url: string; - } - | { - filename?: string; - id: string; - mediaType: string; - providerMetadata?: Record>; - providerOptions?: Record>; - sourceType: "document"; - title: string; - type: "source"; - } - >; - status: "pending" | "success" | "failed"; - stepOrder: number; - text?: string; - threadId: string; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; + providerOptions?: Record>; + role: "tool"; + } + | { + content: string; + providerOptions?: Record>; + role: "system"; + }; + model?: string; + order: number; + provider?: string; + providerMetadata?: Record>; + providerOptions?: Record>; + reasoning?: string; + reasoningDetails?: Array< + | { + providerMetadata?: Record>; + providerOptions?: Record>; + signature?: string; + text: string; + type: "reasoning"; + } + | { signature?: string; text: string; type: "text" } + | { data: string; type: "redacted" } + >; + sources?: Array< + | { + id: string; + providerMetadata?: Record>; + providerOptions?: Record>; + sourceType: "url"; + title?: string; + type?: "source"; + url: string; + } + | { + filename?: string; + id: string; + mediaType: string; + providerMetadata?: Record>; + providerOptions?: Record>; + sourceType: "document"; + title: string; + type: "source"; + } + >; + status: "pending" | "success" | "failed"; + stepOrder: number; + text?: string; + threadId: string; tool: boolean; usage?: { cachedInputTokens?: number; @@ -1134,6 +1884,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record< string, @@ -1144,7 +1895,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -1178,7 +1930,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -1214,8 +1967,25 @@ export type ComponentApi = >; type: "redacted-reasoning"; } + | { + args?: any; + input: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args: any; + input?: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -1241,19 +2011,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -1301,38 +2172,167 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; providerOptions?: Record>; role: "tool"; } @@ -1455,6 +2455,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record>; type: "image"; @@ -1462,7 +2463,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -1490,7 +2492,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -1518,7 +2521,8 @@ export type ComponentApi = type: "redacted-reasoning"; } | { - args: any; + args?: any; + input: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -1529,6 +2533,22 @@ export type ComponentApi = toolName: string; type: "tool-call"; } + | { + args: any; + input?: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args?: any; experimental_content?: Array< @@ -1537,19 +2557,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -1588,47 +2709,173 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record>; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; - providerOptions?: Record>; - role: "tool"; - } - | { - content: string; - providerOptions?: Record>; - role: "system"; - }; - model?: string; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; + providerOptions?: Record>; + role: "tool"; + } + | { + content: string; + providerOptions?: Record>; + role: "system"; + }; + model?: string; order: number; provider?: string; providerMetadata?: Record>; @@ -1729,6 +2976,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record>; type: "image"; @@ -1736,7 +2984,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -1764,7 +3013,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -1792,7 +3042,8 @@ export type ComponentApi = type: "redacted-reasoning"; } | { - args: any; + args?: any; + input: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -1803,6 +3054,22 @@ export type ComponentApi = toolName: string; type: "tool-call"; } + | { + args: any; + input?: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args?: any; experimental_content?: Array< @@ -1811,19 +3078,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -1862,38 +3230,164 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record>; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; providerOptions?: Record>; role: "tool"; } @@ -1996,6 +3490,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record< string, @@ -2006,7 +3501,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -2040,7 +3536,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -2076,8 +3573,25 @@ export type ComponentApi = >; type: "redacted-reasoning"; } + | { + args?: any; + input: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args: any; + input?: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -2103,19 +3617,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -2163,38 +3778,167 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; providerOptions?: Record>; role: "tool"; } @@ -2241,6 +3985,7 @@ export type ComponentApi = } | { image: string | ArrayBuffer; + mediaType?: string; mimeType?: string; providerOptions?: Record>; type: "image"; @@ -2248,7 +3993,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -2276,7 +4022,8 @@ export type ComponentApi = | { data: string | ArrayBuffer; filename?: string; - mimeType: string; + mediaType?: string; + mimeType?: string; providerMetadata?: Record< string, Record @@ -2304,7 +4051,8 @@ export type ComponentApi = type: "redacted-reasoning"; } | { - args: any; + args?: any; + input: any; providerExecuted?: boolean; providerMetadata?: Record< string, @@ -2315,6 +4063,22 @@ export type ComponentApi = toolName: string; type: "tool-call"; } + | { + args: any; + input?: any; + providerExecuted?: boolean; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record< + string, + Record + >; + toolCallId: string; + toolName: string; + type: "tool-call"; + } | { args?: any; experimental_content?: Array< @@ -2323,19 +4087,120 @@ export type ComponentApi = >; isError?: boolean; output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } | { type: "content"; value: Array< - | { text: string; type: "text" } + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } | { data: string; mediaType: string; type: "media"; } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } >; }; providerExecuted?: boolean; @@ -2374,38 +4239,164 @@ export type ComponentApi = title: string; type: "source"; } + | { + approvalId: string; + providerMetadata?: Record< + string, + Record + >; + providerOptions?: Record>; + toolCallId: string; + type: "tool-approval-request"; + } >; providerOptions?: Record>; role: "assistant"; } | { - content: Array<{ - args?: any; - experimental_content?: Array< - | { text: string; type: "text" } - | { data: string; mimeType?: string; type: "image" } - >; - isError?: boolean; - output?: - | { type: "text"; value: string } - | { type: "json"; value: any } - | { type: "error-text"; value: string } - | { type: "error-json"; value: any } - | { - type: "content"; - value: Array< - | { text: string; type: "text" } - | { data: string; mediaType: string; type: "media" } - >; - }; - providerExecuted?: boolean; - providerMetadata?: Record>; - providerOptions?: Record>; - result?: any; - toolCallId: string; - toolName: string; - type: "tool-result"; - }>; + content: Array< + | { + args?: any; + experimental_content?: Array< + | { text: string; type: "text" } + | { data: string; mimeType?: string; type: "image" } + >; + isError?: boolean; + output?: + | { + providerOptions?: Record< + string, + Record + >; + type: "text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-text"; + value: string; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "error-json"; + value: any; + } + | { + providerOptions?: Record< + string, + Record + >; + reason?: string; + type: "execution-denied"; + } + | { + type: "content"; + value: Array< + | { + providerOptions?: Record< + string, + Record + >; + text: string; + type: "text"; + } + | { + data: string; + mediaType: string; + type: "media"; + } + | { + data: string; + filename?: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "file-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "file-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "file-id"; + } + | { + data: string; + mediaType: string; + providerOptions?: Record< + string, + Record + >; + type: "image-data"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "image-url"; + url: string; + } + | { + fileId: string | Record; + providerOptions?: Record< + string, + Record + >; + type: "image-file-id"; + } + | { + providerOptions?: Record< + string, + Record + >; + type: "custom"; + } + >; + }; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + result?: any; + toolCallId: string; + toolName: string; + type: "tool-result"; + } + | { + approvalId: string; + approved: boolean; + providerExecuted?: boolean; + providerMetadata?: Record>; + providerOptions?: Record>; + reason?: string; + type: "tool-approval-response"; + } + >; providerOptions?: Record>; role: "tool"; } diff --git a/src/component/files.ts b/src/component/files.ts index c6ce165b..89506f4c 100644 --- a/src/component/files.ts +++ b/src/component/files.ts @@ -9,7 +9,9 @@ const addFileArgs = v.object({ storageId: v.string(), hash: v.string(), filename: v.optional(v.string()), - mimeType: v.string(), + mediaType: v.optional(v.string()), + /** @deprecated Use `mediaType` instead. */ + mimeType: v.optional(v.string()), }); export const addFile = mutation({ @@ -25,6 +27,9 @@ export async function addFileHandler( ctx: MutationCtx, args: Infer, ) { + // Support both mediaType (preferred) and mimeType (deprecated) + const mediaType = args.mediaType ?? args.mimeType; + const existingFile = await ctx.db .query("files") .withIndex("hash", (q) => q.eq("hash", args.hash)) @@ -42,7 +47,11 @@ export async function addFileHandler( }; } const fileId = await ctx.db.insert("files", { - ...args, + storageId: args.storageId, + hash: args.hash, + filename: args.filename, + mediaType, + mimeType: args.mimeType, // Keep for backwards compatibility // We start out with it unused - when it's saved in a message we increment. refcount: 0, lastTouchedAt: Date.now(), diff --git a/src/component/messages.test.ts b/src/component/messages.test.ts index 9581b8f6..0c273307 100644 --- a/src/component/messages.test.ts +++ b/src/component/messages.test.ts @@ -68,7 +68,7 @@ describe("agent", () => { content: [ { type: "tool-call", - args: { a: 1 }, + input: { a: 1 }, toolCallId: "1", toolName: "tool", }, @@ -258,7 +258,7 @@ describe("agent", () => { content: [ { type: "tool-call", - args: { a: 1 }, + input: { a: 1 }, toolCallId: "1", toolName: "tool", }, @@ -389,7 +389,7 @@ describe("agent", () => { content: [ { type: "tool-call", - args: { a: 1 }, + input: { a: 1 }, toolCallId: "1", toolName: "tool", }, @@ -408,7 +408,7 @@ describe("agent", () => { content: [ { type: "tool-call", - args: { a: 2, b: 3 }, + input: { a: 2, b: 3 }, toolCallId: "1", toolName: "tool", }, @@ -422,7 +422,7 @@ describe("agent", () => { content: [ { type: "tool-call", - args: { a: 2, b: 3 }, + input: { a: 2, b: 3 }, toolCallId: "1", toolName: "tool", }, diff --git a/src/component/schema.ts b/src/component/schema.ts index da319828..644cc62e 100644 --- a/src/component/schema.ts +++ b/src/component/schema.ts @@ -149,7 +149,9 @@ export const schema = defineSchema({ files: defineTable({ storageId: v.string(), - mimeType: v.string(), + mediaType: v.optional(v.string()), + /** @deprecated Use `mediaType` instead. */ + mimeType: v.optional(v.string()), filename: v.optional(v.string()), hash: v.string(), refcount: v.number(), diff --git a/src/fromUIMessages.test.ts b/src/fromUIMessages.test.ts index 4d295d43..4413c3c1 100644 --- a/src/fromUIMessages.test.ts +++ b/src/fromUIMessages.test.ts @@ -166,6 +166,7 @@ describe("fromUIMessages round-trip tests", () => { type: "tool-call", toolName: "calculator", toolCallId: "call1", + input: { operation: "add", a: 2, b: 3 }, args: { operation: "add", a: 2, b: 3 }, }, ], @@ -277,7 +278,7 @@ describe("fromUIMessages round-trip tests", () => { expect(fileContent).toBeDefined(); expect(fileContent).toMatchObject({ type: "file", - mimeType: "image/png", + mediaType: "image/png", }); } }); @@ -442,7 +443,9 @@ describe("fromUIMessages functionality tests", () => { ], }; - const result = await fromUIMessages([toolUIMessage], { threadId: "thread1" }); + const result = await fromUIMessages([toolUIMessage], { + threadId: "thread1", + }); expect(result.length).toBeGreaterThan(0); // Should have tool messages @@ -471,7 +474,9 @@ describe("fromUIMessages functionality tests", () => { ], }; - const result = await fromUIMessages([toolUIMessage], { threadId: "thread1" }); + const result = await fromUIMessages([toolUIMessage], { + threadId: "thread1", + }); expect(result.length).toBeGreaterThan(0); // Should have tool messages diff --git a/src/mapping.ts b/src/mapping.ts index 71c95ac0..c2d179c0 100644 --- a/src/mapping.ts +++ b/src/mapping.ts @@ -328,7 +328,7 @@ export async function serializeContent( } return { type: part.type, - mimeType: getMimeOrMediaType(part), + mediaType: getMimeOrMediaType(part), ...metadata, image, } satisfies Infer; @@ -348,17 +348,18 @@ export async function serializeContent( type: part.type, data, filename: part.filename, - mimeType: getMimeOrMediaType(part)!, + mediaType: getMimeOrMediaType(part)!, ...metadata, } satisfies Infer; } case "tool-call": { - const input = part.input ?? (part as any)?.args; + // Handle legacy data where only args field exists + const input = part.input ?? (part as any)?.args ?? {}; return { type: part.type, - input: input ?? null, + input, /** @deprecated Use `input` instead. */ - args: input ?? null, + args: input, toolCallId: part.toolCallId, toolName: part.toolName, providerExecuted: part.providerExecuted, @@ -419,7 +420,7 @@ export function fromModelMessageContent(content: Content): Message["content"] { case "image": return { type: part.type, - mimeType: getMimeOrMediaType(part), + mediaType: getMimeOrMediaType(part), ...metadata, image: serializeDataOrUrl(part.image), } satisfies Infer; @@ -428,15 +429,16 @@ export function fromModelMessageContent(content: Content): Message["content"] { type: part.type, data: serializeDataOrUrl(part.data), filename: part.filename, - mimeType: getMimeOrMediaType(part)!, + mediaType: getMimeOrMediaType(part)!, ...metadata, } satisfies Infer; case "tool-call": + // Handle legacy data where only args field exists return { type: part.type, - input: part.input ?? null, + input: part.input ?? (part as any)?.args ?? {}, /** @deprecated Use `input` instead. */ - args: part.input ?? null, + args: part.input ?? (part as any)?.args ?? {}, toolCallId: part.toolCallId, toolName: part.toolName, providerExecuted: part.providerExecuted, @@ -515,10 +517,11 @@ export function toModelMessageContent( ...metadata, } satisfies FilePart; case "tool-call": { - const input = part.input ?? (part as any)?.args; + // Handle legacy data where only args field exists + const input = part.input ?? (part as any)?.args ?? {}; return { type: part.type, - input: input ?? null, + input, toolCallId: part.toolCallId, toolName: part.toolName, providerExecuted: part.providerExecuted, diff --git a/src/toUIMessages.test.ts b/src/toUIMessages.test.ts index f871f8d3..63edb787 100644 --- a/src/toUIMessages.test.ts +++ b/src/toUIMessages.test.ts @@ -90,6 +90,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "myTool", toolCallId: "call1", + input: "an arg", args: "an arg", }, ], @@ -219,6 +220,7 @@ describe("toUIMessages", () => { }, { type: "tool-call", + input: "What's the meaning of life?", args: "What's the meaning of life?", toolCallId: "call1", toolName: "myTool", @@ -310,6 +312,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "myTool", toolCallId: "call1", + input: { query: "test" }, args: { query: "test" }, }, ], @@ -356,6 +359,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "myTool", toolCallId: "call1", + input: "hi", args: "hi", }, ], @@ -387,6 +391,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "myTool", toolCallId: "call1", + input: "", args: "", }, ], @@ -448,6 +453,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "calculator", toolCallId: "call1", + input: { operation: "add", a: 2, b: 3 }, args: { operation: "add", a: 2, b: 3 }, }, { @@ -490,6 +496,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "calculator", toolCallId: "call1", + input: { operation: "add", a: 1, b: 2 }, args: { operation: "add", a: 1, b: 2 }, }, ], @@ -561,6 +568,9 @@ describe("toUIMessages", () => { text: "**Finding the Time**\n\nI've pinpointed the core task: obtaining the current time in Paris. It involves using the `dateTime` tool. I've identified \"Europe/Paris\" as the necessary timezone identifier to provide to the tool. My next step is to test the tool.\n\n\n", }, { + input: { + timezone: "Europe/Paris", + }, args: { timezone: "Europe/Paris", }, @@ -690,6 +700,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "calculator", toolCallId: "call1", + input: { operation: "add", a: 40, b: 2 }, args: { operation: "add", a: 40, b: 2 }, }, ], @@ -744,6 +755,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "generateImage", toolCallId: "call1", + input: { id: "invalid-id" }, args: { id: "invalid-id" }, }, ], @@ -898,6 +910,7 @@ describe("toUIMessages", () => { type: "tool-call", toolName: "myTool", toolCallId: "call1", + input: {}, args: {}, }, ], diff --git a/src/validators.ts b/src/validators.ts index f7ecea38..f8e03132 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -115,17 +115,34 @@ export const vSourcePart = v.union( ); export type SourcePart = Infer; -export const vToolCallPart = v.object({ - type: v.literal("tool-call"), - toolCallId: v.string(), - toolName: v.string(), - input: v.any(), - /** @deprecated Use `input` instead. */ - args: v.optional(v.any()), - providerExecuted: v.optional(v.boolean()), - providerOptions, - providerMetadata, -}); +// Union type to support both old (args) and new (input) formats +// Both include input for type hint support +export const vToolCallPart = v.union( + // New format: input is primary, args is optional for backwards compat + v.object({ + type: v.literal("tool-call"), + toolCallId: v.string(), + toolName: v.string(), + input: v.any(), + /** @deprecated Use `input` instead. */ + args: v.optional(v.any()), + providerExecuted: v.optional(v.boolean()), + providerOptions, + providerMetadata, + }), + // Legacy format: args is present, input is optional + v.object({ + type: v.literal("tool-call"), + toolCallId: v.string(), + toolName: v.string(), + /** @deprecated Use `input` instead. */ + args: v.any(), + input: v.optional(v.any()), + providerExecuted: v.optional(v.boolean()), + providerOptions, + providerMetadata, + }), +); const vToolResultContent = v.array( v.union(