@brizz/sdk 0.1.3-rc.0 → 0.1.3

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.
package/README.md CHANGED
@@ -73,6 +73,7 @@ const { openai } = require('@ai-sdk/openai');
73
73
  generateText({
74
74
  model: openai('gpt-3.5-turbo'),
75
75
  prompt: 'Hello, world!',
76
+ experimental_telemetry: { isEnabled: true },
76
77
  }).then(result => console.log(result.text));
77
78
  ```
78
79
 
@@ -136,6 +137,7 @@ import { openai } from '@ai-sdk/openai';
136
137
  const result = await generateText({
137
138
  model: openai('gpt-3.5-turbo'),
138
139
  prompt: 'Hello, world!',
140
+ experimental_telemetry: { isEnabled: true },
139
141
  });
140
142
  ```
141
143
 
@@ -174,6 +176,7 @@ The SDK automatically instruments:
174
176
  - **OpenAI** - `openai` package
175
177
  - **Anthropic** - `@anthropic-ai/sdk` package
176
178
  - **Vercel AI SDK** - `ai` package (generateText, streamText, etc.)
179
+ - Requires `experimental_telemetry: { isEnabled: true }` in function calls
177
180
  - **LangChain** - `langchain` and `@langchain/*` packages
178
181
  - **LlamaIndex** - `llamaindex` package
179
182
  - **AWS Bedrock** - `@aws-sdk/client-bedrock-runtime`
@@ -181,6 +184,35 @@ The SDK automatically instruments:
181
184
  - **Vector Databases** - Pinecone, Qdrant, ChromaDB
182
185
  - **HTTP/Fetch** - Automatic network request tracing
183
186
 
187
+ ### Vercel AI SDK Integration
188
+
189
+ For Vercel AI SDK instrumentation, you need to enable telemetry in your function calls:
190
+
191
+ ```typescript
192
+ import { generateText, streamText } from 'ai';
193
+ import { openai } from '@ai-sdk/openai';
194
+
195
+ // For generateText
196
+ const result = await generateText({
197
+ model: openai('gpt-4'),
198
+ prompt: 'Hello, world!',
199
+ experimental_telemetry: { isEnabled: true }, // Required for instrumentation
200
+ });
201
+
202
+ // For streamText
203
+ const stream = streamText({
204
+ model: openai('gpt-4'),
205
+ messages: [{ role: 'user', content: 'Hello!' }],
206
+ experimental_telemetry: { isEnabled: true }, // Required for instrumentation
207
+ });
208
+ ```
209
+
210
+ This enables automatic tracing of:
211
+ - Model calls and responses
212
+ - Token usage and costs
213
+ - Tool calls and executions
214
+ - Streaming data
215
+
184
216
  ## PII Protection & Data Masking
185
217
 
186
218
  Automatically protects sensitive data in traces and logs:
