@breadcrumb-sdk/core 0.0.3 → 0.0.5

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
@@ -1,6 +1,6 @@
1
1
  # @breadcrumb-sdk/core
2
2
 
3
- Trace your AI agents and pipelines with Breadcrumb.
3
+ Trace your AI agents and pipelines with Breadcrumb. **[Documentation](https://breadcrumb.sh/docs)**
4
4
 
5
5
  ## Install
6
6
 
@@ -16,6 +16,7 @@ import { init } from "@breadcrumb-sdk/core";
16
16
  const bc = init({
17
17
  apiKey: "bc_...",
18
18
  baseUrl: "https://your-breadcrumb-instance.com",
19
+ environment: "production",
19
20
  });
20
21
 
21
22
  const answer = await bc.trace("answer-question", async (root) => {
@@ -54,6 +55,7 @@ Call once at startup. Returns a `bc` instance you use to create traces and spans
54
55
  const bc = init({
55
56
  apiKey: string,
56
57
  baseUrl: string,
58
+ environment?: string, // e.g. "production", "staging", "development"
57
59
  batching?: false | {
58
60
  flushInterval?: number, // ms between sends (default: 5000)
59
61
  maxBatchSize?: number, // spans per send (default: 100)
@@ -61,6 +63,8 @@ const bc = init({
61
63
  })
62
64
  ```
63
65
 
66
+ Set `environment` once at init time to attach it to every root trace created by this SDK instance. This powers environment filtering in the Breadcrumb UI.
67
+
64
68
  Set `batching: false` to send each span as it finishes. The default batches them. Either way, everything is flushed before the process exits.
65
69
 
66
70
  ---
@@ -123,7 +127,7 @@ span.set({
123
127
  output_cost_usd: 0.00087,
124
128
  metadata: {
125
129
  score: 0.95,
126
- environment: "production",
130
+ region: "eu-central-1",
127
131
  },
128
132
  });
129
133
  ```
package/dist/index.cjs CHANGED
@@ -289,9 +289,10 @@ function passthroughMetadata(span, existing) {
289
289
  };
290
290
  }
291
291
  var BreadcrumbSpanExporter = class {
292
- constructor(apiKey, baseUrl) {
292
+ constructor(apiKey, baseUrl, environment) {
293
293
  this.apiKey = apiKey;
294
294
  this.baseUrl = baseUrl;
295
+ this.environment = environment;
295
296
  }
296
297
  export(spans, resultCallback) {
297
298
  this._export(spans).then(() => resultCallback({ code: __opentelemetry_core.ExportResultCode.SUCCESS }), () => resultCallback({ code: __opentelemetry_core.ExportResultCode.SUCCESS }));
@@ -339,7 +340,8 @@ var BreadcrumbSpanExporter = class {
339
340
  start_time: hrTimeToISO(span.startTime),
340
341
  end_time: hrTimeToISO(span.endTime),
341
342
  status: spanStatus(span),
342
- status_message: span.status.message || void 0
343
+ status_message: span.status.message || void 0,
344
+ environment: this.environment
343
345
  });
344
346
  }
345
347
  async _post(path, body) {
@@ -365,7 +367,7 @@ var BreadcrumbSpanExporter = class {
365
367
  //#endregion
366
368
  //#region src/index.ts
367
369
  function init(options) {
368
- const exporter = new BreadcrumbSpanExporter(options.apiKey, options.baseUrl);
370
+ const exporter = new BreadcrumbSpanExporter(options.apiKey, options.baseUrl, options.environment);
369
371
  const batchOpts = typeof options.batching === "object" ? options.batching : void 0;
370
372
  const processor = options.batching === false ? new __opentelemetry_sdk_trace_base.SimpleSpanProcessor(exporter) : new __opentelemetry_sdk_trace_base.BatchSpanProcessor(exporter, {
371
373
  scheduledDelayMillis: batchOpts?.flushInterval ?? 5e3,
package/dist/index.d.cts CHANGED
@@ -44,6 +44,7 @@ interface Breadcrumb {
44
44
  interface InitOptions {
45
45
  apiKey: string;
46
46
  baseUrl: string;
47
+ environment?: string;
47
48
  batching?: false | {
48
49
  flushInterval?: number;
49
50
  maxBatchSize?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/index.ts"],"sourcesContent":null,"mappings":";;;;;UAIiB,OAAA;EAAA,IAAA,EAAA,QAAO,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;EAKP,OAAA,EAAA,MAAQ;;AAON,UAPF,QAAA,CAOE;EAAO;;;AAYP;AAGnB;AAIA;EAIiB,KAAA,CAAA,EAAA,MAAU,GAvBR,OAuBQ,EAAA,GAvBI,MAuBJ,CAAA,MAAA,EAAA,OAAA,CAAA;EAAA;;;;EACmC,MAAc,CAAA,EAAA,MAAA,GAnBxD,MAmBwD,CAAA,MAAA,EAAA,OAAA,CAAA;EAAC,KAAT,CAAA,EAAA,MAAA;EAAO,QAG5D,CAAA,EAAA,MAAA;EAAc,YAAa,CAAA,EAAA,MAAA;EAAC,aAAT,CAAA,EAAA,MAAA;EAAO,cAC3B,CAAA,EAAA,MAAA;EAAW,eACZ,CAAA,EAAA,MAAA;EAAC,QAAT,CAAA,EAjBQ,MAiBR,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA;AAAO;UAdK,cAAA;YACL;;ACfK,UDkBA,WAAA,CClBW;EAWZ,IAAA,CAAA,EAAI,KAAA,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;;AAAU,UDWb,UAAA,CCXa;EAAW,KAAG,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDYR,cCZQ,EAAA,GDYW,OCZX,CDYmB,CCZnB,CAAA,CAAA,EDYwB,OCZxB,CDYgC,CCZhC,CAAA;EAAU,IAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDevC,cCfuC,EAAA,GDepB,OCfoB,CDeZ,CCfY,CAAA,EAAA,OAAA,CAAA,EDgBxC,WChBwC,CAAA,EDiBjD,OCjBiD,CDiBzC,CCjByC,CAAA;;;;;UAXrC,WAAA;;;EDbA,QAAA,CAAA,EAAO,KAAA,GAAA;IAKP,aAAQ,CAAA,EAAA,MAAA;IAAA,YAAA,CAAA,EAAA,MAAA;EAAA,CAAA;;AAYL,iBCOJ,IAAA,CDPI,OAAA,ECOU,WDPV,CAAA,ECOwB,UDPxB"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/index.ts"],"sourcesContent":null,"mappings":";;;;;UAIiB,OAAA;EAAA,IAAA,EAAA,QAAO,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;EAKP,OAAA,EAAA,MAAQ;;AAON,UAPF,QAAA,CAOE;EAAO;;;AAYP;AAGnB;AAIA;EAIiB,KAAA,CAAA,EAAA,MAAU,GAvBR,OAuBQ,EAAA,GAvBI,MAuBJ,CAAA,MAAA,EAAA,OAAA,CAAA;EAAA;;;;EACmC,MAAc,CAAA,EAAA,MAAA,GAnBxD,MAmBwD,CAAA,MAAA,EAAA,OAAA,CAAA;EAAC,KAAT,CAAA,EAAA,MAAA;EAAO,QAG5D,CAAA,EAAA,MAAA;EAAc,YAAa,CAAA,EAAA,MAAA;EAAC,aAAT,CAAA,EAAA,MAAA;EAAO,cAC3B,CAAA,EAAA,MAAA;EAAW,eACZ,CAAA,EAAA,MAAA;EAAC,QAAT,CAAA,EAjBQ,MAiBR,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA;AAAO;UAdK,cAAA;YACL;;ACfK,UDkBA,WAAA,CClBW;EAYZ,IAAA,CAAA,EAAI,KAAA,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;;AAAU,UDUb,UAAA,CCVa;EAAW,KAAG,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDWR,cCXQ,EAAA,GDWW,OCXX,CDWmB,CCXnB,CAAA,CAAA,EDWwB,OCXxB,CDWgC,CCXhC,CAAA;EAAU,IAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDcvC,cCduC,EAAA,GDcpB,OCdoB,CDcZ,CCdY,CAAA,EAAA,OAAA,CAAA,EDexC,WCfwC,CAAA,EDgBjD,OChBiD,CDgBzC,CChByC,CAAA;;;;;UAZrC,WAAA;;;EDbA,WAAO,CAAA,EAAA,MAAA;EAKP,QAAA,CAAA,EAAQ,KAAA,GAAA;IAAA,aAAA,CAAA,EAAA,MAAA;IAON,YAAA,CAAA,EAAA,MAAA;EAAO,CAAA;;AAYb,iBCCG,IAAA,CDDH,OAAA,ECCiB,WDDjB,CAAA,ECC+B,UDD/B;;;AAAM"}
package/dist/index.d.ts CHANGED
@@ -44,6 +44,7 @@ interface Breadcrumb {
44
44
  interface InitOptions {
45
45
  apiKey: string;
46
46
  baseUrl: string;
47
+ environment?: string;
47
48
  batching?: false | {
48
49
  flushInterval?: number;
49
50
  maxBatchSize?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/index.ts"],"sourcesContent":null,"mappings":";;;;;UAIiB,OAAA;EAAA,IAAA,EAAA,QAAO,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;EAKP,OAAA,EAAA,MAAQ;;AAON,UAPF,QAAA,CAOE;EAAO;;;AAYP;AAGnB;AAIA;EAIiB,KAAA,CAAA,EAAA,MAAU,GAvBR,OAuBQ,EAAA,GAvBI,MAuBJ,CAAA,MAAA,EAAA,OAAA,CAAA;EAAA;;;;EACmC,MAAc,CAAA,EAAA,MAAA,GAnBxD,MAmBwD,CAAA,MAAA,EAAA,OAAA,CAAA;EAAC,KAAT,CAAA,EAAA,MAAA;EAAO,QAG5D,CAAA,EAAA,MAAA;EAAc,YAAa,CAAA,EAAA,MAAA;EAAC,aAAT,CAAA,EAAA,MAAA;EAAO,cAC3B,CAAA,EAAA,MAAA;EAAW,eACZ,CAAA,EAAA,MAAA;EAAC,QAAT,CAAA,EAjBQ,MAiBR,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA;AAAO;UAdK,cAAA;YACL;;ACfK,UDkBA,WAAA,CClBW;EAWZ,IAAA,CAAA,EAAI,KAAA,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;;AAAU,UDWb,UAAA,CCXa;EAAW,KAAG,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDYR,cCZQ,EAAA,GDYW,OCZX,CDYmB,CCZnB,CAAA,CAAA,EDYwB,OCZxB,CDYgC,CCZhC,CAAA;EAAU,IAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDevC,cCfuC,EAAA,GDepB,OCfoB,CDeZ,CCfY,CAAA,EAAA,OAAA,CAAA,EDgBxC,WChBwC,CAAA,EDiBjD,OCjBiD,CDiBzC,CCjByC,CAAA;;;;;UAXrC,WAAA;;;EDbA,QAAA,CAAA,EAAO,KAAA,GAAA;IAKP,aAAQ,CAAA,EAAA,MAAA;IAAA,YAAA,CAAA,EAAA,MAAA;EAAA,CAAA;;AAYL,iBCOJ,IAAA,CDPI,OAAA,ECOU,WDPV,CAAA,ECOwB,UDPxB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/index.ts"],"sourcesContent":null,"mappings":";;;;;UAIiB,OAAA;EAAA,IAAA,EAAA,QAAO,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;EAKP,OAAA,EAAA,MAAQ;;AAON,UAPF,QAAA,CAOE;EAAO;;;AAYP;AAGnB;AAIA;EAIiB,KAAA,CAAA,EAAA,MAAU,GAvBR,OAuBQ,EAAA,GAvBI,MAuBJ,CAAA,MAAA,EAAA,OAAA,CAAA;EAAA;;;;EACmC,MAAc,CAAA,EAAA,MAAA,GAnBxD,MAmBwD,CAAA,MAAA,EAAA,OAAA,CAAA;EAAC,KAAT,CAAA,EAAA,MAAA;EAAO,QAG5D,CAAA,EAAA,MAAA;EAAc,YAAa,CAAA,EAAA,MAAA;EAAC,aAAT,CAAA,EAAA,MAAA;EAAO,cAC3B,CAAA,EAAA,MAAA;EAAW,eACZ,CAAA,EAAA,MAAA;EAAC,QAAT,CAAA,EAjBQ,MAiBR,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA;AAAO;UAdK,cAAA;YACL;;ACfK,UDkBA,WAAA,CClBW;EAYZ,IAAA,CAAA,EAAI,KAAA,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA;;AAAU,UDUb,UAAA,CCVa;EAAW,KAAG,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDWR,cCXQ,EAAA,GDWW,OCXX,CDWmB,CCXnB,CAAA,CAAA,EDWwB,OCXxB,CDWgC,CCXhC,CAAA;EAAU,IAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EAAA,CAAA,IAAA,EDcvC,cCduC,EAAA,GDcpB,OCdoB,CDcZ,CCdY,CAAA,EAAA,OAAA,CAAA,EDexC,WCfwC,CAAA,EDgBjD,OChBiD,CDgBzC,CChByC,CAAA;;;;;UAZrC,WAAA;;;EDbA,WAAO,CAAA,EAAA,MAAA;EAKP,QAAA,CAAA,EAAQ,KAAA,GAAA;IAAA,aAAA,CAAA,EAAA,MAAA;IAON,YAAA,CAAA,EAAA,MAAA;EAAO,CAAA;;AAYb,iBCCG,IAAA,CDDH,OAAA,ECCiB,WDDjB,CAAA,ECC+B,UDD/B;;;AAAM"}
package/dist/index.js CHANGED
@@ -265,9 +265,10 @@ function passthroughMetadata(span, existing) {
265
265
  };
266
266
  }
267
267
  var BreadcrumbSpanExporter = class {
268
- constructor(apiKey, baseUrl) {
268
+ constructor(apiKey, baseUrl, environment) {
269
269
  this.apiKey = apiKey;
270
270
  this.baseUrl = baseUrl;
271
+ this.environment = environment;
271
272
  }
272
273
  export(spans, resultCallback) {
273
274
  this._export(spans).then(() => resultCallback({ code: ExportResultCode.SUCCESS }), () => resultCallback({ code: ExportResultCode.SUCCESS }));
@@ -315,7 +316,8 @@ var BreadcrumbSpanExporter = class {
315
316
  start_time: hrTimeToISO(span.startTime),
316
317
  end_time: hrTimeToISO(span.endTime),
317
318
  status: spanStatus(span),
318
- status_message: span.status.message || void 0
319
+ status_message: span.status.message || void 0,
320
+ environment: this.environment
319
321
  });
320
322
  }
321
323
  async _post(path, body) {
@@ -341,7 +343,7 @@ var BreadcrumbSpanExporter = class {
341
343
  //#endregion
342
344
  //#region src/index.ts
343
345
  function init(options) {
344
- const exporter = new BreadcrumbSpanExporter(options.apiKey, options.baseUrl);
346
+ const exporter = new BreadcrumbSpanExporter(options.apiKey, options.baseUrl, options.environment);
345
347
  const batchOpts = typeof options.batching === "object" ? options.batching : void 0;
346
348
  const processor = options.batching === false ? new SimpleSpanProcessor(exporter) : new BatchSpanProcessor(exporter, {
347
349
  scheduledDelayMillis: batchOpts?.flushInterval ?? 5e3,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["s: string","attrs: Attributes","spanName: string","raw: string","span: ReadableSpan","result: Partial<MappedSpanData>","messages: { role: string; content: unknown }[]","tc: Record<string, unknown>","metadata: Record<string, string>","span: ReadableSpan","result: Partial<MappedSpanData>","metadata: Record<string, string>","hrTime: [number, number]","span: ReadableSpan","existing: Record<string, string> | undefined","extra: Record<string, string>","apiKey: string","baseUrl: string","spans: ReadableSpan[]","resultCallback: (result: ExportResult) => void","sends: Promise<void>[]","path: string","body: unknown","options: InitOptions","otelSpan: OtelSpan","activeCtx: typeof ROOT_CONTEXT","fn: (span: BreadcrumbSpan) => Promise<T>","bcSpan: BreadcrumbSpan","name: string","options?: SpanOptions","options"],"sources":["../src/mappers/utils.ts","../src/mappers/ai-sdk.ts","../src/mappers/breadcrumb.ts","../src/exporter.ts","../src/index.ts"],"sourcesContent":["import type { Attributes } from \"@opentelemetry/api\";\n\nexport function tryJson(s: string): unknown {\n try {\n return JSON.parse(s);\n } catch {\n return undefined;\n }\n}\n\nexport function strAttr(attrs: Attributes, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const v = attrs[key];\n if (typeof v === \"string\" && v !== \"\") return v;\n }\n return undefined;\n}\n\nexport function intAttr(attrs: Attributes, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const v = attrs[key];\n if (typeof v === \"number\") return Math.round(v);\n }\n return undefined;\n}\n\nexport function floatAttr(attrs: Attributes, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const v = attrs[key];\n if (typeof v === \"number\") return v;\n }\n return undefined;\n}\n","import type { ReadableSpan } from \"@opentelemetry/sdk-trace-base\";\nimport type { MappedSpanData, SpanType } from \"./types.js\";\nimport { tryJson, strAttr, intAttr, floatAttr } from \"./utils.js\";\n\nconst LLM_SPAN_NAMES = new Set([\n \"ai.generateText\",\n \"ai.generateText.doGenerate\",\n \"ai.streamText\",\n \"ai.streamText.doStream\",\n \"ai.generateObject\",\n \"ai.generateObject.doGenerate\",\n \"ai.generateObject.doStream\",\n]);\n\nconst TOOL_SPAN_NAMES = new Set([\n \"ai.toolCall\",\n \"ai.toolExecution\",\n \"ai.executeToolCall\",\n]);\n\n// Attributes extracted into first-class fields — excluded from metadata pass-through\nconst HANDLED = new Set([\n \"resource.name\",\n \"ai.prompt\",\n \"ai.prompt.messages\",\n \"ai.response.text\",\n \"ai.response.toolCalls\",\n \"ai.toolCall.name\",\n \"ai.toolCall.args\",\n \"ai.toolCall.result\",\n \"ai.model.id\",\n \"ai.model.provider\",\n \"ai.response.model\",\n \"gen_ai.request.model\",\n \"gen_ai.system\",\n \"ai.usage.inputTokens\",\n \"ai.usage.promptTokens\",\n \"ai.usage.outputTokens\",\n \"ai.usage.completionTokens\",\n \"gen_ai.usage.input_tokens\",\n \"gen_ai.usage.output_tokens\",\n \"ai.response.providerMetadata\",\n \"ai.response.finishReason\",\n // Metadata with prefix stripped — handled in the metadata loop below\n // (ai.telemetry.metadata.*)\n]);\n\n// Attributes to drop entirely (not extracted, not in metadata)\nconst DROP = new Set([\n \"operation.name\",\n \"ai.operationId\",\n \"ai.telemetry.functionId\",\n \"gen_ai.response.finish_reasons\",\n \"gen_ai.response.id\",\n \"gen_ai.response.model\",\n \"ai.response.id\",\n \"ai.response.timestamp\",\n \"ai.prompt.tools\",\n \"ai.prompt.toolChoice\",\n \"ai.toolCall.id\",\n]);\n\nfunction inferType(spanName: string): SpanType {\n if (LLM_SPAN_NAMES.has(spanName)) return \"llm\";\n if (TOOL_SPAN_NAMES.has(spanName)) return \"tool\";\n return \"custom\";\n}\n\nfunction extractCost(\n raw: string,\n): { input_cost_usd?: number; output_cost_usd?: number } {\n try {\n const parsed = tryJson(raw) as Record<string, unknown> | null;\n if (!parsed || typeof parsed !== \"object\") return {};\n for (const providerData of Object.values(parsed)) {\n const usage = (providerData as Record<string, unknown>)?.usage as\n | Record<string, unknown>\n | undefined;\n if (!usage) continue;\n const totalCost = usage[\"cost\"];\n if (typeof totalCost !== \"number\") continue;\n const prompt = typeof usage[\"promptTokens\"] === \"number\" ? usage[\"promptTokens\"] : 0;\n const completion =\n typeof usage[\"completionTokens\"] === \"number\" ? usage[\"completionTokens\"] : 0;\n const total = prompt + completion;\n if (total > 0) {\n return {\n input_cost_usd: totalCost * (prompt / total),\n output_cost_usd: totalCost * (completion / total),\n };\n }\n return { input_cost_usd: totalCost };\n }\n } catch {\n // ignore\n }\n return {};\n}\n\nexport function mapAiSdk(span: ReadableSpan): Partial<MappedSpanData> {\n const attrs = span.attributes;\n const result: Partial<MappedSpanData> = {};\n\n // ── Name ─────────────────────────────────────────────────────────────────\n const toolCallName = strAttr(attrs, \"ai.toolCall.name\");\n const resourceName = strAttr(attrs, \"resource.name\");\n if (toolCallName) result.name = toolCallName;\n else if (resourceName) result.name = resourceName;\n\n // ── Type ─────────────────────────────────────────────────────────────────\n result.type = inferType(span.name);\n\n // ── Input ─────────────────────────────────────────────────────────────────\n const toolArgs = attrs[\"ai.toolCall.args\"];\n const aiMessages = attrs[\"ai.prompt.messages\"];\n const aiPrompt = attrs[\"ai.prompt\"];\n\n if (typeof toolArgs === \"string\") {\n result.input = tryJson(toolArgs) ?? toolArgs;\n } else if (typeof aiMessages === \"string\") {\n result.input = tryJson(aiMessages) ?? aiMessages;\n } else if (typeof aiPrompt === \"string\") {\n const parsed = tryJson(aiPrompt) as Record<string, unknown> | null;\n if (parsed && typeof parsed === \"object\") {\n const messages: { role: string; content: unknown }[] = [];\n if (parsed[\"system\"]) messages.push({ role: \"system\", content: parsed[\"system\"] });\n if (Array.isArray(parsed[\"messages\"])) {\n messages.push(...(parsed[\"messages\"] as { role: string; content: unknown }[]));\n } else if (parsed[\"prompt\"] !== undefined) {\n messages.push({ role: \"user\", content: parsed[\"prompt\"] });\n }\n result.input = messages.length > 0 ? messages : parsed;\n } else {\n result.input = aiPrompt;\n }\n }\n\n // ── Output ────────────────────────────────────────────────────────────────\n const toolResult = attrs[\"ai.toolCall.result\"];\n const aiText = attrs[\"ai.response.text\"];\n const aiToolCalls = attrs[\"ai.response.toolCalls\"];\n\n if (typeof toolResult === \"string\") {\n result.output = tryJson(toolResult) ?? toolResult;\n } else if (typeof aiText === \"string\") {\n result.output = aiText;\n } else if (typeof aiToolCalls === \"string\") {\n const parsed = tryJson(aiToolCalls);\n if (Array.isArray(parsed)) {\n result.output = parsed.map((tc: Record<string, unknown>) => ({\n ...tc,\n input:\n typeof tc[\"input\"] === \"string\"\n ? (tryJson(tc[\"input\"]) ?? tc[\"input\"])\n : tc[\"input\"],\n }));\n } else {\n result.output = parsed ?? aiToolCalls;\n }\n }\n\n // ── Model / provider ──────────────────────────────────────────────────────\n const model = strAttr(attrs, \"ai.model.id\", \"ai.response.model\", \"gen_ai.request.model\");\n if (model) result.model = model;\n\n const provider = strAttr(attrs, \"ai.model.provider\", \"gen_ai.system\");\n if (provider) result.provider = provider;\n\n // ── Tokens ────────────────────────────────────────────────────────────────\n const input_tokens = intAttr(\n attrs,\n \"ai.usage.inputTokens\",\n \"ai.usage.promptTokens\",\n \"gen_ai.usage.input_tokens\",\n );\n if (input_tokens != null) result.input_tokens = input_tokens;\n\n const output_tokens = intAttr(\n attrs,\n \"ai.usage.outputTokens\",\n \"ai.usage.completionTokens\",\n \"gen_ai.usage.output_tokens\",\n );\n if (output_tokens != null) result.output_tokens = output_tokens;\n\n // ── Cost ──────────────────────────────────────────────────────────────────\n const providerMeta = attrs[\"ai.response.providerMetadata\"];\n if (typeof providerMeta === \"string\") {\n const cost = extractCost(providerMeta);\n if (cost.input_cost_usd != null) result.input_cost_usd = cost.input_cost_usd;\n if (cost.output_cost_usd != null) result.output_cost_usd = cost.output_cost_usd;\n }\n\n // ── Cost from explicit breadcrumb attrs (none here — handled by mapBreadcrumb) ─\n\n // ── Metadata pass-through ─────────────────────────────────────────────────\n // Collect unrecognised ai.* / gen_ai.* attrs as metadata.\n const metadata: Record<string, string> = {};\n\n // ai.response.finishReason is in HANDLED (excluded from pass-through) but\n // still needs to appear in metadata under a clean key.\n const finishReason = attrs[\"ai.response.finishReason\"];\n if (typeof finishReason === \"string\" && finishReason !== \"\") {\n metadata[\"finish_reason\"] = finishReason;\n }\n\n for (const [k, v] of Object.entries(attrs)) {\n if (v == null) continue;\n if (HANDLED.has(k) || DROP.has(k)) continue;\n if (k.startsWith(\"ai.settings.\") || k.startsWith(\"ai.request.headers.\")) continue;\n\n if (k.startsWith(\"ai.telemetry.metadata.\")) {\n metadata[k.slice(\"ai.telemetry.metadata.\".length)] = String(v);\n continue;\n }\n // Only pass through ai.* and gen_ai.* here; other namespaces are handled\n // by the exporter's own pass-through for truly unknown attributes.\n if (k.startsWith(\"ai.\") || k.startsWith(\"gen_ai.\")) {\n metadata[k] = String(v);\n }\n }\n\n if (Object.keys(metadata).length > 0) result.metadata = metadata;\n\n return result;\n}\n","import type { ReadableSpan } from \"@opentelemetry/sdk-trace-base\";\nimport type { MappedSpanData, SpanType } from \"./types.js\";\nimport { tryJson, strAttr, intAttr, floatAttr } from \"./utils.js\";\n\nconst VALID_TYPES = new Set<string>([\"llm\", \"tool\", \"retrieval\", \"step\", \"custom\"]);\n\nexport function mapBreadcrumb(span: ReadableSpan): Partial<MappedSpanData> {\n const attrs = span.attributes;\n const result: Partial<MappedSpanData> = {};\n\n // ── Type override ─────────────────────────────────────────────────────────\n const explicitType = attrs[\"breadcrumb.span.type\"];\n if (typeof explicitType === \"string\" && VALID_TYPES.has(explicitType)) {\n result.type = explicitType as SpanType;\n }\n\n // ── Input ─────────────────────────────────────────────────────────────────\n const rawInput = attrs[\"breadcrumb.input\"];\n if (rawInput != null) {\n result.input =\n typeof rawInput === \"string\" ? (tryJson(rawInput) ?? rawInput) : rawInput;\n }\n\n // ── Output ────────────────────────────────────────────────────────────────\n const rawOutput = attrs[\"breadcrumb.output\"];\n if (rawOutput != null) {\n result.output =\n typeof rawOutput === \"string\" ? (tryJson(rawOutput) ?? rawOutput) : rawOutput;\n }\n\n // ── Model / provider ──────────────────────────────────────────────────────\n const model = strAttr(attrs, \"breadcrumb.model\");\n if (model) result.model = model;\n\n const provider = strAttr(attrs, \"breadcrumb.provider\");\n if (provider) result.provider = provider;\n\n // ── Tokens ────────────────────────────────────────────────────────────────\n const input_tokens = intAttr(attrs, \"breadcrumb.input_tokens\");\n if (input_tokens != null) result.input_tokens = input_tokens;\n\n const output_tokens = intAttr(attrs, \"breadcrumb.output_tokens\");\n if (output_tokens != null) result.output_tokens = output_tokens;\n\n // ── Cost ──────────────────────────────────────────────────────────────────\n const input_cost_usd = floatAttr(attrs, \"breadcrumb.input_cost_usd\");\n if (input_cost_usd != null) result.input_cost_usd = input_cost_usd;\n\n const output_cost_usd = floatAttr(attrs, \"breadcrumb.output_cost_usd\");\n if (output_cost_usd != null) result.output_cost_usd = output_cost_usd;\n\n // ── Metadata ──────────────────────────────────────────────────────────────\n const metadata: Record<string, string> = {};\n for (const [k, v] of Object.entries(attrs)) {\n if (v == null) continue;\n if (k.startsWith(\"breadcrumb.meta.\")) {\n metadata[k.slice(\"breadcrumb.meta.\".length)] = String(v);\n }\n }\n if (Object.keys(metadata).length > 0) result.metadata = metadata;\n\n return result;\n}\n","import type { ExportResult } from \"@opentelemetry/core\";\nimport { ExportResultCode } from \"@opentelemetry/core\";\nimport type { SpanExporter, ReadableSpan } from \"@opentelemetry/sdk-trace-base\";\nimport { SpanStatusCode } from \"@opentelemetry/api\";\nimport { mapAiSdk } from \"./mappers/ai-sdk.js\";\nimport { mapBreadcrumb } from \"./mappers/breadcrumb.js\";\nimport type { MappedSpanData } from \"./mappers/types.js\";\n\n// Attribute namespaces fully handled by mappers — excluded from the generic\n// pass-through that collects remaining unknown attrs into metadata.\nconst MAPPER_NAMESPACES = [\"ai.\", \"gen_ai.\", \"breadcrumb.\", \"resource.name\"];\n\n\n// Non-namespaced keys that should be dropped entirely (not in metadata).\n// These come from AI SDK / OTel conventions and are not user-meaningful.\nconst GLOBAL_DROP = new Set([\"operation.name\"]);\n\nfunction hrTimeToISO(hrTime: [number, number]): string {\n return new Date(hrTime[0] * 1000 + hrTime[1] / 1_000_000).toISOString();\n}\n\nfunction spanStatus(span: ReadableSpan): \"ok\" | \"error\" {\n return span.status.code === SpanStatusCode.ERROR ? \"error\" : \"ok\";\n}\n\nfunction mergeMappers(span: ReadableSpan): MappedSpanData {\n const aiSdk = mapAiSdk(span);\n const bc = mapBreadcrumb(span);\n\n // breadcrumb (user-set) wins for all scalar fields; metadata is merged with\n // breadcrumb keys overriding matching AI SDK keys.\n return {\n ...aiSdk,\n ...bc,\n metadata:\n aiSdk.metadata || bc.metadata\n ? { ...aiSdk.metadata, ...bc.metadata }\n : undefined,\n };\n}\n\n// Collect attributes not handled by any mapper (unknown namespaces like\n// \"custom.key\", bare keys like \"score\") into metadata as strings.\nfunction passthroughMetadata(\n span: ReadableSpan,\n existing: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const extra: Record<string, string> = {};\n for (const [k, v] of Object.entries(span.attributes)) {\n if (v == null) continue;\n const handled = MAPPER_NAMESPACES.some((ns) =>\n k === ns || k.startsWith(ns),\n );\n if (handled || GLOBAL_DROP.has(k)) continue;\n extra[k] = String(v);\n }\n if (Object.keys(extra).length === 0) return existing || undefined;\n return { ...extra, ...existing }; // existing (breadcrumb) still wins\n}\n\nexport class BreadcrumbSpanExporter implements SpanExporter {\n constructor(\n private readonly apiKey: string,\n private readonly baseUrl: string,\n ) {}\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n this._export(spans).then(\n () => resultCallback({ code: ExportResultCode.SUCCESS }),\n () => resultCallback({ code: ExportResultCode.SUCCESS }), // fail silently\n );\n }\n\n private async _export(spans: ReadableSpan[]): Promise<void> {\n try {\n const roots = spans.filter((s) => !s.parentSpanId);\n const spanPayloads = spans.map((s) => this._mapSpan(s));\n\n const sends: Promise<void>[] = roots.map((s) => this._sendTrace(s));\n if (spanPayloads.length > 0) {\n sends.push(this._post(\"/v1/spans\", spanPayloads));\n }\n\n await Promise.all(sends);\n } catch {\n // Fail silently\n }\n }\n\n private _mapSpan(span: ReadableSpan) {\n const ctx = span.spanContext();\n const mapped = mergeMappers(span);\n const metadata = passthroughMetadata(span, mapped.metadata);\n\n return {\n id: ctx.spanId,\n trace_id: ctx.traceId,\n parent_span_id: span.parentSpanId || undefined,\n name: mapped.name ?? span.name,\n type: mapped.type ?? \"custom\",\n start_time: hrTimeToISO(span.startTime),\n end_time: hrTimeToISO(span.endTime),\n status: spanStatus(span),\n status_message: span.status.message || undefined,\n input: mapped.input !== undefined ? mapped.input : undefined,\n output: mapped.output !== undefined ? mapped.output : undefined,\n provider: mapped.provider,\n model: mapped.model,\n input_tokens: mapped.input_tokens,\n output_tokens: mapped.output_tokens,\n input_cost_usd: mapped.input_cost_usd,\n output_cost_usd: mapped.output_cost_usd,\n metadata: metadata && Object.keys(metadata).length > 0 ? metadata : undefined,\n };\n }\n\n private async _sendTrace(span: ReadableSpan): Promise<void> {\n const ctx = span.spanContext();\n const mapped = mergeMappers(span);\n await this._post(\"/v1/traces\", {\n id: ctx.traceId,\n name: mapped.name ?? span.name,\n start_time: hrTimeToISO(span.startTime),\n end_time: hrTimeToISO(span.endTime),\n status: spanStatus(span),\n status_message: span.status.message || undefined,\n });\n }\n\n private async _post(path: string, body: unknown): Promise<void> {\n try {\n await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n } catch {\n // Fail silently — backend unreachable\n }\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve();\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve();\n }\n}\n","import {\n context,\n trace,\n ROOT_CONTEXT,\n SpanStatusCode,\n type Span as OtelSpan,\n} from \"@opentelemetry/api\";\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\";\nimport {\n SimpleSpanProcessor,\n BatchSpanProcessor,\n} from \"@opentelemetry/sdk-trace-base\";\nimport { BreadcrumbSpanExporter } from \"./exporter.js\";\nimport type { Breadcrumb, BreadcrumbSpan, SpanOptions, SpanData, Message } from \"./types.js\";\n\nexport type { Breadcrumb, BreadcrumbSpan, SpanOptions, SpanData, Message };\n\nexport interface InitOptions {\n apiKey: string;\n baseUrl: string;\n batching?:\n | false\n | {\n flushInterval?: number;\n maxBatchSize?: number;\n };\n}\n\nexport function init(options: InitOptions): Breadcrumb {\n const exporter = new BreadcrumbSpanExporter(options.apiKey, options.baseUrl);\n\n const batchOpts =\n typeof options.batching === \"object\" ? options.batching : undefined;\n\n const processor =\n options.batching === false\n ? new SimpleSpanProcessor(exporter)\n : new BatchSpanProcessor(exporter, {\n scheduledDelayMillis: batchOpts?.flushInterval ?? 5000,\n maxExportBatchSize: batchOpts?.maxBatchSize ?? 100,\n });\n\n const provider = new NodeTracerProvider({ spanProcessors: [processor] });\n provider.register();\n\n process.once(\"beforeExit\", async () => {\n await provider.shutdown().catch(() => {});\n });\n\n const tracer = provider.getTracer(\"@breadcrumb-sdk/core\");\n\n function runSpan<T>(\n otelSpan: OtelSpan,\n activeCtx: typeof ROOT_CONTEXT,\n fn: (span: BreadcrumbSpan) => Promise<T>,\n ): Promise<T> {\n const bcSpan: BreadcrumbSpan = {\n set(data) {\n const { metadata, ...semantic } = data;\n for (const [key, value] of Object.entries(semantic)) {\n if (value == null) continue;\n const attrKey = `breadcrumb.${key}`;\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n otelSpan.setAttribute(attrKey, value);\n } else {\n otelSpan.setAttribute(attrKey, JSON.stringify(value));\n }\n }\n if (metadata) {\n for (const [key, value] of Object.entries(metadata)) {\n if (value == null) continue;\n otelSpan.setAttribute(`breadcrumb.meta.${key}`, value);\n }\n }\n },\n };\n\n return context.with(trace.setSpan(activeCtx, otelSpan), async () => {\n try {\n const result = await fn(bcSpan);\n otelSpan.setStatus({ code: SpanStatusCode.OK });\n otelSpan.end();\n return result;\n } catch (err) {\n otelSpan.setStatus({\n code: SpanStatusCode.ERROR,\n message: err instanceof Error ? err.message : String(err),\n });\n otelSpan.end();\n throw err;\n }\n });\n }\n\n return {\n trace<T>(\n name: string,\n fn: (span: BreadcrumbSpan) => Promise<T>,\n ): Promise<T> {\n const otelSpan = tracer.startSpan(name, {}, ROOT_CONTEXT);\n return runSpan(otelSpan, ROOT_CONTEXT, fn);\n },\n\n span<T>(\n name: string,\n fn: (span: BreadcrumbSpan) => Promise<T>,\n options?: SpanOptions,\n ): Promise<T> {\n const activeCtx = context.active();\n const otelSpan = tracer.startSpan(name, {}, activeCtx);\n if (options?.type) {\n otelSpan.setAttribute(\"breadcrumb.span.type\", options.type);\n }\n return runSpan(otelSpan, activeCtx, fn);\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["s: string","attrs: Attributes","spanName: string","raw: string","span: ReadableSpan","result: Partial<MappedSpanData>","messages: { role: string; content: unknown }[]","tc: Record<string, unknown>","metadata: Record<string, string>","span: ReadableSpan","result: Partial<MappedSpanData>","metadata: Record<string, string>","hrTime: [number, number]","span: ReadableSpan","existing: Record<string, string> | undefined","extra: Record<string, string>","apiKey: string","baseUrl: string","environment?: string","spans: ReadableSpan[]","resultCallback: (result: ExportResult) => void","sends: Promise<void>[]","path: string","body: unknown","options: InitOptions","otelSpan: OtelSpan","activeCtx: typeof ROOT_CONTEXT","fn: (span: BreadcrumbSpan) => Promise<T>","bcSpan: BreadcrumbSpan","name: string","options?: SpanOptions","options"],"sources":["../src/mappers/utils.ts","../src/mappers/ai-sdk.ts","../src/mappers/breadcrumb.ts","../src/exporter.ts","../src/index.ts"],"sourcesContent":["import type { Attributes } from \"@opentelemetry/api\";\n\nexport function tryJson(s: string): unknown {\n try {\n return JSON.parse(s);\n } catch {\n return undefined;\n }\n}\n\nexport function strAttr(attrs: Attributes, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const v = attrs[key];\n if (typeof v === \"string\" && v !== \"\") return v;\n }\n return undefined;\n}\n\nexport function intAttr(attrs: Attributes, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const v = attrs[key];\n if (typeof v === \"number\") return Math.round(v);\n }\n return undefined;\n}\n\nexport function floatAttr(attrs: Attributes, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const v = attrs[key];\n if (typeof v === \"number\") return v;\n }\n return undefined;\n}\n","import type { ReadableSpan } from \"@opentelemetry/sdk-trace-base\";\nimport type { MappedSpanData, SpanType } from \"./types.js\";\nimport { tryJson, strAttr, intAttr, floatAttr } from \"./utils.js\";\n\nconst LLM_SPAN_NAMES = new Set([\n \"ai.generateText\",\n \"ai.generateText.doGenerate\",\n \"ai.streamText\",\n \"ai.streamText.doStream\",\n \"ai.generateObject\",\n \"ai.generateObject.doGenerate\",\n \"ai.generateObject.doStream\",\n]);\n\nconst TOOL_SPAN_NAMES = new Set([\n \"ai.toolCall\",\n \"ai.toolExecution\",\n \"ai.executeToolCall\",\n]);\n\n// Attributes extracted into first-class fields — excluded from metadata pass-through\nconst HANDLED = new Set([\n \"resource.name\",\n \"ai.prompt\",\n \"ai.prompt.messages\",\n \"ai.response.text\",\n \"ai.response.toolCalls\",\n \"ai.toolCall.name\",\n \"ai.toolCall.args\",\n \"ai.toolCall.result\",\n \"ai.model.id\",\n \"ai.model.provider\",\n \"ai.response.model\",\n \"gen_ai.request.model\",\n \"gen_ai.system\",\n \"ai.usage.inputTokens\",\n \"ai.usage.promptTokens\",\n \"ai.usage.outputTokens\",\n \"ai.usage.completionTokens\",\n \"gen_ai.usage.input_tokens\",\n \"gen_ai.usage.output_tokens\",\n \"ai.response.providerMetadata\",\n \"ai.response.finishReason\",\n // Metadata with prefix stripped — handled in the metadata loop below\n // (ai.telemetry.metadata.*)\n]);\n\n// Attributes to drop entirely (not extracted, not in metadata)\nconst DROP = new Set([\n \"operation.name\",\n \"ai.operationId\",\n \"ai.telemetry.functionId\",\n \"gen_ai.response.finish_reasons\",\n \"gen_ai.response.id\",\n \"gen_ai.response.model\",\n \"ai.response.id\",\n \"ai.response.timestamp\",\n \"ai.prompt.tools\",\n \"ai.prompt.toolChoice\",\n \"ai.toolCall.id\",\n]);\n\nfunction inferType(spanName: string): SpanType {\n if (LLM_SPAN_NAMES.has(spanName)) return \"llm\";\n if (TOOL_SPAN_NAMES.has(spanName)) return \"tool\";\n return \"custom\";\n}\n\nfunction extractCost(\n raw: string,\n): { input_cost_usd?: number; output_cost_usd?: number } {\n try {\n const parsed = tryJson(raw) as Record<string, unknown> | null;\n if (!parsed || typeof parsed !== \"object\") return {};\n for (const providerData of Object.values(parsed)) {\n const usage = (providerData as Record<string, unknown>)?.usage as\n | Record<string, unknown>\n | undefined;\n if (!usage) continue;\n const totalCost = usage[\"cost\"];\n if (typeof totalCost !== \"number\") continue;\n const prompt = typeof usage[\"promptTokens\"] === \"number\" ? usage[\"promptTokens\"] : 0;\n const completion =\n typeof usage[\"completionTokens\"] === \"number\" ? usage[\"completionTokens\"] : 0;\n const total = prompt + completion;\n if (total > 0) {\n return {\n input_cost_usd: totalCost * (prompt / total),\n output_cost_usd: totalCost * (completion / total),\n };\n }\n return { input_cost_usd: totalCost };\n }\n } catch {\n // ignore\n }\n return {};\n}\n\nexport function mapAiSdk(span: ReadableSpan): Partial<MappedSpanData> {\n const attrs = span.attributes;\n const result: Partial<MappedSpanData> = {};\n\n // ── Name ─────────────────────────────────────────────────────────────────\n const toolCallName = strAttr(attrs, \"ai.toolCall.name\");\n const resourceName = strAttr(attrs, \"resource.name\");\n if (toolCallName) result.name = toolCallName;\n else if (resourceName) result.name = resourceName;\n\n // ── Type ─────────────────────────────────────────────────────────────────\n result.type = inferType(span.name);\n\n // ── Input ─────────────────────────────────────────────────────────────────\n const toolArgs = attrs[\"ai.toolCall.args\"];\n const aiMessages = attrs[\"ai.prompt.messages\"];\n const aiPrompt = attrs[\"ai.prompt\"];\n\n if (typeof toolArgs === \"string\") {\n result.input = tryJson(toolArgs) ?? toolArgs;\n } else if (typeof aiMessages === \"string\") {\n result.input = tryJson(aiMessages) ?? aiMessages;\n } else if (typeof aiPrompt === \"string\") {\n const parsed = tryJson(aiPrompt) as Record<string, unknown> | null;\n if (parsed && typeof parsed === \"object\") {\n const messages: { role: string; content: unknown }[] = [];\n if (parsed[\"system\"]) messages.push({ role: \"system\", content: parsed[\"system\"] });\n if (Array.isArray(parsed[\"messages\"])) {\n messages.push(...(parsed[\"messages\"] as { role: string; content: unknown }[]));\n } else if (parsed[\"prompt\"] !== undefined) {\n messages.push({ role: \"user\", content: parsed[\"prompt\"] });\n }\n result.input = messages.length > 0 ? messages : parsed;\n } else {\n result.input = aiPrompt;\n }\n }\n\n // ── Output ────────────────────────────────────────────────────────────────\n const toolResult = attrs[\"ai.toolCall.result\"];\n const aiText = attrs[\"ai.response.text\"];\n const aiToolCalls = attrs[\"ai.response.toolCalls\"];\n\n if (typeof toolResult === \"string\") {\n result.output = tryJson(toolResult) ?? toolResult;\n } else if (typeof aiText === \"string\") {\n result.output = aiText;\n } else if (typeof aiToolCalls === \"string\") {\n const parsed = tryJson(aiToolCalls);\n if (Array.isArray(parsed)) {\n result.output = parsed.map((tc: Record<string, unknown>) => ({\n ...tc,\n input:\n typeof tc[\"input\"] === \"string\"\n ? (tryJson(tc[\"input\"]) ?? tc[\"input\"])\n : tc[\"input\"],\n }));\n } else {\n result.output = parsed ?? aiToolCalls;\n }\n }\n\n // ── Model / provider ──────────────────────────────────────────────────────\n const model = strAttr(attrs, \"ai.model.id\", \"ai.response.model\", \"gen_ai.request.model\");\n if (model) result.model = model;\n\n const provider = strAttr(attrs, \"ai.model.provider\", \"gen_ai.system\");\n if (provider) result.provider = provider;\n\n // ── Tokens ────────────────────────────────────────────────────────────────\n const input_tokens = intAttr(\n attrs,\n \"ai.usage.inputTokens\",\n \"ai.usage.promptTokens\",\n \"gen_ai.usage.input_tokens\",\n );\n if (input_tokens != null) result.input_tokens = input_tokens;\n\n const output_tokens = intAttr(\n attrs,\n \"ai.usage.outputTokens\",\n \"ai.usage.completionTokens\",\n \"gen_ai.usage.output_tokens\",\n );\n if (output_tokens != null) result.output_tokens = output_tokens;\n\n // ── Cost ──────────────────────────────────────────────────────────────────\n const providerMeta = attrs[\"ai.response.providerMetadata\"];\n if (typeof providerMeta === \"string\") {\n const cost = extractCost(providerMeta);\n if (cost.input_cost_usd != null) result.input_cost_usd = cost.input_cost_usd;\n if (cost.output_cost_usd != null) result.output_cost_usd = cost.output_cost_usd;\n }\n\n // ── Cost from explicit breadcrumb attrs (none here — handled by mapBreadcrumb) ─\n\n // ── Metadata pass-through ─────────────────────────────────────────────────\n // Collect unrecognised ai.* / gen_ai.* attrs as metadata.\n const metadata: Record<string, string> = {};\n\n // ai.response.finishReason is in HANDLED (excluded from pass-through) but\n // still needs to appear in metadata under a clean key.\n const finishReason = attrs[\"ai.response.finishReason\"];\n if (typeof finishReason === \"string\" && finishReason !== \"\") {\n metadata[\"finish_reason\"] = finishReason;\n }\n\n for (const [k, v] of Object.entries(attrs)) {\n if (v == null) continue;\n if (HANDLED.has(k) || DROP.has(k)) continue;\n if (k.startsWith(\"ai.settings.\") || k.startsWith(\"ai.request.headers.\")) continue;\n\n if (k.startsWith(\"ai.telemetry.metadata.\")) {\n metadata[k.slice(\"ai.telemetry.metadata.\".length)] = String(v);\n continue;\n }\n // Only pass through ai.* and gen_ai.* here; other namespaces are handled\n // by the exporter's own pass-through for truly unknown attributes.\n if (k.startsWith(\"ai.\") || k.startsWith(\"gen_ai.\")) {\n metadata[k] = String(v);\n }\n }\n\n if (Object.keys(metadata).length > 0) result.metadata = metadata;\n\n return result;\n}\n","import type { ReadableSpan } from \"@opentelemetry/sdk-trace-base\";\nimport type { MappedSpanData, SpanType } from \"./types.js\";\nimport { tryJson, strAttr, intAttr, floatAttr } from \"./utils.js\";\n\nconst VALID_TYPES = new Set<string>([\"llm\", \"tool\", \"retrieval\", \"step\", \"custom\"]);\n\nexport function mapBreadcrumb(span: ReadableSpan): Partial<MappedSpanData> {\n const attrs = span.attributes;\n const result: Partial<MappedSpanData> = {};\n\n // ── Type override ─────────────────────────────────────────────────────────\n const explicitType = attrs[\"breadcrumb.span.type\"];\n if (typeof explicitType === \"string\" && VALID_TYPES.has(explicitType)) {\n result.type = explicitType as SpanType;\n }\n\n // ── Input ─────────────────────────────────────────────────────────────────\n const rawInput = attrs[\"breadcrumb.input\"];\n if (rawInput != null) {\n result.input =\n typeof rawInput === \"string\" ? (tryJson(rawInput) ?? rawInput) : rawInput;\n }\n\n // ── Output ────────────────────────────────────────────────────────────────\n const rawOutput = attrs[\"breadcrumb.output\"];\n if (rawOutput != null) {\n result.output =\n typeof rawOutput === \"string\" ? (tryJson(rawOutput) ?? rawOutput) : rawOutput;\n }\n\n // ── Model / provider ──────────────────────────────────────────────────────\n const model = strAttr(attrs, \"breadcrumb.model\");\n if (model) result.model = model;\n\n const provider = strAttr(attrs, \"breadcrumb.provider\");\n if (provider) result.provider = provider;\n\n // ── Tokens ────────────────────────────────────────────────────────────────\n const input_tokens = intAttr(attrs, \"breadcrumb.input_tokens\");\n if (input_tokens != null) result.input_tokens = input_tokens;\n\n const output_tokens = intAttr(attrs, \"breadcrumb.output_tokens\");\n if (output_tokens != null) result.output_tokens = output_tokens;\n\n // ── Cost ──────────────────────────────────────────────────────────────────\n const input_cost_usd = floatAttr(attrs, \"breadcrumb.input_cost_usd\");\n if (input_cost_usd != null) result.input_cost_usd = input_cost_usd;\n\n const output_cost_usd = floatAttr(attrs, \"breadcrumb.output_cost_usd\");\n if (output_cost_usd != null) result.output_cost_usd = output_cost_usd;\n\n // ── Metadata ──────────────────────────────────────────────────────────────\n const metadata: Record<string, string> = {};\n for (const [k, v] of Object.entries(attrs)) {\n if (v == null) continue;\n if (k.startsWith(\"breadcrumb.meta.\")) {\n metadata[k.slice(\"breadcrumb.meta.\".length)] = String(v);\n }\n }\n if (Object.keys(metadata).length > 0) result.metadata = metadata;\n\n return result;\n}\n","import type { ExportResult } from \"@opentelemetry/core\";\nimport { ExportResultCode } from \"@opentelemetry/core\";\nimport type { SpanExporter, ReadableSpan } from \"@opentelemetry/sdk-trace-base\";\nimport { SpanStatusCode } from \"@opentelemetry/api\";\nimport { mapAiSdk } from \"./mappers/ai-sdk.js\";\nimport { mapBreadcrumb } from \"./mappers/breadcrumb.js\";\nimport type { MappedSpanData } from \"./mappers/types.js\";\n\n// Attribute namespaces fully handled by mappers — excluded from the generic\n// pass-through that collects remaining unknown attrs into metadata.\nconst MAPPER_NAMESPACES = [\"ai.\", \"gen_ai.\", \"breadcrumb.\", \"resource.name\"];\n\n\n// Non-namespaced keys that should be dropped entirely (not in metadata).\n// These come from AI SDK / OTel conventions and are not user-meaningful.\nconst GLOBAL_DROP = new Set([\"operation.name\"]);\n\nfunction hrTimeToISO(hrTime: [number, number]): string {\n return new Date(hrTime[0] * 1000 + hrTime[1] / 1_000_000).toISOString();\n}\n\nfunction spanStatus(span: ReadableSpan): \"ok\" | \"error\" {\n return span.status.code === SpanStatusCode.ERROR ? \"error\" : \"ok\";\n}\n\nfunction mergeMappers(span: ReadableSpan): MappedSpanData {\n const aiSdk = mapAiSdk(span);\n const bc = mapBreadcrumb(span);\n\n // breadcrumb (user-set) wins for all scalar fields; metadata is merged with\n // breadcrumb keys overriding matching AI SDK keys.\n return {\n ...aiSdk,\n ...bc,\n metadata:\n aiSdk.metadata || bc.metadata\n ? { ...aiSdk.metadata, ...bc.metadata }\n : undefined,\n };\n}\n\n// Collect attributes not handled by any mapper (unknown namespaces like\n// \"custom.key\", bare keys like \"score\") into metadata as strings.\nfunction passthroughMetadata(\n span: ReadableSpan,\n existing: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const extra: Record<string, string> = {};\n for (const [k, v] of Object.entries(span.attributes)) {\n if (v == null) continue;\n const handled = MAPPER_NAMESPACES.some((ns) =>\n k === ns || k.startsWith(ns),\n );\n if (handled || GLOBAL_DROP.has(k)) continue;\n extra[k] = String(v);\n }\n if (Object.keys(extra).length === 0) return existing || undefined;\n return { ...extra, ...existing }; // existing (breadcrumb) still wins\n}\n\nexport class BreadcrumbSpanExporter implements SpanExporter {\n constructor(\n private readonly apiKey: string,\n private readonly baseUrl: string,\n private readonly environment?: string,\n ) {}\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n this._export(spans).then(\n () => resultCallback({ code: ExportResultCode.SUCCESS }),\n () => resultCallback({ code: ExportResultCode.SUCCESS }), // fail silently\n );\n }\n\n private async _export(spans: ReadableSpan[]): Promise<void> {\n try {\n const roots = spans.filter((s) => !s.parentSpanId);\n const spanPayloads = spans.map((s) => this._mapSpan(s));\n\n const sends: Promise<void>[] = roots.map((s) => this._sendTrace(s));\n if (spanPayloads.length > 0) {\n sends.push(this._post(\"/v1/spans\", spanPayloads));\n }\n\n await Promise.all(sends);\n } catch {\n // Fail silently\n }\n }\n\n private _mapSpan(span: ReadableSpan) {\n const ctx = span.spanContext();\n const mapped = mergeMappers(span);\n const metadata = passthroughMetadata(span, mapped.metadata);\n\n return {\n id: ctx.spanId,\n trace_id: ctx.traceId,\n parent_span_id: span.parentSpanId || undefined,\n name: mapped.name ?? span.name,\n type: mapped.type ?? \"custom\",\n start_time: hrTimeToISO(span.startTime),\n end_time: hrTimeToISO(span.endTime),\n status: spanStatus(span),\n status_message: span.status.message || undefined,\n input: mapped.input !== undefined ? mapped.input : undefined,\n output: mapped.output !== undefined ? mapped.output : undefined,\n provider: mapped.provider,\n model: mapped.model,\n input_tokens: mapped.input_tokens,\n output_tokens: mapped.output_tokens,\n input_cost_usd: mapped.input_cost_usd,\n output_cost_usd: mapped.output_cost_usd,\n metadata: metadata && Object.keys(metadata).length > 0 ? metadata : undefined,\n };\n }\n\n private async _sendTrace(span: ReadableSpan): Promise<void> {\n const ctx = span.spanContext();\n const mapped = mergeMappers(span);\n await this._post(\"/v1/traces\", {\n id: ctx.traceId,\n name: mapped.name ?? span.name,\n start_time: hrTimeToISO(span.startTime),\n end_time: hrTimeToISO(span.endTime),\n status: spanStatus(span),\n status_message: span.status.message || undefined,\n environment: this.environment,\n });\n }\n\n private async _post(path: string, body: unknown): Promise<void> {\n try {\n await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n } catch {\n // Fail silently — backend unreachable\n }\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve();\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve();\n }\n}\n","import {\n context,\n trace,\n ROOT_CONTEXT,\n SpanStatusCode,\n type Span as OtelSpan,\n} from \"@opentelemetry/api\";\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\";\nimport {\n SimpleSpanProcessor,\n BatchSpanProcessor,\n} from \"@opentelemetry/sdk-trace-base\";\nimport { BreadcrumbSpanExporter } from \"./exporter.js\";\nimport type { Breadcrumb, BreadcrumbSpan, SpanOptions, SpanData, Message } from \"./types.js\";\n\nexport type { Breadcrumb, BreadcrumbSpan, SpanOptions, SpanData, Message };\n\nexport interface InitOptions {\n apiKey: string;\n baseUrl: string;\n environment?: string;\n batching?:\n | false\n | {\n flushInterval?: number;\n maxBatchSize?: number;\n };\n}\n\nexport function init(options: InitOptions): Breadcrumb {\n const exporter = new BreadcrumbSpanExporter(\n options.apiKey,\n options.baseUrl,\n options.environment,\n );\n\n const batchOpts =\n typeof options.batching === \"object\" ? options.batching : undefined;\n\n const processor =\n options.batching === false\n ? new SimpleSpanProcessor(exporter)\n : new BatchSpanProcessor(exporter, {\n scheduledDelayMillis: batchOpts?.flushInterval ?? 5000,\n maxExportBatchSize: batchOpts?.maxBatchSize ?? 100,\n });\n\n const provider = new NodeTracerProvider({ spanProcessors: [processor] });\n provider.register();\n\n process.once(\"beforeExit\", async () => {\n await provider.shutdown().catch(() => {});\n });\n\n const tracer = provider.getTracer(\"@breadcrumb-sdk/core\");\n\n function runSpan<T>(\n otelSpan: OtelSpan,\n activeCtx: typeof ROOT_CONTEXT,\n fn: (span: BreadcrumbSpan) => Promise<T>,\n ): Promise<T> {\n const bcSpan: BreadcrumbSpan = {\n set(data) {\n const { metadata, ...semantic } = data;\n for (const [key, value] of Object.entries(semantic)) {\n if (value == null) continue;\n const attrKey = `breadcrumb.${key}`;\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n otelSpan.setAttribute(attrKey, value);\n } else {\n otelSpan.setAttribute(attrKey, JSON.stringify(value));\n }\n }\n if (metadata) {\n for (const [key, value] of Object.entries(metadata)) {\n if (value == null) continue;\n otelSpan.setAttribute(`breadcrumb.meta.${key}`, value);\n }\n }\n },\n };\n\n return context.with(trace.setSpan(activeCtx, otelSpan), async () => {\n try {\n const result = await fn(bcSpan);\n otelSpan.setStatus({ code: SpanStatusCode.OK });\n otelSpan.end();\n return result;\n } catch (err) {\n otelSpan.setStatus({\n code: SpanStatusCode.ERROR,\n message: err instanceof Error ? err.message : String(err),\n });\n otelSpan.end();\n throw err;\n }\n });\n }\n\n return {\n trace<T>(\n name: string,\n fn: (span: BreadcrumbSpan) => Promise<T>,\n ): Promise<T> {\n const otelSpan = tracer.startSpan(name, {}, ROOT_CONTEXT);\n return runSpan(otelSpan, ROOT_CONTEXT, fn);\n },\n\n span<T>(\n name: string,\n fn: (span: BreadcrumbSpan) => Promise<T>,\n options?: SpanOptions,\n ): Promise<T> {\n const activeCtx = context.active();\n const otelSpan = tracer.startSpan(name, {}, activeCtx);\n if (options?.type) {\n otelSpan.setAttribute(\"breadcrumb.span.type\", options.type);\n }\n return runSpan(otelSpan, activeCtx, fn);\n },\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@breadcrumb-sdk/core",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"