weflayr 0.22.0 → 0.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.prettierignore +2 -0
  2. package/dist/api/caseConversion.d.ts +16 -0
  3. package/dist/api/caseConversion.js +45 -0
  4. package/dist/api/generated/client/client.gen.d.ts +2 -0
  5. package/dist/api/generated/client/client.gen.js +220 -0
  6. package/dist/api/generated/client/index.d.ts +10 -0
  7. package/dist/api/generated/client/index.js +17 -0
  8. package/dist/api/generated/client/types.gen.d.ts +120 -0
  9. package/dist/api/generated/client/types.gen.js +3 -0
  10. package/dist/api/generated/client/utils.gen.d.ts +37 -0
  11. package/dist/api/generated/client/utils.gen.js +239 -0
  12. package/dist/api/generated/client.gen.d.ts +12 -0
  13. package/dist/api/generated/client.gen.js +6 -0
  14. package/dist/api/generated/core/auth.gen.d.ts +25 -0
  15. package/dist/api/generated/core/auth.gen.js +18 -0
  16. package/dist/api/generated/core/bodySerializer.gen.d.ts +25 -0
  17. package/dist/api/generated/core/bodySerializer.gen.js +60 -0
  18. package/dist/api/generated/core/params.gen.d.ts +43 -0
  19. package/dist/api/generated/core/params.gen.js +112 -0
  20. package/dist/api/generated/core/pathSerializer.gen.d.ts +33 -0
  21. package/dist/api/generated/core/pathSerializer.gen.js +115 -0
  22. package/dist/api/generated/core/queryKeySerializer.gen.d.ts +18 -0
  23. package/dist/api/generated/core/queryKeySerializer.gen.js +98 -0
  24. package/dist/api/generated/core/serverSentEvents.gen.d.ts +71 -0
  25. package/dist/api/generated/core/serverSentEvents.gen.js +135 -0
  26. package/dist/api/generated/core/types.gen.d.ts +83 -0
  27. package/dist/api/generated/core/types.gen.js +3 -0
  28. package/dist/api/generated/core/utils.gen.d.ts +19 -0
  29. package/dist/api/generated/core/utils.gen.js +93 -0
  30. package/dist/api/generated/facade.gen.d.ts +153 -0
  31. package/dist/api/generated/facade.gen.js +49 -0
  32. package/dist/api/generated/index.d.ts +2 -0
  33. package/dist/api/generated/index.js +14 -0
  34. package/dist/api/generated/sdk.gen.d.ts +51 -0
  35. package/dist/api/generated/sdk.gen.js +98 -0
  36. package/dist/api/generated/types.gen.d.ts +652 -0
  37. package/dist/api/generated/types.gen.js +3 -0
  38. package/dist/api/index.d.ts +27 -0
  39. package/dist/api/index.js +48 -0
  40. package/dist/api/makeEndpoint.d.ts +27 -0
  41. package/dist/api/makeEndpoint.js +37 -0
  42. package/index.d.ts +24 -15
  43. package/openapi-ts.config.mjs +9 -0
  44. package/package.json +9 -2
  45. package/scripts/generate_facade.mjs +86 -0
  46. package/src/api/caseConversion.ts +58 -0
  47. package/src/api/generated/client/client.gen.ts +277 -0
  48. package/src/api/generated/client/index.ts +27 -0
  49. package/src/api/generated/client/types.gen.ts +218 -0
  50. package/src/api/generated/client/utils.gen.ts +316 -0
  51. package/src/api/generated/client.gen.ts +16 -0
  52. package/src/api/generated/core/auth.gen.ts +48 -0
  53. package/src/api/generated/core/bodySerializer.gen.ts +82 -0
  54. package/src/api/generated/core/params.gen.ts +178 -0
  55. package/src/api/generated/core/pathSerializer.gen.ts +171 -0
  56. package/src/api/generated/core/queryKeySerializer.gen.ts +117 -0
  57. package/src/api/generated/core/serverSentEvents.gen.ts +242 -0
  58. package/src/api/generated/core/types.gen.ts +110 -0
  59. package/src/api/generated/core/utils.gen.ts +140 -0
  60. package/src/api/generated/facade.gen.ts +62 -0
  61. package/src/api/generated/index.ts +4 -0
  62. package/src/api/generated/sdk.gen.ts +112 -0
  63. package/src/api/generated/types.gen.ts +718 -0
  64. package/src/api/index.ts +45 -0
  65. package/src/api/makeEndpoint.ts +54 -0
  66. package/src/auto-instrument.js +19 -6
  67. package/src/index.js +5 -0
  68. package/src/instrumentation/google/get_provider_name.js +2 -1
  69. package/src/instrumentation/vercel/full_instrumentation.js +44 -0
  70. package/src/otel/propagation.js +21 -12
  71. package/src/otel/span-processor.js +11 -1
  72. package/src/otel/vercel-ai-sdk-span-filter.js +79 -0
  73. package/tests/api/index.test.js +361 -0
  74. package/tests/index.test.js +48 -15
  75. package/tests/instrumentation/vercel/full_instrumentation.test.js +16 -0
  76. package/tests/otel/vercel-ai-sdk-span-filter.test.js +159 -0
  77. package/tsconfig.json +18 -0