@@ -226,6 +258,7 @@ async function processUserWorkflow(userId: string) {
226
258
  const result = await generateText({
227
259
  model: openai('gpt-4'),
228
260
  messages: [{ role: 'user', content: 'Hello' }],
261
+ experimental_telemetry: { isEnabled: true },
229
262
  });
230
263
 
231
264
  emitEvent('workflow.completed', { userId, result: result.text });
@@ -380,6 +413,7 @@ Check out the [examples](./examples/) directory for complete working examples:
380
413
  - For ESM, use loader + `Brizz.initialize()`
381
414
  - For CommonJS, use preload (with optional `Brizz.initialize()`)
382
415
  - Check that `BRIZZ_API_KEY` is set
416
+ - For Vercel AI SDK: Add `experimental_telemetry: { isEnabled: true }` to function calls
383
417
 
384
418
  **CJS/ESM compatibility issues**
385
419
 
package/dist/index.cjs CHANGED
@@ -1469,7 +1469,7 @@ var HANDLED_SPAN_NAMES = {
1469
1469
  "ai.streamText": "ai.streamText",
1470
1470
  "ai.toolCall": (span) => {
1471
1471
  const toolName = span.attributes["ai.toolCall.name"];
1472
- return `${toolName}.tool`;
1472
+ return `${String(toolName ?? "unknown")}.tool`;
1473
1473
  }
1474
1474
  };
1475
1475
  var AI_RESPONSE_TEXT = "ai.response.text";
@@ -1479,10 +1479,11 @@ var AI_USAGE_COMPLETION_TOKENS = "ai.usage.completionTokens";
1479
1479
  var AI_MODEL_PROVIDER = "ai.model.provider";
1480
1480
  var transformAiSdkSpanName = (span) => {
1481
1481
  if (span.name in HANDLED_SPAN_NAMES) {
1482
- if (typeof HANDLED_SPAN_NAMES[span.name] === "function") {
1483
- span.name = HANDLED_SPAN_NAMES[span.name](span);
1484
- } else {
1485
- span.name = HANDLED_SPAN_NAMES[span.name];
1482
+ const handler = HANDLED_SPAN_NAMES[span.name];
1483
+ if (typeof handler === "function") {
1484
+ span.name = handler(span);
1485
+ } else if (handler) {
1486
+ span.name = handler;
1486
1487
  }
1487
1488
  }
1488
1489
  };
@@ -1497,26 +1498,30 @@ var transformPromptMessages = (attributes) => {
1497
1498
  if (AI_PROMPT_MESSAGES in attributes) {
1498
1499
  try {
1499
1500
  const messages = JSON.parse(attributes[AI_PROMPT_MESSAGES]);
1500
- messages.forEach((msg, index) => {
1501
- logger.debug("Transforming prompt message", { msg, type: typeof msg.content });
1502
- if (typeof msg.content === "string") {
1503
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = msg.content;
1501
+ for (const [index, msg] of messages.entries()) {
1502
+ const message = msg;
1503
+ logger.debug("Transforming prompt message", { msg: message, type: typeof message.content });
1504
+ if (typeof message.content === "string") {
1505
+ attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = message.content;
1504
1506
  } else {
1505
- if (Array.isArray(msg.content) && msg.content.length > 0) {
1506
- const lastContent = msg.content[msg.content.length - 1];
1507
- if (lastContent.text) {
1507
+ if (Array.isArray(message.content) && message.content.length > 0) {
1508
+ const lastContent = message.content.at(-1);
1509
+ if (lastContent?.text) {
1508
1510
  attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = lastContent.text;
1509
1511
  }
1510
1512
  } else {
1511
1513
  attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = JSON.stringify(
1512
- msg.content
1514
+ message.content
1513
1515
  );
1514
1516
  }
1515
1517
  }
1516
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.role`] = msg.role;
1517
- });
1518
+ attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.role`] = message.role;
1519
+ }
1518
1520
  delete attributes[AI_PROMPT_MESSAGES];
1519
- } catch {
1521
+ } catch (error) {
1522
+ logger.debug("Skipping prompt messages transformation because of JSON parsing error", {
1523
+ e: error
1524
+ });
1520
1525
  }
1521
1526
  }
1522
1527
  };
@@ -1542,11 +1547,7 @@ var calculateTotalTokens = (attributes) => {
1542
1547
  var transformVendor = (attributes) => {
1543
1548
  if (AI_MODEL_PROVIDER in attributes) {
1544
1549
  const vendor = attributes[AI_MODEL_PROVIDER];
1545
- if (vendor && vendor.startsWith("openai")) {
1546
- attributes[import_ai_semantic_conventions.SpanAttributes.LLM_SYSTEM] = "OpenAI";
1547
- } else {
1548
- attributes[import_ai_semantic_conventions.SpanAttributes.LLM_SYSTEM] = vendor;
1549
- }
1550
+ attributes[import_ai_semantic_conventions.SpanAttributes.LLM_SYSTEM] = vendor && vendor.startsWith("openai") ? "OpenAI" : vendor;
1550
1551
  delete attributes[AI_MODEL_PROVIDER];
1551
1552
  }
1552
1553
  };
@@ -1562,11 +1563,20 @@ var shouldHandleSpan = (span) => {
1562
1563
  return span.name in HANDLED_SPAN_NAMES;
1563
1564
  };
1564
1565
  var transformAiSdkSpan = (span) => {
1565
- logger.debug("Transforming AI SDK span", { spanName: span.name });
1566
1566
  if (!shouldHandleSpan(span)) {
1567
1567
  logger.debug("Skipping span transformation", { spanName: span.name });
1568
1568
  return;
1569
1569
  }
1570
+ for (const key in span.attributes) {
1571
+ if (Number.isNaN(span.attributes[key])) {
1572
+ span.attributes[key] = 0;
1573
+ }
1574
+ }
1575
+ logger.debug("Transforming AI SDK span", {
1576
+ spanName: span.name,
1577
+ spanContext: span.spanContext(),
1578
+ attributes: span.attributes
1579
+ });
1570
1580
  transformAiSdkSpanName(span);
1571
1581
  transformAiSdkAttributes(span.attributes);
1572
1582
  };