diff --git a/package.json b/package.json index d71c55b..73b2b42 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@requesty/ai-sdk", - "version": "3.2.0", + "version": "3.3.0", "license": "Apache-2.0", "sideEffects": false, "main": "./dist/index.js", diff --git a/src/e2e/usage.test.ts b/src/e2e/usage.test.ts new file mode 100644 index 0000000..43265b8 --- /dev/null +++ b/src/e2e/usage.test.ts @@ -0,0 +1,45 @@ +import { generateText, streamText } from 'ai' +import { describe, expect, it } from 'vitest' +import { createRequesty } from '..' +import { getTestModels } from './get-models' + +const requesty = createRequesty({ + apiKey: process.env.REQUESTY_API_KEY, + baseURL: process.env.REQUESTY_BASE_URL, +}) + +const modelsToTest = getTestModels() + +describe.concurrent.each(modelsToTest)('Usage and Cost', ({ id }) => { + const model = requesty.chat(id) + + describe.skip('generateText', () => { + it('should return cost in response', async () => { + const result = await generateText({ + model, + prompt: 'Say hello in one word.', + maxOutputTokens: 100, + temperature: 0.3, + }) + + const raw = result.usage.raw + expect(raw).toBeDefined() + expect(raw!.cost).toBeTypeOf('number') + }) + }) + + describe('streamText', () => { + it('should return cost in response', async () => { + const result = streamText({ + model, + prompt: 'Say hello in one word.', + maxOutputTokens: 100, + temperature: 0.3, + }) + + const raw = (await result.usage).raw + expect(raw).toBeDefined() + expect(raw!.cost).toBeTypeOf('number') + }) + }) +}) diff --git a/src/stream/index.test.ts b/src/stream/index.test.ts index 9180da4..7608f47 100644 --- a/src/stream/index.test.ts +++ b/src/stream/index.test.ts @@ -224,6 +224,14 @@ describe('stream', () => { cacheWrite: 5, }, outputTokens: { total: 20, reasoning: 0, text: 20 }, + raw: { + completion_tokens: 20, + prompt_tokens: 10, + prompt_tokens_details: { + caching_tokens: 5, + }, + total_tokens: 30, + }, }) expect(requestyUsage.set).toHaveBeenCalledWith({ cachingTokens: 5, @@ -495,6 +503,7 @@ describe('stream', () => { cacheWrite: 0, }, outputTokens: { total: 0, reasoning: 0, text: 0 }, + raw: {}, }) expect(requestyUsage.set).toHaveBeenCalledWith({ cachingTokens: 0, diff --git a/src/usage/adapt.test.ts b/src/usage/adapt.test.ts index 40b778b..a944052 100644 --- a/src/usage/adapt.test.ts +++ b/src/usage/adapt.test.ts @@ -30,6 +30,15 @@ describe('getUsage', () => { text: 50, reasoning: 0, }, + raw: { + completion_tokens: 50, + prompt_tokens: 100, + prompt_tokens_details: { + cached_tokens: 20, + caching_tokens: 10, + }, + total_tokens: 150, + }, }) }) @@ -53,6 +62,10 @@ describe('getUsage', () => { text: 50, reasoning: 0, }, + raw: { + completion_tokens: 50, + prompt_tokens: 100, + }, }) }) @@ -73,6 +86,7 @@ describe('getUsage', () => { text: 0, reasoning: 0, }, + raw: undefined, }) }) @@ -93,6 +107,7 @@ describe('getUsage', () => { text: 0, reasoning: 0, }, + raw: {}, }) }) @@ -119,6 +134,13 @@ describe('getUsage', () => { text: 50, reasoning: 0, }, + raw: { + completion_tokens: 50, + prompt_tokens: 100, + prompt_tokens_details: { + cached_tokens: 20, + }, + }, }) }) @@ -160,6 +182,14 @@ describe('getUsage', () => { text: 0, reasoning: 0, }, + raw: { + completion_tokens: 0, + prompt_tokens: 0, + prompt_tokens_details: { + cached_tokens: 0, + caching_tokens: 0, + }, + }, }) }) @@ -187,6 +217,14 @@ describe('getUsage', () => { text: 500000, reasoning: 0, }, + raw: { + completion_tokens: 500000, + prompt_tokens: 1000000, + prompt_tokens_details: { + cached_tokens: 200000, + caching_tokens: 100000, + }, + }, }) }) }) diff --git a/src/usage/adapt.ts b/src/usage/adapt.ts index e4350d4..b0f6685 100644 --- a/src/usage/adapt.ts +++ b/src/usage/adapt.ts @@ -27,5 +27,6 @@ export const adaptUsage = ( // TODO adapt reasoning usage reasoning: 0, }, + raw: requestyUsage, } } diff --git a/src/usage/schema.ts b/src/usage/schema.ts index 05dc546..efd9b99 100644 --- a/src/usage/schema.ts +++ b/src/usage/schema.ts @@ -11,5 +11,6 @@ export const RequestyUsageSchema = z cached_tokens: z.number().optional(), }) .optional(), + cost: z.number().positive().optional(), }) .optional()