diff --git a/package.json b/package.json index 759dfd6bee..edfa87eb42 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,8 @@ "rollup": "4.60.4", "vite": "8.1.0", "undici": "6.28.1", + "@ai-sdk/provider@3": "3.0.13", + "@ai-sdk/provider-utils@4": "4.0.35", "form-data": ">=4.0.4", "bluebird": ">=3.7.2", "glob": "11.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ad1c7eff4..75c6c8ee54 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,8 @@ overrides: rollup: 4.60.4 vite: 8.1.0 undici: 6.28.1 + '@ai-sdk/provider@3': 3.0.13 + '@ai-sdk/provider-utils@4': 4.0.35 form-data: '>=4.0.4' bluebird: '>=3.7.2' glob: 11.1.0 @@ -372,7 +374,7 @@ importers: dependencies: ai-sdk-provider-poe: specifier: 2.0.18 - version: 2.0.18(ai@6.0.218(zod@3.25.76))(zod@3.25.76) + version: 2.0.18(ai@7.0.137(zod@3.25.76))(zod@3.25.76) zod: specifier: 3.25.76 version: 3.25.76 @@ -466,7 +468,7 @@ importers: version: 4.9.3 ai-sdk-provider-poe: specifier: 2.0.18 - version: 2.0.18(ai@6.0.218(zod@3.25.76))(zod@3.25.76) + version: 2.0.18(ai@7.0.137(zod@3.25.76))(zod@3.25.76) async-mutex: specifier: ^0.5.0 version: 0.5.0 @@ -673,8 +675,8 @@ importers: specifier: 3.9.2 version: 3.9.2 ai: - specifier: 6.0.218 - version: 6.0.218(zod@3.25.76) + specifier: 7.0.137 + version: 7.0.137(zod@3.25.76) esbuild-wasm: specifier: 0.28.1 version: 0.28.1 @@ -973,9 +975,9 @@ packages: peerDependencies: zod: 3.25.76 - '@ai-sdk/gateway@3.0.142': - resolution: {integrity: sha512-Y1iwdxdebYXpoK5y/4CrcCfJGeFwEJWlEx+pMWIg/ZVWGi9KA+JXM7YBkhxcshpq/jAXx8YyQeFMyZr0TGfXZQ==} - engines: {node: '>=18'} + '@ai-sdk/gateway@4.0.110': + resolution: {integrity: sha512-5IwnOR6v7KC+D9eddUqsCobXl/FbLUVb2LaQc/uyuQdpP3/n9s0YLc9zl4/W3IS/R2pjHrqUfCzEAeOu7bFLoQ==} + engines: {node: '>=22'} peerDependencies: zod: 3.25.76 @@ -991,15 +993,15 @@ packages: peerDependencies: zod: 3.25.76 - '@ai-sdk/provider-utils@4.0.14': - resolution: {integrity: sha512-7bzKd9lgiDeXM7O4U4nQ8iTxguAOkg8LZGD9AfDVZYjO5cKYRwBPwVjboFcVrxncRHu0tYxZtXZtiLKpG4pEng==} + '@ai-sdk/provider-utils@4.0.35': + resolution: {integrity: sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg==} engines: {node: '>=18'} peerDependencies: zod: 3.25.76 - '@ai-sdk/provider-utils@4.0.35': - resolution: {integrity: sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg==} - engines: {node: '>=18'} + '@ai-sdk/provider-utils@5.0.58': + resolution: {integrity: sha512-iXSwKR/7LpHzAlyrUl+bTinwzmZ3Nmup1viwPisM5Gn5cogRdIG4rV9w1ZDuKFcrXyu/AeVs42E1CX/0aNwrfQ==} + engines: {node: '>=22'} peerDependencies: zod: 3.25.76 @@ -1007,9 +1009,9 @@ packages: resolution: {integrity: sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw==} engines: {node: '>=18'} - '@ai-sdk/provider@3.0.8': - resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==} - engines: {node: '>=18'} + '@ai-sdk/provider@4.0.26': + resolution: {integrity: sha512-BZ443uBEq6HuMA+Z4b7Hpm65GpZSo7pWqnYqpf/7tAO3C48JbtvAhOE2JnODFj+jodsZzfRHkAyQb64xuD2tZQ==} + engines: {node: '>=22'} '@alcalzone/ansi-tokenize@0.2.5': resolution: {integrity: sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw==} @@ -3825,6 +3827,9 @@ packages: peerDependencies: react: '>=16.9.0' + '@workflow/serde@4.1.0': + resolution: {integrity: sha512-pav4F2BoirECWR7Nf1TKt+2eETcBj7jj4cBefQ8VXQCA6NPkaKeLfj/zMgi+3zYV5ZIBT4GuUiphsj0/b9hPQQ==} + '@xmldom/xmldom@0.8.15': resolution: {integrity: sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==} engines: {node: '>=10.0.0'} @@ -3871,9 +3876,9 @@ packages: peerDependencies: ai: '>=6.0.0' - ai@6.0.218: - resolution: {integrity: sha512-HsyCUNaaYgX/b/kGOoYfKkqfT1HvpUKKDb8YkN1FKeCNZjKdqXLGY+cKBpYGIRAvsPuOHskxLxZ46cK1dTBWQQ==} - engines: {node: '>=18'} + ai@7.0.137: + resolution: {integrity: sha512-JxrPkSQknxIN/gYqS3UQksExS6eWI23QMPBrKMGXeeFHhru6xFtF4MuMq17WaHD+lXPh0lne6H0BM2Z2VMW9EQ==} + engines: {node: '>=22'} peerDependencies: zod: 3.25.76 @@ -8972,14 +8977,14 @@ snapshots: '@ai-sdk/anthropic@3.0.42(zod@3.25.76)': dependencies: - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.14(zod@3.25.76) + '@ai-sdk/provider': 3.0.13 + '@ai-sdk/provider-utils': 4.0.35(zod@3.25.76) zod: 3.25.76 - '@ai-sdk/gateway@3.0.142(zod@3.25.76)': + '@ai-sdk/gateway@4.0.110(zod@3.25.76)': dependencies: - '@ai-sdk/provider': 3.0.13 - '@ai-sdk/provider-utils': 4.0.35(zod@3.25.76) + '@ai-sdk/provider': 4.0.26 + '@ai-sdk/provider-utils': 5.0.58(zod@3.25.76) '@vercel/oidc': 3.2.0 zod: 3.25.76 @@ -8991,29 +8996,31 @@ snapshots: '@ai-sdk/openai@3.0.27(zod@3.25.76)': dependencies: - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.14(zod@3.25.76) + '@ai-sdk/provider': 3.0.13 + '@ai-sdk/provider-utils': 4.0.35(zod@3.25.76) zod: 3.25.76 - '@ai-sdk/provider-utils@4.0.14(zod@3.25.76)': + '@ai-sdk/provider-utils@4.0.35(zod@3.25.76)': dependencies: - '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider': 3.0.13 '@standard-schema/spec': 1.1.0 eventsource-parser: 3.1.0 zod: 3.25.76 - '@ai-sdk/provider-utils@4.0.35(zod@3.25.76)': + '@ai-sdk/provider-utils@5.0.58(zod@3.25.76)': dependencies: - '@ai-sdk/provider': 3.0.13 + '@ai-sdk/provider': 4.0.26 '@standard-schema/spec': 1.1.0 + '@workflow/serde': 4.1.0 eventsource-parser: 3.1.0 + undici: 6.28.1 zod: 3.25.76 '@ai-sdk/provider@3.0.13': dependencies: json-schema: 0.4.0 - '@ai-sdk/provider@3.0.8': + '@ai-sdk/provider@4.0.26': dependencies: json-schema: 0.4.0 @@ -10497,7 +10504,8 @@ snapshots: '@open-draft/until@2.1.0': {} - '@opentelemetry/api@1.9.0': {} + '@opentelemetry/api@1.9.0': + optional: true '@oxc-project/types@0.137.0': {} @@ -12188,6 +12196,8 @@ snapshots: react: 18.3.1 tslib: 2.8.1 + '@workflow/serde@4.1.0': {} + '@xmldom/xmldom@0.8.15': {} '@xobotyi/scrollbar-width@1.9.5': {} @@ -12224,23 +12234,22 @@ snapshots: agent-base@7.1.3: {} - ai-sdk-provider-poe@2.0.18(ai@6.0.218(zod@3.25.76))(zod@3.25.76): + ai-sdk-provider-poe@2.0.18(ai@7.0.137(zod@3.25.76))(zod@3.25.76): dependencies: '@ai-sdk/anthropic': 3.0.42(zod@3.25.76) '@ai-sdk/openai': 3.0.27(zod@3.25.76) '@ai-sdk/openai-compatible': 2.0.56(zod@3.25.76) - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.14(zod@3.25.76) - ai: 6.0.218(zod@3.25.76) + '@ai-sdk/provider': 3.0.13 + '@ai-sdk/provider-utils': 4.0.35(zod@3.25.76) + ai: 7.0.137(zod@3.25.76) transitivePeerDependencies: - zod - ai@6.0.218(zod@3.25.76): + ai@7.0.137(zod@3.25.76): dependencies: - '@ai-sdk/gateway': 3.0.142(zod@3.25.76) - '@ai-sdk/provider': 3.0.13 - '@ai-sdk/provider-utils': 4.0.35(zod@3.25.76) - '@opentelemetry/api': 1.9.0 + '@ai-sdk/gateway': 4.0.110(zod@3.25.76) + '@ai-sdk/provider': 4.0.26 + '@ai-sdk/provider-utils': 5.0.58(zod@3.25.76) zod: 3.25.76 ajv-formats@3.0.1(ajv@8.20.0): diff --git a/src/api/providers/__tests__/openai-compatible.spec.ts b/src/api/providers/__tests__/openai-compatible.spec.ts index 71cf93b343..78a5a43576 100644 --- a/src/api/providers/__tests__/openai-compatible.spec.ts +++ b/src/api/providers/__tests__/openai-compatible.spec.ts @@ -120,6 +120,36 @@ describe("OpenAICompatibleHandler", () => { expect(textChunks[0].text).toBe("Test response") }) + it("should map cache read and reasoning tokens from ai v7 usage details", async () => { + async function* mockFullStream() { + yield { type: "text-delta", text: "ok" } + } + + mockStreamText.mockReturnValue({ + fullStream: mockFullStream(), + usage: Promise.resolve({ + inputTokens: 20, + outputTokens: 10, + inputTokenDetails: { cacheReadTokens: 7 }, + outputTokenDetails: { reasoningTokens: 4 }, + raw: {}, + }), + }) + + const chunks: ApiStreamChunk[] = [] + for await (const chunk of handler.createMessage(systemPrompt, messages)) { + chunks.push(chunk) + } + + expect(chunks.find((chunk) => chunk.type === "usage")).toEqual({ + type: "usage", + inputTokens: 20, + outputTokens: 10, + cacheReadTokens: 7, + reasoningTokens: 4, + }) + }) + it("should handle multiple stream parts and yield usage metrics", async () => { async function* mockFullStream() { yield { type: "text-delta", text: "First part" } diff --git a/src/api/providers/openai-compatible.ts b/src/api/providers/openai-compatible.ts index a781acb811..e2dbfae237 100644 --- a/src/api/providers/openai-compatible.ts +++ b/src/api/providers/openai-compatible.ts @@ -89,18 +89,16 @@ export abstract class OpenAICompatibleHandler extends BaseProvider implements Si protected processUsageMetrics(usage: { inputTokens?: number outputTokens?: number - details?: { - cachedInputTokens?: number - reasoningTokens?: number - } + inputTokenDetails?: { cacheReadTokens?: number } + outputTokenDetails?: { reasoningTokens?: number } raw?: Record }): ApiStreamUsageChunk { return { type: "usage", inputTokens: usage.inputTokens || 0, outputTokens: usage.outputTokens || 0, - cacheReadTokens: usage.details?.cachedInputTokens, - reasoningTokens: usage.details?.reasoningTokens, + cacheReadTokens: usage.inputTokenDetails?.cacheReadTokens, + reasoningTokens: usage.outputTokenDetails?.reasoningTokens, } } diff --git a/src/package.json b/src/package.json index 353fc40c40..fb4cb26abc 100644 --- a/src/package.json +++ b/src/package.json @@ -559,7 +559,7 @@ "@types/vscode": "1.100.0", "@vitest/coverage-v8": "4.1.9", "@vscode/vsce": "3.9.2", - "ai": "6.0.218", + "ai": "7.0.137", "esbuild-wasm": "0.28.1", "execa": "9.6.1", "mkdirp": "3.0.1",