-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
test(node): Cover Vercel AI v7 cache tokens from the SDK usage object #24358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import * as Sentry from '@sentry/node'; | ||
| import { generateText } from 'ai'; | ||
| import { MockLanguageModelV3 } from 'ai/test'; | ||
|
|
||
| // Calls routed through the Vercel AI Gateway carry a `gateway` key in `providerMetadata` instead of a | ||
| // provider name, so cache counts can only be derived from the SDK's normalized usage object. | ||
| async function run() { | ||
| await Sentry.startSpan({ op: 'function', name: 'main' }, async () => { | ||
| await generateText({ | ||
| experimental_telemetry: { isEnabled: true, recordInputs: true, recordOutputs: true }, | ||
| model: new MockLanguageModelV3({ | ||
| doGenerate: async () => ({ | ||
| finishReason: { unified: 'stop', raw: 'stop' }, | ||
| usage: { | ||
| inputTokens: { total: 120, noCache: 20, cacheRead: 80, cacheWrite: 20 }, | ||
| outputTokens: { total: 10, noCache: 10, cached: 0 }, | ||
| totalTokens: { total: 130, noCache: 30, cached: 100 }, | ||
| }, | ||
| content: [{ type: 'text', text: 'Cache token span!' }], | ||
| warnings: [], | ||
| providerMetadata: { | ||
| gateway: { routing: {} }, | ||
| }, | ||
| }), | ||
| }), | ||
| messages: [{ role: 'user', content: 'Tell me something' }], | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| run(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ import { | |
| GEN_AI_TOOL_DEFINITIONS, | ||
| GEN_AI_TOOL_DESCRIPTION, | ||
| GEN_AI_TOOL_NAME, | ||
| GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, | ||
| GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, | ||
| GEN_AI_USAGE_INPUT_TOKENS, | ||
| GEN_AI_USAGE_OUTPUT_TOKENS, | ||
|
|
@@ -811,6 +812,43 @@ describe.each(matrix)('Vercel AI integration (version %s)', (version, vercelAiVe | |
| }, | ||
| ); | ||
|
|
||
| createEsmTests( | ||
| __dirname, | ||
| 'scenario-cache-tokens.mjs', | ||
| 'instrument.mjs', | ||
| (createRunner, test) => { | ||
| test('reads cache token counts from the SDK usage object', async () => { | ||
| await createRunner() | ||
| .expect({ transaction: { transaction: 'main' } }) | ||
| .expect({ | ||
| span: container => { | ||
| const generateContent = container.items.find( | ||
| span => span.attributes['sentry.op']?.value === 'gen_ai.generate_content', | ||
| )!; | ||
| expect(generateContent).toBeDefined(); | ||
| expect(generateContent.attributes[GEN_AI_USAGE_INPUT_TOKENS]?.value).toBe(120); | ||
| expect(generateContent.attributes[GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS]?.value).toBe(80); | ||
| expect(generateContent.attributes[GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS]?.value).toBe(20); | ||
|
|
||
| const invokeAgent = container.items.find( | ||
| span => span.attributes['sentry.op']?.value === 'gen_ai.invoke_agent', | ||
| )!; | ||
| expect(invokeAgent).toBeDefined(); | ||
| expect(invokeAgent.attributes[GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS]?.value).toBe(80); | ||
| expect(invokeAgent.attributes[GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS]?.value).toBe(20); | ||
| }, | ||
| }) | ||
| .start() | ||
| .completed(); | ||
| }); | ||
|
Comment on lines
+833
to
+843
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The test Suggested FixWrap the test case Prompt for AI AgentDid we get this right? 👍 / 👎 to inform future reviews. |
||
| }, | ||
| { | ||
| additionalDependencies: { | ||
| ai: vercelAiVersion, | ||
| }, | ||
| }, | ||
| ); | ||
|
|
||
| createEsmTests( | ||
| __dirname, | ||
| 'scenario-embeddings.mjs', | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cache token test not skipped on v6
Medium Severity
The new cache-token test is registered for both matrix versions, but v6 cannot derive cache counts from this gateway scenario. Nearby version-specific cases use
test.skipIf, so the v6 entry will assertgen_ai.usage.input_tokens.cache_readandcache_creationvalues that that path never writes.Triggered by project rule: PR Review Guidelines for Cursor Bot
Reviewed by Cursor Bugbot for commit 58c1aaa. Configure here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems to work just fine