@@ -0,0 +1,159 @@
1
+ 'use strict';
2
+
3
+ // The Vercel AI SDK emits aggregate spans around each model call (see
4
+ // src/otel/vercel-ai-sdk-span-filter.js). These tests drive real spans through
5
+ // the WeflayrSpanProcessor and assert exactly one span per model call is
6
+ // exported, for both the ai >= 7 semconv shape and the legacy ai.* shape.
7
+
8
+ const test = require('node:test');
9
+ const assert = require('node:assert/strict');
10
+ const { context, trace } = require('@opentelemetry/api');
11
+ const { BasicTracerProvider, InMemorySpanExporter } = require('@opentelemetry/sdk-trace-base');
12
+
13
+ const { WeflayrSpanProcessor } = require('../../src/otel/span-processor');
14
+
15
+ function buildProviderWithExporter() {
16
+ const exporter = new InMemorySpanExporter();
17
+ const provider = new BasicTracerProvider({
18
+ spanProcessors: [new WeflayrSpanProcessor({ exporter, exportMode: 'immediate' })],
19
+ });
20
+ return { exporter, provider };
21
+ }
22
+
23
+ function startChildSpan(tracer, parentSpan, name, attributes) {
24
+ const parentContext = trace.setSpan(context.active(), parentSpan);
25
+ return tracer.startSpan(name, { attributes }, parentContext);
26
+ }
27
+
28
+ test('semconv shape: only the chat span is exported, not invoke_agent/step/tool', () => {
29
+ const { exporter, provider } = buildProviderWithExporter();
30
+ const tracer = provider.getTracer('gen_ai');
31
+
32
+ const invokeAgent = tracer.startSpan('invoke_agent openai/gpt-4o-mini', {
33
+ attributes: {
34
+ 'gen_ai.operation.name': 'invoke_agent',
35
+ 'gen_ai.usage.input_tokens': 50,
36
+ 'gen_ai.usage.output_tokens': 15,
37
+ },
38
+ });
39
+ const step = startChildSpan(tracer, invokeAgent, 'step 1', {
40
+ 'gen_ai.operation.name': 'agent_step',
41
+ });
42
+ const chat = startChildSpan(tracer, step, 'chat openai/gpt-4o-mini', {
43
+ 'gen_ai.operation.name': 'chat',
44
+ 'gen_ai.usage.input_tokens': 50,
45
+ 'gen_ai.usage.output_tokens': 15,
46
+ });
47
+ const tool = startChildSpan(tracer, step, 'execute_tool get_weather', {
48
+ 'gen_ai.operation.name': 'execute_tool',
49
+ });
50
+
51
+ chat.end();
52
+ tool.end();
53
+ step.end();
54
+ invokeAgent.end();
55
+
56
+ const exported = exporter.getFinishedSpans();
57
+ assert.equal(exported.length, 1);
58
+ assert.equal(exported[0].name, 'chat openai/gpt-4o-mini');
59
+ });
60
+
61
+ test('semconv shape: nested embeddings span is dropped, the outer one is exported', () => {
62
+ const { exporter, provider } = buildProviderWithExporter();
63
+ const tracer = provider.getTracer('gen_ai');
64
+
65
+ const outerEmbeddings = tracer.startSpan('embeddings openai/text-embedding-3-small', {
66
+ attributes: {
67
+ 'gen_ai.operation.name': 'embeddings',
68
+ 'gen_ai.usage.input_tokens': 2,
69
+ },
70
+ });
71
+ const modelCallEmbeddings = startChildSpan(
72
+ tracer,
73
+ outerEmbeddings,
74
+ 'embeddings openai/text-embedding-3-small',
75
+ {
76
+ 'gen_ai.operation.name': 'embeddings',
77
+ 'gen_ai.usage.input_tokens': 2,
78
+ }
79
+ );
80
+
81
+ modelCallEmbeddings.end();
82
+ outerEmbeddings.end();
83
+
84
+ const exported = exporter.getFinishedSpans();
85
+ assert.equal(exported.length, 1);
86
+ assert.equal(exported[0].spanContext().spanId, outerEmbeddings.spanContext().spanId);
87
+ });
88
+
89
+ test('legacy shape: only ai.<fn>.do* spans are exported', () => {
90
+ const { exporter, provider } = buildProviderWithExporter();
91
+ const tracer = provider.getTracer('ai');
92
+
93
+ const outer = tracer.startSpan('ai.streamText', {
94
+ attributes: { 'ai.usage.inputTokens': 100 },
95
+ });
96
+ const doStream = startChildSpan(tracer, outer, 'ai.streamText.doStream', {
97
+ 'gen_ai.usage.input_tokens': 100,
98
+ });
99
+ const toolCall = startChildSpan(tracer, outer, 'ai.toolCall', {});
100
+ const doEmbed = tracer.startSpan('ai.embed.doEmbed', {
101
+ attributes: { 'gen_ai.usage.input_tokens': 1 },
102
+ });
103
+
104
+ doStream.end();
105
+ toolCall.end();
106
+ doEmbed.end();
107
+ outer.end();
108
+
109
+ const exported = exporter.getFinishedSpans().map((span) => span.name);
110
+ assert.deepEqual(exported.sort(), ['ai.embed.doEmbed', 'ai.streamText.doStream']);
111
+ });
112
+
113
+ test('gateway provider id gets the weflayr override, direct providers do not', () => {
114
+ const { exporter, provider } = buildProviderWithExporter();
115
+ const tracer = provider.getTracer('gen_ai');
116
+
117
+ const gatewayChat = tracer.startSpan('chat openai/gpt-4o-mini', {
118
+ attributes: { 'gen_ai.operation.name': 'chat', 'gen_ai.provider.name': 'gateway' },
119
+ });
120
+ gatewayChat.end();
121
+ const directChat = tracer.startSpan('chat gpt-4o-mini', {
122
+ attributes: { 'gen_ai.operation.name': 'chat', 'gen_ai.provider.name': 'openai' },
123
+ });
124
+ directChat.end();
125
+
126
+ const [gatewayExported, directExported] = exporter.getFinishedSpans();
127
+ assert.equal(gatewayExported.attributes['weflayr.provider_name'], 'vercel_ai_gateway');
128
+ assert.equal(directExported.attributes['weflayr.provider_name'], undefined);
129
+ });
130
+
131
+ test('gateway provider id does not overwrite a propagateMetadata providerName', () => {
132
+ const { exporter, provider } = buildProviderWithExporter();
133
+ const tracer = provider.getTracer('gen_ai');
134
+
135
+ const chat = tracer.startSpan('chat openai/gpt-4o-mini', {
136
+ attributes: {
137
+ 'gen_ai.operation.name': 'chat',
138
+ 'gen_ai.provider.name': 'gateway',
139
+ 'weflayr.provider_name': 'openai',
140
+ },
141
+ });
142
+ chat.end();
143
+
144
+ assert.equal(exporter.getFinishedSpans()[0].attributes['weflayr.provider_name'], 'openai');
145
+ });
146
+
147
+ test('non-Vercel scopes still go through the default export filter', () => {
148
+ const { exporter, provider } = buildProviderWithExporter();
149
+
150
+ const llmSpan = provider
151
+ .getTracer('@traceloop/instrumentation-openai')
152
+ .startSpan('openai.chat', { attributes: { 'gen_ai.system': 'openai' } });
153
+ llmSpan.end();
154
+ const unrelatedSpan = provider.getTracer('my-app').startSpan('http request');
155
+ unrelatedSpan.end();
156
+
157
+ const exported = exporter.getFinishedSpans().map((span) => span.name);
158
+ assert.deepEqual(exported, ['openai.chat']);
159
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ // First TypeScript module of the SDK: only src/api is compiled (to dist/);
3
+ // the rest of src stays plain JavaScript until it is migrated.
4
+ "compilerOptions": {
5
+ "target": "ES2022",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "module": "NodeNext",
8
+ "moduleResolution": "NodeNext",
9
+ "rootDir": "src",
10
+ "outDir": "dist",
11
+ "declaration": true,
12
+ "strict": true,
13
+ "esModuleInterop": true,
14
+ "skipLibCheck": true,
15
+ "types": ["node"]
16
+ },
17
+ "include": ["src/api"]
18
+ }