neatlogs 1.1.21 → 1.1.22

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
@@ -536,7 +536,7 @@ matrix; API-shaped rows deliberately make no blanket semver claim.
536
536
  | Google GenAI | `@google/genai` 1.34.x | `wrapGoogleGenAI(client)` / `wrapGoogleGenAIChat(chat)` | `neatlogs/google-genai` |
537
537
  | Vertex AI through `@google/genai` | `@google/genai` 1.34.x | `wrapVertexAI(client)` / `wrapVertexAIChat(chat)` | `neatlogs/vertex-ai` |
538
538
  | OpenRouter Agent | `@openrouter/agent` 0.7.x | `wrapOpenRouterAgent(client)` / `wrapCallModel(fn)` | `neatlogs/openrouter-agent` |
539
- | Vercel AI SDK | `ai` 6.x | `wrapAISDK(ai)` | `neatlogs/ai` |
539
+ | Vercel AI SDK | `ai` 6.x and 7.x | `wrapAISDK(ai)` | `neatlogs/ai` |
540
540
  | Mastra | `@mastra/core` 1.32.x | `wrapMastra(entity)` / `wrapMastraRerank(fn)` | `neatlogs/mastra` |
541
541
  | Claude Agent SDK | documented `query()` API | `wrapClaudeAgentSDK(sdk)` | `neatlogs/claude-agent-sdk` |
542
542
  | LangChain / LangGraph | `@langchain/core` 0.3.x | `langchainHandler()` callback | `neatlogs` or `neatlogs/langchain` |
@@ -565,22 +565,25 @@ const { text } = await generateText({
565
565
  prompt: 'What is TypeScript?',
566
566
  });
567
567
 
568
- // AI SDK v6 agents are supported too. The wrapper injects telemetry into the
569
- // constructor settings, including calls returned from a custom prepareCall.
568
+ // Agents are supported in both versions. The wrapper selects `telemetry` for
569
+ // AI SDK v7 and `experimental_telemetry` for AI SDK v6 automatically.
570
570
  const agent = new ToolLoopAgent({
571
571
  id: 'support-agent',
572
572
  model: openai('gpt-4o-mini'),
573
- experimental_telemetry: { functionId: 'support-agent' },
573
+ telemetry: { functionId: 'support-agent' }, // use experimental_telemetry on v6
574
574
  });
575
575
  await agent.generate({ prompt: 'Help me debug my order' });
576
576
 
577
577
  await shutdown();
578
578
  ```
579
579
 
580
- If a call already supplies an `experimental_telemetry.tracer` (for example,
581
- Laminar), the wrapper mirrors the AI SDK's native spans to both that tracer and
582
- Neatlogs. The caller-owned tracer remains the global context owner; Neatlogs
583
- keeps separate parent context and export state in its private provider.
580
+ AI SDK v7 users must also install the telemetry adapter with
581
+ `npm install @ai-sdk/otel`. AI SDK v6 users do not need that package.
582
+
583
+ If a call supplies a tracer through `createAITelemetry` (for example, Laminar),
584
+ the wrapper mirrors the AI SDK's native spans to both that tracer and Neatlogs.
585
+ The caller-owned tracer remains the global context owner; Neatlogs keeps
586
+ separate parent context and export state in its private provider.
584
587
 
585
588
  The same coexistence is available without the wrapper by passing the existing
586
589
  tracer to `createAITelemetry`:
@@ -593,7 +596,7 @@ import { createAITelemetry } from 'neatlogs/ai';
593
596
  await streamText({
594
597
  model,
595
598
  prompt,
596
- experimental_telemetry: createAITelemetry({
599
+ telemetry: createAITelemetry({ // use experimental_telemetry on AI SDK v6
597
600
  tracer: getTracer(),
598
601
  functionId: 'progress-narration',
599
602
  }),
package/dist/ai-sdk.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/ai-sdk.ts
@@ -126,10 +136,104 @@ function withNeatlogsSpan(span, fn, baseContext, rootSpan) {
126
136
 
127
137
  // src/ai-sdk.ts
128
138
  var TRACER_NAME = "neatlogs.ai-sdk";
139
+ var NEATLOGS_V7_INTEGRATION = /* @__PURE__ */ Symbol("neatlogs.ai-sdk.v7-integration");
140
+ var LazyV7OpenTelemetryIntegration = class {
141
+ constructor(tracer, metadata) {
142
+ this.tracer = tracer;
143
+ this.metadata = metadata;
144
+ }
145
+ tracer;
146
+ metadata;
147
+ [NEATLOGS_V7_INTEGRATION] = true;
148
+ delegatePromise;
149
+ getDelegate() {
150
+ return this.delegatePromise ??= import("@ai-sdk/otel").then(
151
+ ({ OpenTelemetry }) => new OpenTelemetry({
152
+ tracer: this.tracer,
153
+ enrichSpan: () => this.metadata
154
+ })
155
+ ).catch((error) => {
156
+ const detail = error instanceof Error ? `: ${error.message}` : "";
157
+ throw new Error(
158
+ "Vercel AI SDK v7 telemetry requires the optional @ai-sdk/otel peer dependency" + detail
159
+ );
160
+ });
161
+ }
162
+ async notify(method, event) {
163
+ const delegate = await this.getDelegate();
164
+ const fn = delegate[method];
165
+ if (typeof fn === "function") {
166
+ await Reflect.apply(fn, delegate, [event]);
167
+ }
168
+ }
169
+ onStart(event) {
170
+ return this.notify("onStart", event);
171
+ }
172
+ onStepStart(event) {
173
+ return this.notify("onStepStart", event);
174
+ }
175
+ onLanguageModelCallStart(event) {
176
+ return this.notify("onLanguageModelCallStart", event);
177
+ }
178
+ onLanguageModelCallEnd(event) {
179
+ return this.notify("onLanguageModelCallEnd", event);
180
+ }
181
+ onToolExecutionStart(event) {
182
+ return this.notify("onToolExecutionStart", event);
183
+ }
184
+ onToolExecutionEnd(event) {
185
+ return this.notify("onToolExecutionEnd", event);
186
+ }
187
+ onStepEnd(event) {
188
+ return this.notify("onStepEnd", event);
189
+ }
190
+ onStepFinish(event) {
191
+ return this.notify("onStepFinish", event);
192
+ }
193
+ onObjectStepStart(event) {
194
+ return this.notify("onObjectStepStart", event);
195
+ }
196
+ onObjectStepEnd(event) {
197
+ return this.notify("onObjectStepEnd", event);
198
+ }
199
+ onEmbedStart(event) {
200
+ return this.notify("onEmbedStart", event);
201
+ }
202
+ onEmbedEnd(event) {
203
+ return this.notify("onEmbedEnd", event);
204
+ }
205
+ onRerankStart(event) {
206
+ return this.notify("onRerankStart", event);
207
+ }
208
+ onRerankEnd(event) {
209
+ return this.notify("onRerankEnd", event);
210
+ }
211
+ onEnd(event) {
212
+ return this.notify("onEnd", event);
213
+ }
214
+ onAbort(event) {
215
+ return this.notify("onAbort", event);
216
+ }
217
+ onError(event) {
218
+ return this.notify("onError", event);
219
+ }
220
+ async executeLanguageModelCall(options) {
221
+ const delegate = await this.getDelegate();
222
+ const fn = delegate.executeLanguageModelCall;
223
+ return typeof fn === "function" ? Reflect.apply(fn, delegate, [options]) : options.execute();
224
+ }
225
+ async executeTool(options) {
226
+ const delegate = await this.getDelegate();
227
+ const fn = delegate.executeTool;
228
+ return typeof fn === "function" ? Reflect.apply(fn, delegate, [options]) : options.execute();
229
+ }
230
+ };
129
231
  function createAITelemetry(opts = {}) {
130
232
  const userMeta = opts.metadata ?? {};
131
233
  const neatlogsTracer = getRoutingNeatlogsTracer(TRACER_NAME);
132
234
  const callerTracer = opts.tracer;
235
+ const tracer = callerTracer ? createMirroredTracer(callerTracer, neatlogsTracer) : neatlogsTracer;
236
+ const metadata = callerTracer ? { ...userMeta } : { ...userMeta, neatlogsWrapped: true };
133
237
  return {
134
238
  isEnabled: true,
135
239
  recordInputs: true,
@@ -138,11 +242,12 @@ function createAITelemetry(opts = {}) {
138
242
  // internally, which would otherwise parent its native spans from the foreign
139
243
  // global context AND push them onto it (so a co-tenant's next span inherits
140
244
  // ours). The facade routes both through the private Neatlogs context.
141
- tracer: callerTracer ? createMirroredTracer(callerTracer, neatlogsTracer) : neatlogsTracer,
245
+ tracer,
142
246
  ...opts.functionId !== void 0 ? { functionId: opts.functionId } : {},
143
247
  // The marker is an implementation detail used only when Neatlogs owns the
144
248
  // telemetry stream. Do not leak it into caller-owned providers.
145
- metadata: callerTracer ? { ...userMeta } : { ...userMeta, neatlogsWrapped: true }
249
+ metadata,
250
+ integrations: [new LazyV7OpenTelemetryIntegration(tracer, metadata)]
146
251
  };
147
252
  }
148
253
  function safeStringify(value) {
@@ -175,7 +280,7 @@ function setOutputValue(span, result) {
175
280
  span.setAttribute("output.value", text);
176
281
  }
177
282
  if (r.finishReason) {
178
- span.setAttribute("gen_ai.finish_reason", String(r.finishReason));
283
+ span.setAttribute("neatlogs.llm.finish_reason", String(r.finishReason));
179
284
  }
180
285
  return;
181
286
  }
@@ -184,7 +289,7 @@ function setOutputValue(span, result) {
184
289
  span.setAttribute("output.value", safeStringify(r.object));
185
290
  }
186
291
  if (r.finishReason) {
187
- span.setAttribute("gen_ai.finish_reason", String(r.finishReason));
292
+ span.setAttribute("neatlogs.llm.finish_reason", String(r.finishReason));
188
293
  }
189
294
  return;
190
295
  }
@@ -204,7 +309,7 @@ function setStreamOutputValue(span, event) {
204
309
  if (stringified) span.setAttribute("output.value", stringified);
205
310
  }
206
311
  if (e.finishReason) {
207
- span.setAttribute("gen_ai.finish_reason", String(e.finishReason));
312
+ span.setAttribute("neatlogs.llm.finish_reason", String(e.finishReason));
208
313
  }
209
314
  }
210
315
  var WRAPPED_FUNCTIONS = [
@@ -224,6 +329,8 @@ var wrappedExports = /* @__PURE__ */ new WeakSet();
224
329
  var wrapperByOriginal = /* @__PURE__ */ new WeakMap();
225
330
  function wrapAISDK(aiModule) {
226
331
  const wrapped = { ...aiModule };
332
+ const hasRegisterTelemetry = "registerTelemetry" in aiModule && typeof Reflect.get(aiModule, "registerTelemetry") === "function";
333
+ const telemetryKey = hasRegisterTelemetry ? "telemetry" : "experimental_telemetry";
227
334
  for (const name of WRAPPED_FUNCTIONS) {
228
335
  const original = aiModule[name];
229
336
  if (typeof original !== "function") continue;
@@ -235,12 +342,16 @@ function wrapAISDK(aiModule) {
235
342
  if (name === "streamText" || name === "streamObject") {
236
343
  wrapped[name] = cacheWrapper(
237
344
  original,
238
- createStreamWrapper(name, original)
345
+ createStreamWrapper(name, original, telemetryKey)
239
346
  );
240
347
  } else {
241
348
  wrapped[name] = cacheWrapper(
242
349
  original,
243
- createAsyncWrapper(name, original)
350
+ createAsyncWrapper(
351
+ name,
352
+ original,
353
+ telemetryKey
354
+ )
244
355
  );
245
356
  }
246
357
  }
@@ -250,7 +361,7 @@ function wrapAISDK(aiModule) {
250
361
  const existing = getExistingWrapper(original);
251
362
  wrapped[name] = existing ?? cacheWrapper(
252
363
  original,
253
- createAgentConstructorWrapper(original)
364
+ createAgentConstructorWrapper(original, telemetryKey)
254
365
  );
255
366
  }
256
367
  return wrapped;
@@ -264,26 +375,30 @@ function cacheWrapper(original, wrapped) {
264
375
  wrappedExports.add(wrapped);
265
376
  return wrapped;
266
377
  }
267
- function createAgentConstructorWrapper(original) {
378
+ function createAgentConstructorWrapper(original, telemetryKey) {
268
379
  return new Proxy(original, {
269
380
  construct(target, args, newTarget) {
270
381
  if (args.length === 0 || typeof args[0] !== "object" || args[0] === null) {
271
382
  return Reflect.construct(target, args, newTarget);
272
383
  }
273
- const settings = mergeAgentSettings(args[0]);
384
+ const settings = mergeAgentSettings(args[0], telemetryKey);
274
385
  return Reflect.construct(target, [settings, ...args.slice(1)], newTarget);
275
386
  }
276
387
  });
277
388
  }
278
- function mergeAgentSettings(settings) {
279
- const merged = mergeTelemetry(settings);
389
+ function mergeAgentSettings(settings, telemetryKey) {
390
+ const merged = mergeTelemetry(settings, telemetryKey);
280
391
  const userPrepareCall = settings.prepareCall;
281
392
  if (typeof userPrepareCall !== "function") return merged;
282
393
  return {
283
394
  ...merged,
284
395
  prepareCall: async function wrappedPrepareCall(...args) {
285
396
  const prepared = await Reflect.apply(userPrepareCall, this, args);
286
- return prepared == null ? prepared : mergeTelemetry(prepared, settings.experimental_telemetry);
397
+ return prepared == null ? prepared : mergeTelemetry(
398
+ prepared,
399
+ telemetryKey,
400
+ settings.telemetry ?? settings.experimental_telemetry
401
+ );
287
402
  }
288
403
  };
289
404
  }
@@ -295,7 +410,7 @@ function rootSpanKind(name) {
295
410
  function getParentContext() {
296
411
  return getNeatlogsParentContext();
297
412
  }
298
- function createAsyncWrapper(name, original) {
413
+ function createAsyncWrapper(name, original, telemetryKey) {
299
414
  return async function wrappedAsyncFn(opts) {
300
415
  const tracer = getNeatlogsTracer(TRACER_NAME);
301
416
  const parentContext = getParentContext();
@@ -315,7 +430,7 @@ function createAsyncWrapper(name, original) {
315
430
  if (name === "rerank" && opts?.query) {
316
431
  span.setAttribute("ai.rerank.query", String(opts.query));
317
432
  }
318
- const merged = mergeTelemetry(opts);
433
+ const merged = mergeTelemetry(opts, telemetryKey);
319
434
  const result = await original(merged);
320
435
  if (!isEmbedOrRerank) {
321
436
  setOutputValue(span, result);
@@ -332,7 +447,7 @@ function createAsyncWrapper(name, original) {
332
447
  );
333
448
  };
334
449
  }
335
- function createStreamWrapper(name, original) {
450
+ function createStreamWrapper(name, original, telemetryKey) {
336
451
  return function wrappedStreamFn(opts) {
337
452
  const tracer = getNeatlogsTracer(TRACER_NAME);
338
453
  const parentContext = getParentContext();
@@ -352,7 +467,7 @@ function createStreamWrapper(name, original) {
352
467
  };
353
468
  try {
354
469
  setInputValue(span, opts);
355
- const merged = mergeTelemetry(opts);
470
+ const merged = mergeTelemetry(opts, telemetryKey);
356
471
  const userOnFinish = opts?.onFinish;
357
472
  const userOnError = opts?.onError;
358
473
  const wrappedOpts = {
@@ -477,25 +592,47 @@ function createMirroredTracer(primary, secondary) {
477
592
  })
478
593
  };
479
594
  }
480
- function mergeTelemetry(opts, fallbackTelemetry) {
595
+ function isNeatlogsV7Integration(integration) {
596
+ return typeof integration === "object" && integration !== null && NEATLOGS_V7_INTEGRATION in integration;
597
+ }
598
+ function mergeTelemetry(opts, telemetryKey, fallbackTelemetry) {
599
+ const legacyTelemetry = opts?.experimental_telemetry ?? {};
600
+ const v7Telemetry = opts?.telemetry ?? {};
601
+ const preferredTelemetry = telemetryKey === "telemetry" ? { ...legacyTelemetry, ...v7Telemetry } : { ...v7Telemetry, ...legacyTelemetry };
481
602
  const requestedTelemetry = {
482
603
  ...fallbackTelemetry,
483
- ...opts?.experimental_telemetry,
604
+ ...preferredTelemetry,
484
605
  metadata: {
485
606
  ...fallbackTelemetry?.metadata,
486
- ...opts?.experimental_telemetry?.metadata
607
+ ...legacyTelemetry.metadata,
608
+ ...v7Telemetry.metadata
487
609
  }
488
610
  };
489
- const baseTelemetry = createAITelemetry({
611
+ const existingNeatlogsIntegration = Array.isArray(
612
+ requestedTelemetry.integrations
613
+ ) ? requestedTelemetry.integrations.find(isNeatlogsV7Integration) : void 0;
614
+ const baseTelemetry = existingNeatlogsIntegration ? {
615
+ isEnabled: true,
616
+ recordInputs: true,
617
+ recordOutputs: true,
618
+ tracer: requestedTelemetry.tracer,
619
+ ...requestedTelemetry.functionId !== void 0 ? { functionId: requestedTelemetry.functionId } : {},
620
+ metadata: requestedTelemetry.metadata,
621
+ integrations: [existingNeatlogsIntegration]
622
+ } : createAITelemetry({
490
623
  functionId: requestedTelemetry.functionId,
491
624
  metadata: requestedTelemetry.metadata,
492
625
  tracer: requestedTelemetry.tracer
493
626
  });
494
627
  const callerTracer = requestedTelemetry.tracer;
495
628
  const hasCallerTracer = callerTracer !== void 0;
629
+ const requestedIntegrations = Array.isArray(requestedTelemetry.integrations) ? requestedTelemetry.integrations.filter(
630
+ (integration) => !isNeatlogsV7Integration(integration)
631
+ ) : [];
632
+ const { telemetry: _telemetry, experimental_telemetry: _legacy, ...rest } = opts ?? {};
496
633
  return {
497
- ...opts,
498
- experimental_telemetry: {
634
+ ...rest,
635
+ [telemetryKey]: {
499
636
  ...baseTelemetry,
500
637
  ...requestedTelemetry,
501
638
  isEnabled: true,
@@ -505,7 +642,8 @@ function mergeTelemetry(opts, fallbackTelemetry) {
505
642
  // Do not add Neatlogs-only marker metadata to a caller-owned telemetry
506
643
  // pipeline such as Laminar. Both providers receive the same AI SDK span
507
644
  // data, while their providers, parent contexts, and exporters stay separate.
508
- metadata: hasCallerTracer ? requestedTelemetry.metadata : baseTelemetry.metadata
645
+ metadata: hasCallerTracer ? requestedTelemetry.metadata : baseTelemetry.metadata,
646
+ integrations: [...baseTelemetry.integrations, ...requestedIntegrations]
509
647
  }
510
648
  };
511
649
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ai-sdk.ts","../src/core/provider.ts","../src/core/active-client.ts"],"sourcesContent":["/**\n * Vercel AI SDK wrapper — inline implementation.\n *\n * Wraps `generateText`, `streamText`, `generateObject`, `streamObject` from\n * the `ai` package with OTel parent spans + forced telemetry. Static export,\n * no dynamic imports — bundler-friendly (works with Turbopack, webpack, esbuild).\n *\n * Usage:\n * import { wrapAISDK } from 'neatlogs';\n * import * as ai from 'ai';\n * const { streamText, generateText, ToolLoopAgent } = wrapAISDK(ai);\n */\n\nimport {\n SpanStatusCode,\n type AttributeValue,\n type Context,\n type Span,\n type SpanOptions,\n type Tracer,\n} from '@opentelemetry/api';\nimport {\n getNeatlogsTracer,\n getNeatlogsParentContext,\n getRoutingNeatlogsTracer,\n withNeatlogsSpan,\n} from './core/provider.js';\n\nconst TRACER_NAME = 'neatlogs.ai-sdk';\n\n// -- Telemetry config --------------------------------------------------------\n\nexport interface CreateAITelemetryOptions {\n /** Identifier used by the AI SDK to group telemetry for this operation. */\n functionId?: string;\n metadata?: Record<string, AttributeValue>;\n /**\n * Existing telemetry tracer to preserve alongside Neatlogs (for example,\n * Laminar). Native AI SDK spans are mirrored to both isolated pipelines.\n */\n tracer?: Tracer;\n}\n\nexport interface AITelemetryConfig {\n isEnabled: true;\n recordInputs: true;\n recordOutputs: true;\n tracer: Tracer;\n functionId?: string;\n metadata: Record<string, AttributeValue>;\n}\n\nexport function createAITelemetry(\n opts: CreateAITelemetryOptions = {},\n): AITelemetryConfig {\n const userMeta = opts.metadata ?? {};\n const neatlogsTracer = getRoutingNeatlogsTracer(TRACER_NAME);\n const callerTracer = opts.tracer;\n return {\n isEnabled: true,\n recordInputs: true,\n recordOutputs: true,\n // Hand the AI SDK an isolation-aware tracer: it calls startActiveSpan()\n // internally, which would otherwise parent its native spans from the foreign\n // global context AND push them onto it (so a co-tenant's next span inherits\n // ours). The facade routes both through the private Neatlogs context.\n tracer: callerTracer\n ? createMirroredTracer(callerTracer, neatlogsTracer)\n : neatlogsTracer,\n ...(opts.functionId !== undefined ? { functionId: opts.functionId } : {}),\n // The marker is an implementation detail used only when Neatlogs owns the\n // telemetry stream. Do not leak it into caller-owned providers.\n metadata: callerTracer ? { ...userMeta } : { ...userMeta, neatlogsWrapped: true },\n };\n}\n\n// -- Span attributes ---------------------------------------------------------\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return '';\n }\n}\n\nfunction setInputValue(span: Span, opts: Record<string, unknown>): void {\n // For generateText/streamText — only capture prompt or messages, not full model config\n if (opts && ('prompt' in opts || 'messages' in opts)) {\n const input = opts.messages ?? opts.prompt;\n const stringified = safeStringify(input);\n if (stringified) {\n span.setAttribute('input.value', stringified);\n }\n return;\n }\n const stringified = safeStringify(opts);\n if (stringified) {\n span.setAttribute('input.value', stringified);\n }\n}\n\nfunction setOutputValue(span: Span, result: unknown): void {\n if (result && typeof result === 'object') {\n const r = result as Record<string, unknown>;\n // GenerateTextResult / StreamTextResult — extract meaningful fields\n if ('text' in r && 'finishReason' in r) {\n const text = String(r.text ?? '');\n if (text) {\n span.setAttribute('output.value', text);\n }\n if (r.finishReason) {\n span.setAttribute('gen_ai.finish_reason', String(r.finishReason));\n }\n return;\n }\n // GenerateObjectResult — the structured object is the output, not `text`.\n // Without this the envelope (object+usage+response+…) gets stringified whole.\n if ('object' in r && 'finishReason' in r) {\n if (r.object !== undefined) {\n span.setAttribute('output.value', safeStringify(r.object));\n }\n if (r.finishReason) {\n span.setAttribute('gen_ai.finish_reason', String(r.finishReason));\n }\n return;\n }\n }\n const stringified = safeStringify(result);\n if (stringified) {\n span.setAttribute('output.value', stringified);\n }\n}\n\n// Extract output from a streamText/streamObject `onFinish` event. The event\n// extends StepResult, so `text` (streamText) / `object` (streamObject) sit at\n// the top level alongside `finishReason` — but the event also carries `steps`,\n// `usage`, etc., so we pull only the meaningful fields instead of stringifying\n// the whole envelope.\nfunction setStreamOutputValue(span: Span, event: unknown): void {\n if (!event || typeof event !== 'object') return;\n const e = event as Record<string, unknown>;\n if (typeof e.text === 'string' && e.text) {\n span.setAttribute('output.value', e.text);\n } else if ('object' in e && e.object !== undefined) {\n const stringified = safeStringify(e.object);\n if (stringified) span.setAttribute('output.value', stringified);\n }\n if (e.finishReason) {\n span.setAttribute('gen_ai.finish_reason', String(e.finishReason));\n }\n}\n\n// -- Wrapping ----------------------------------------------------------------\n\ntype WrappedFunctionName =\n | 'generateText'\n | 'streamText'\n | 'generateObject'\n | 'streamObject'\n | 'embed'\n | 'embedMany'\n | 'rerank';\n\nconst WRAPPED_FUNCTIONS: readonly WrappedFunctionName[] = [\n 'generateText',\n 'streamText',\n 'generateObject',\n 'streamObject',\n 'embed',\n 'embedMany',\n 'rerank',\n] as const;\n\ntype WrappedAgentConstructorName = 'ToolLoopAgent' | 'Experimental_Agent';\n\nconst WRAPPED_AGENT_CONSTRUCTORS: readonly WrappedAgentConstructorName[] = [\n 'ToolLoopAgent',\n 'Experimental_Agent',\n] as const;\n\ntype AgentConstructor = new (...args: any[]) => unknown;\n\nconst wrappedExports = new WeakSet<Function>();\nconst wrapperByOriginal = new WeakMap<Function, Function>();\n\n/**\n * Wrap the `ai` module namespace so that every supported generation, embedding,\n * and reranking call:\n *\n * 1. Opens a parent OTel span on the active TracerProvider.\n * 2. Forces `experimental_telemetry: { isEnabled: true }`, merging user metadata.\n * 3. Records input/output on the parent span and propagates errors.\n *\n * AI SDK v6's `ToolLoopAgent` (and its `Experimental_Agent` alias) is wrapped at\n * construction time so its internal model and tool calls receive the same native\n * telemetry configuration. Other exports pass through unchanged.\n */\nexport function wrapAISDK<T extends Record<string, unknown>>(aiModule: T): T {\n const wrapped: Record<string, unknown> = { ...aiModule };\n\n for (const name of WRAPPED_FUNCTIONS) {\n const original = aiModule[name];\n if (typeof original !== 'function') continue;\n\n const existing = getExistingWrapper(original);\n if (existing) {\n wrapped[name] = existing;\n continue;\n }\n\n if (name === 'streamText' || name === 'streamObject') {\n wrapped[name] = cacheWrapper(\n original,\n createStreamWrapper(name, original as (opts: any) => unknown),\n );\n } else {\n wrapped[name] = cacheWrapper(\n original,\n createAsyncWrapper(name, original as (opts: any) => Promise<unknown>),\n );\n }\n }\n\n for (const name of WRAPPED_AGENT_CONSTRUCTORS) {\n const original = aiModule[name];\n if (typeof original !== 'function') continue;\n\n const existing = getExistingWrapper(original);\n wrapped[name] =\n existing ??\n cacheWrapper(\n original,\n createAgentConstructorWrapper(original as AgentConstructor),\n );\n }\n\n return wrapped as T;\n}\n\nfunction getExistingWrapper(original: Function): Function | undefined {\n if (wrappedExports.has(original)) return original;\n return wrapperByOriginal.get(original);\n}\n\nfunction cacheWrapper(original: Function, wrapped: Function): Function {\n wrapperByOriginal.set(original, wrapped);\n wrappedExports.add(wrapped);\n return wrapped;\n}\n\nfunction createAgentConstructorWrapper(\n original: AgentConstructor,\n): AgentConstructor {\n return new Proxy(original, {\n construct(target, args, newTarget) {\n if (\n args.length === 0 ||\n typeof args[0] !== 'object' ||\n args[0] === null\n ) {\n return Reflect.construct(target, args, newTarget);\n }\n\n const settings = mergeAgentSettings(args[0]);\n return Reflect.construct(target, [settings, ...args.slice(1)], newTarget);\n },\n });\n}\n\nfunction mergeAgentSettings(settings: any): any {\n const merged = mergeTelemetry(settings);\n const userPrepareCall = settings.prepareCall;\n if (typeof userPrepareCall !== 'function') return merged;\n\n return {\n ...merged,\n prepareCall: async function wrappedPrepareCall(\n this: unknown,\n ...args: any[]\n ) {\n const prepared = await Reflect.apply(userPrepareCall, this, args);\n return prepared == null\n ? prepared\n : mergeTelemetry(prepared, settings.experimental_telemetry);\n },\n };\n}\n\nfunction rootSpanKind(name: WrappedFunctionName): string {\n if (name === 'embed' || name === 'embedMany' || name === 'rerank')\n return 'CHAIN';\n return 'WORKFLOW';\n}\n\nfunction getParentContext() {\n // Our parent comes solely from the private span store; a\n // foreign provider's active span must never become our ancestor.\n return getNeatlogsParentContext();\n}\n\nfunction createAsyncWrapper(\n name: WrappedFunctionName,\n original: (opts: any) => Promise<unknown>,\n): (opts: any) => Promise<unknown> {\n return async function wrappedAsyncFn(opts: any): Promise<unknown> {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n // startSpan (NOT startActiveSpan) + withNeatlogsSpan: startActiveSpan would\n // push our span onto the GLOBAL OTel context, so a foreign tracer's\n // startSpan() inside generateText() would read it as parent and inherit our\n // trace id. withNeatlogsSpan carries the parent in the private store in\n // the private context, leaving the global context untouched.\n const parentContext = getParentContext();\n const span = tracer.startSpan(\n `ai.${name}`,\n { attributes: { 'openinference.span.kind': rootSpanKind(name) } },\n parentContext,\n );\n return withNeatlogsSpan(\n span,\n async () => {\n try {\n const isEmbedOrRerank =\n name === 'embed' || name === 'embedMany' || name === 'rerank';\n if (!isEmbedOrRerank) {\n setInputValue(span, opts);\n }\n if (name === 'rerank' && opts?.query) {\n span.setAttribute('ai.rerank.query', String(opts.query));\n }\n const merged = mergeTelemetry(opts);\n const result = await original(merged);\n if (!isEmbedOrRerank) {\n setOutputValue(span, result);\n }\n return result;\n } catch (err) {\n recordSpanError(span, err);\n throw err;\n } finally {\n span.end();\n }\n },\n parentContext,\n );\n };\n}\n\n// streamText/streamObject return synchronously while the model keeps producing\n// tokens for seconds afterwards. Ending the span in a `finally` (as a plain sync\n// wrapper would) closes it in ~2ms with no output — the output only exists once\n// the stream finishes. Instead we keep the span open and end it from the AI SDK's\n// `onFinish` callback, where the final text/object is available. Any user-provided\n// `onFinish` is preserved and invoked first.\nfunction createStreamWrapper(\n name: WrappedFunctionName,\n original: (opts: any) => unknown,\n): (opts: any) => unknown {\n return function wrappedStreamFn(opts: any): unknown {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n // startSpan + withNeatlogsSpan (see createAsyncWrapper) so streamText's\n // internals never see our span on the global OTel context. The span stays\n // open past the run scope and is ended from onFinish/onError.\n const parentContext = getParentContext();\n const span = tracer.startSpan(\n `ai.${name}`,\n { attributes: { 'openinference.span.kind': rootSpanKind(name) } },\n parentContext,\n );\n return withNeatlogsSpan(\n span,\n () => {\n let spanEnded = false;\n const endOnce = () => {\n if (spanEnded) return;\n spanEnded = true;\n span.end();\n };\n try {\n setInputValue(span, opts);\n const merged = mergeTelemetry(opts);\n const userOnFinish = opts?.onFinish;\n const userOnError = opts?.onError;\n const wrappedOpts = {\n ...merged,\n onFinish: async (event: any) => {\n try {\n setStreamOutputValue(span, event);\n } finally {\n endOnce();\n }\n if (typeof userOnFinish === 'function') {\n return userOnFinish(event);\n }\n },\n onError: (event: any) => {\n recordSpanError(span, (event && event.error) ?? event);\n endOnce();\n if (typeof userOnError === 'function') {\n return userOnError(event);\n }\n },\n };\n return original(wrappedOpts);\n } catch (err) {\n // Synchronous throw (e.g. bad arguments) — the stream never started.\n recordSpanError(span, err);\n endOnce();\n throw err;\n }\n },\n parentContext,\n );\n };\n}\n\nfunction createMirroredSpan(primary: Span, secondary: Span): Span {\n const mirrored: Span = {\n spanContext() {\n // The caller-owned tracer remains the process-global context owner. Its\n // context is therefore the one external instrumentation must observe.\n return primary.spanContext();\n },\n setAttribute(key, value) {\n primary.setAttribute(key, value);\n secondary.setAttribute(key, value);\n return mirrored;\n },\n setAttributes(attributes) {\n primary.setAttributes(attributes);\n secondary.setAttributes(attributes);\n return mirrored;\n },\n addEvent(name, attributesOrStartTime, startTime) {\n primary.addEvent(name, attributesOrStartTime, startTime);\n secondary.addEvent(name, attributesOrStartTime, startTime);\n return mirrored;\n },\n addLink(link) {\n primary.addLink(link);\n secondary.addLink(link);\n return mirrored;\n },\n addLinks(links) {\n primary.addLinks(links);\n secondary.addLinks(links);\n return mirrored;\n },\n setStatus(status) {\n primary.setStatus(status);\n secondary.setStatus(status);\n return mirrored;\n },\n updateName(name) {\n primary.updateName(name);\n secondary.updateName(name);\n return mirrored;\n },\n end(endTime) {\n primary.end(endTime);\n secondary.end(endTime);\n },\n isRecording() {\n return primary.isRecording() || secondary.isRecording();\n },\n recordException(exception, time) {\n primary.recordException(exception, time);\n secondary.recordException(exception, time);\n },\n };\n return mirrored;\n}\n\n/**\n * Mirror one AI SDK telemetry stream to two isolated tracer pipelines.\n *\n * The caller-owned tracer is deliberately outermost so its normal global OTel\n * activation and parentage stay unchanged. The Neatlogs routing tracer keeps\n * its span active only in Neatlogs' private AsyncLocalStorage context.\n */\nfunction createMirroredTracer(primary: Tracer, secondary: Tracer): Tracer {\n return {\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n const primarySpan = primary.startSpan(name, options, context);\n const secondarySpan = secondary.startSpan(name, options);\n return createMirroredSpan(primarySpan, secondarySpan);\n },\n startActiveSpan: (<F extends (span: Span) => unknown>(\n name: string,\n arg2?: SpanOptions | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> => {\n let options: SpanOptions | undefined;\n let context: Context | undefined;\n let fn: F;\n\n if (typeof arg2 === 'function') {\n fn = arg2;\n } else if (typeof arg3 === 'function') {\n options = arg2;\n fn = arg3;\n } else {\n options = arg2;\n context = arg3 as Context;\n fn = arg4!;\n }\n\n const runSecondary = (primarySpan: Span): ReturnType<F> => {\n const onSecondarySpan = (secondarySpan: Span) =>\n fn(createMirroredSpan(primarySpan, secondarySpan)) as ReturnType<F>;\n return options === undefined\n ? secondary.startActiveSpan(name, onSecondarySpan)\n : secondary.startActiveSpan(name, options, onSecondarySpan);\n };\n\n if (context !== undefined) {\n return primary.startActiveSpan(\n name,\n options ?? {},\n context,\n runSecondary,\n ) as ReturnType<F>;\n }\n return options === undefined\n ? (primary.startActiveSpan(name, runSecondary) as ReturnType<F>)\n : (primary.startActiveSpan(name, options, runSecondary) as ReturnType<F>);\n }) as Tracer['startActiveSpan'],\n };\n}\n\nfunction mergeTelemetry(opts: any, fallbackTelemetry?: any): any {\n const requestedTelemetry = {\n ...fallbackTelemetry,\n ...opts?.experimental_telemetry,\n metadata: {\n ...fallbackTelemetry?.metadata,\n ...opts?.experimental_telemetry?.metadata,\n },\n };\n const baseTelemetry: AITelemetryConfig = createAITelemetry({\n functionId: requestedTelemetry.functionId,\n metadata: requestedTelemetry.metadata,\n tracer: requestedTelemetry.tracer as Tracer | undefined,\n });\n const callerTracer = requestedTelemetry.tracer as Tracer | undefined;\n const hasCallerTracer = callerTracer !== undefined;\n\n return {\n ...opts,\n experimental_telemetry: {\n ...baseTelemetry,\n ...requestedTelemetry,\n isEnabled: true,\n recordInputs: requestedTelemetry.recordInputs ?? true,\n recordOutputs: requestedTelemetry.recordOutputs ?? true,\n tracer: baseTelemetry.tracer,\n // Do not add Neatlogs-only marker metadata to a caller-owned telemetry\n // pipeline such as Laminar. Both providers receive the same AI SDK span\n // data, while their providers, parent contexts, and exporters stay separate.\n metadata: hasCallerTracer\n ? requestedTelemetry.metadata\n : baseTelemetry.metadata,\n },\n };\n}\n\nfunction recordSpanError(span: Span, err: unknown): void {\n if (err instanceof Error) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });\n span.recordException(err);\n } else {\n span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });\n }\n}\n","/**\n * Neatlogs-owned tracing state.\n *\n * Spans are created by the private Neatlogs provider and their parent is carried\n * in a private context key. The process-global OpenTelemetry span is\n * deliberately left untouched so other observability SDKs cannot export or\n * become parents of Neatlogs spans.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n ROOT_CONTEXT,\n INVALID_SPAN_CONTEXT,\n createContextKey,\n trace as otelTrace,\n type Context,\n type Span,\n type SpanOptions,\n type Tracer,\n type TracerProvider,\n} from '@opentelemetry/api';\nimport { getActiveClient } from './active-client.js';\n\n// Carries the trace-ROOT span down the private context so descendants can target\n// it (e.g. setTraceOutput). getActiveNeatlogsSpan() returns the innermost span,\n// which is not the root once nested; this key preserves the root reference.\nconst NEATLOGS_ROOT_SPAN_KEY = createContextKey('neatlogs.root_span');\n\n// Entry points are bundled independently (`neatlogs`, `neatlogs/openai`,\n// `neatlogs/ai`, `neatlogs/mastra`, … each in both CJS and ESM), so every piece\n// of shared tracing state — the private span store AND the resolved provider /\n// provider — must live on `globalThis` behind a `Symbol.for` key.\n// Otherwise `init()` (run from the `neatlogs` bundle) sets `_provider` in ITS\n// module copy while a wrapper imported from `neatlogs/openai` reads a different,\n// still-null copy and silently falls back to the foreign global provider.\nconst PRIVATE_SPAN_STORAGE_KEY = Symbol.for(\n 'neatlogs.private_span_async_local_storage',\n);\nconst PRIVATE_PROVIDER_STATE_KEY = Symbol.for(\n 'neatlogs.private_provider_state',\n);\ninterface PrivateProviderState {\n provider: TracerProvider | null;\n}\ntype NeatlogsGlobal = typeof globalThis & {\n [PRIVATE_SPAN_STORAGE_KEY]?: AsyncLocalStorage<Context>;\n [PRIVATE_PROVIDER_STATE_KEY]?: PrivateProviderState;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\n// Stores the full Neatlogs Context (parent span PLUS any threaded values such as\n// trace()'s prompt-template keys), not just the span. We never\n// activate the OTel global context, so this private store is the ONLY channel\n// through which those values propagate down to descendant spans.\nconst privateContextStorage =\n neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] ??\n (neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] = new AsyncLocalStorage<Context>());\nconst providerState: PrivateProviderState =\n neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] ??\n (neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] = {\n provider: null,\n });\n// Wrappers may be constructed or accidentally invoked before init(). They must\n// never fall back to a foreign process-global provider, so pre-init calls use a\n// local no-op tracer and safely emit no exported spans.\nconst preInitTracer: Tracer = {\n startSpan(): Span {\n return otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n _name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n const fn =\n typeof arg2 === 'function'\n ? arg2\n : typeof arg3 === 'function'\n ? arg3\n : arg4;\n return fn!(otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT)) as ReturnType<F>;\n },\n};\n\n/** @internal Configure the provider used by Neatlogs-created spans. */\nexport function _setNeatlogsProvider(provider: TracerProvider | null): void {\n providerState.provider = provider;\n}\n\n/** Resolve a tracer from the private provider when one is configured. */\nexport function getNeatlogsTracer(name: string): Tracer {\n const client = getActiveClient();\n if (client) return client.getTracer(name);\n return providerState.provider?.getTracer(name) ?? preInitTracer;\n}\n\n/** A reusable tracer facade that resolves the active Client on every call. */\nexport function getRoutingNeatlogsTracer(name: string): Tracer {\n return {\n startSpan(spanName: string, options?: SpanOptions, context?: Context): Span {\n return isolateTracer(getNeatlogsTracer(name)).startSpan(\n spanName,\n options,\n context,\n );\n },\n startActiveSpan: ((...args: any[]) =>\n (isolateTracer(getNeatlogsTracer(name)).startActiveSpan as (...inner: any[]) => any)(\n ...args,\n )) as Tracer['startActiveSpan'],\n };\n}\n\n/**\n * @internal The private Neatlogs provider, or null before\n * init(). Used by integrations that must repoint a self-instrumenting library's\n * captured provider onto ours.\n */\nexport function getNeatlogsProvider(): TracerProvider | null {\n const client = getActiveClient();\n if (client) return client.tracerProvider;\n return providerState.provider;\n}\n\n/** Run a Client callback without inheriting another pipeline's private span. */\nexport function runWithFreshNeatlogsContext<T>(fn: () => T): T {\n return privateContextStorage.run(ROOT_CONTEXT, fn);\n}\n\n/**\n * Wrap a tracer so that spans it creates parent from — and, for\n * `startActiveSpan`, activate on — the PRIVATE Neatlogs context instead of the\n * global one.\n *\n * We hand this to libraries that create their own spans off a tracer we give\n * them (the Vercel AI SDK's `experimental_telemetry.tracer`, which calls\n * `tracer.startActiveSpan()` internally). Without the facade the AI SDK's native\n * spans would parent from `context.active()` — the foreign co-tenant's context —\n * and `startActiveSpan` would push them onto the GLOBAL context, so a foreign\n * tracer's next span reads our native span as its parent. Both directions leak.\n *\n */\nexport function isolateTracer(tracer: Tracer): Tracer {\n const facade: Tracer = {\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n const parent = context ?? getNeatlogsActiveContext();\n return tracer.startSpan(name, options, parent);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n // Normalize the 2/3/4-arg overloads of startActiveSpan.\n let options: SpanOptions | undefined;\n let context: Context | undefined;\n let fn: F;\n if (typeof arg2 === 'function') {\n fn = arg2 as F;\n } else if (typeof arg3 === 'function') {\n options = arg2 as SpanOptions;\n fn = arg3 as F;\n } else {\n options = arg2 as SpanOptions;\n context = arg3 as Context;\n fn = arg4 as F;\n }\n const parent = context ?? getNeatlogsActiveContext();\n const span = tracer.startSpan(name, options, parent);\n return withNeatlogsSpan(span, () => fn(span), parent) as ReturnType<F>;\n },\n };\n return facade;\n}\n\n/**\n * The base context to build new Neatlogs spans and values on. NEVER contains a\n * foreign provider's span: it reads our private store, or ROOT_CONTEXT when\n * nothing is active.\n */\nexport function getNeatlogsActiveContext(): Context {\n return privateContextStorage.getStore() ?? ROOT_CONTEXT;\n}\n\n/** Return only the active Neatlogs span (never a foreign provider's span). */\nexport function getActiveNeatlogsSpan(): Span | undefined {\n return otelTrace.getSpan(getNeatlogsActiveContext());\n}\n\n/**\n * Return the trace-ROOT Neatlogs span, or undefined when no trace is active.\n *\n * Unlike {@link getActiveNeatlogsSpan} (innermost), this is the outermost span\n * of the current trace — the one the backend derives trace-level output from\n * (`parent_span_id=''`). It is stashed on the private context the first time a\n * span becomes active, so nested calls still resolve to the root.\n */\nexport function getNeatlogsRootSpan(): Span | undefined {\n return getNeatlogsActiveContext().getValue(NEATLOGS_ROOT_SPAN_KEY) as\n | Span\n | undefined;\n}\n\n/**\n * Build a parent context that cannot contain a foreign provider's span.\n *\n * The active Neatlogs context already carries the parent span AND any values\n * the caller threaded in upstream (e.g. `trace()`'s prompt-template values), so\n * those values reach the span processor via `onStart(parentContext)`. An\n * explicit `baseContext` (a caller's own value-carrying context) is honored as-is.\n */\nexport function getNeatlogsParentContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * A base context for callers that thread parent linkage themselves\n * (callback/event handlers that keep their own run-id → span map: LangChain,\n * OpenAI-Agents, Claude Agent SDK).\n *\n * This is the ACTIVE Neatlogs context — the private store's\n * context if a Neatlogs `trace()`/`span()` encloses this call, else\n * ROOT_CONTEXT. So a handler's own root/entry span nests under an enclosing\n * Neatlogs trace (preserving its session + end-user id) when one exists, and\n * auto-roots cleanly when one doesn't. A foreign provider's active span can\n * never leak in as an ancestor because the global context is never read.\n */\nexport function getNeatlogsBaseContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * Build an execution context for a Neatlogs span while preserving the active\n * foreign context. The span rides our private context store.\n */\nexport function getNeatlogsExecutionContext(\n span: Span,\n baseContext: Context = ROOT_CONTEXT,\n): Context {\n return otelTrace.setSpan(baseContext, span);\n}\n\n/**\n * Run a callback with a Neatlogs span active under the appropriate policy.\n *\n * The stored context is `setSpan(base, span)` — carrying the span PLUS whatever\n * values `base` holds — so threaded values (prompt templates)\n * propagate to descendant spans through our private store instead of the global\n * OTel context we deliberately never touch.\n */\nexport function withNeatlogsSpan<T>(\n span: Span,\n fn: () => T,\n baseContext?: Context,\n rootSpan?: Span,\n): T {\n const base = baseContext ?? getNeatlogsActiveContext();\n let ctx = otelTrace.setSpan(base, span);\n // The first span activated in a context with no root recorded IS the root of\n // this trace; remember it so descendants (setTraceOutput) can target it.\n if (base.getValue(NEATLOGS_ROOT_SPAN_KEY) === undefined) {\n ctx = ctx.setValue(NEATLOGS_ROOT_SPAN_KEY, rootSpan ?? span);\n }\n return privateContextStorage.run(ctx, fn);\n}\n\n/**\n * @internal Run with a private Neatlogs parent without treating that parent as\n * a locally-recording trace root. This is used for an extracted remote parent:\n * the first local recording span should remain the target for local trace-level\n * output, while still inheriting the remote trace/span IDs.\n */\nexport function withNeatlogsRemoteParent<T>(span: Span, fn: () => T): T {\n return privateContextStorage.run(otelTrace.setSpan(ROOT_CONTEXT, span), fn);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Tracer, TracerProvider } from '@opentelemetry/api';\n\nexport interface ActiveNeatlogsClient {\n readonly workflowName: string;\n readonly tracerProvider: TracerProvider;\n getTracer(scope: string): Tracer;\n getLogger(): any | null;\n}\n\nconst ACTIVE_CLIENT_STORAGE_KEY = Symbol.for(\n 'neatlogs.active_client_async_local_storage',\n);\ntype NeatlogsGlobal = typeof globalThis & {\n [ACTIVE_CLIENT_STORAGE_KEY]?: AsyncLocalStorage<ActiveNeatlogsClient>;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\nconst storage =\n neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] ??\n (neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] =\n new AsyncLocalStorage<ActiveNeatlogsClient>());\n\nexport function getActiveClient(): ActiveNeatlogsClient | undefined {\n return storage.getStore();\n}\n\nexport function runWithClient<T>(\n client: ActiveNeatlogsClient,\n fn: () => T,\n): T {\n return storage.run(client, fn);\n}\n"],"mappings":"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","names":["import_api","import_node_async_hooks","neatlogsGlobal","otelTrace","otelTrace","stringified"]}
1
+ {"version":3,"sources":["../src/ai-sdk.ts","../src/core/provider.ts","../src/core/active-client.ts"],"sourcesContent":["/**\n * Vercel AI SDK wrapper — inline implementation.\n *\n * Wraps `generateText`, `streamText`, `generateObject`, `streamObject` from\n * the `ai` package with OTel parent spans + forced telemetry. AI SDK v7's\n * optional OpenTelemetry adapter is loaded only when its integration runs.\n *\n * Usage:\n * import { wrapAISDK } from 'neatlogs';\n * import * as ai from 'ai';\n * const { streamText, generateText, ToolLoopAgent } = wrapAISDK(ai);\n */\n\nimport {\n SpanStatusCode,\n type AttributeValue,\n type Context,\n type Span,\n type SpanOptions,\n type Tracer,\n} from '@opentelemetry/api';\nimport {\n getNeatlogsTracer,\n getNeatlogsParentContext,\n getRoutingNeatlogsTracer,\n withNeatlogsSpan,\n} from './core/provider.js';\n\nconst TRACER_NAME = 'neatlogs.ai-sdk';\n\n// -- Telemetry config --------------------------------------------------------\n\nexport interface CreateAITelemetryOptions {\n /** Identifier used by the AI SDK to group telemetry for this operation. */\n functionId?: string;\n metadata?: Record<string, AttributeValue>;\n /**\n * Existing telemetry tracer to preserve alongside Neatlogs (for example,\n * Laminar). Native AI SDK spans are mirrored to both isolated pipelines.\n */\n tracer?: Tracer;\n}\n\nexport interface AITelemetryConfig {\n isEnabled: true;\n recordInputs: true;\n recordOutputs: true;\n tracer: Tracer;\n functionId?: string;\n metadata: Record<string, AttributeValue>;\n /** AI SDK v7 telemetry integrations. Ignored by AI SDK v6. */\n integrations: V7TelemetryIntegration[];\n}\n\n/**\n * Small structural surface shared by the AI SDK v6 and v7 telemetry integration types.\n * Keeping this local avoids making either AI SDK version part of Neatlogs' public type identity.\n */\ninterface V7TelemetryIntegration {\n onStart(event: unknown): Promise<void>;\n}\n\nconst NEATLOGS_V7_INTEGRATION = Symbol('neatlogs.ai-sdk.v7-integration');\n\n/**\n * AI SDK v7 moved OpenTelemetry support into `@ai-sdk/otel` and now invokes a\n * telemetry integration instead of accepting a tracer directly. Keep the\n * package optional for AI SDK v6 users and load it only if v7 calls one of the\n * integration hooks.\n */\nclass LazyV7OpenTelemetryIntegration {\n readonly [NEATLOGS_V7_INTEGRATION] = true;\n private delegatePromise?: Promise<Record<string, any>>;\n\n constructor(\n private readonly tracer: Tracer,\n private readonly metadata: Record<string, AttributeValue>,\n ) {}\n\n private getDelegate(): Promise<Record<string, any>> {\n return (this.delegatePromise ??= import('@ai-sdk/otel')\n .then(({ OpenTelemetry }) =>\n new OpenTelemetry({\n tracer: this.tracer,\n enrichSpan: () => this.metadata,\n }) as unknown as Record<string, any>,\n )\n .catch((error: unknown) => {\n const detail = error instanceof Error ? `: ${error.message}` : '';\n throw new Error(\n 'Vercel AI SDK v7 telemetry requires the optional @ai-sdk/otel peer dependency' +\n detail,\n );\n }));\n }\n\n private async notify(method: string, event: unknown): Promise<void> {\n const delegate = await this.getDelegate();\n const fn = delegate[method];\n if (typeof fn === 'function') {\n await Reflect.apply(fn, delegate, [event]);\n }\n }\n\n onStart(event: unknown) { return this.notify('onStart', event); }\n onStepStart(event: unknown) { return this.notify('onStepStart', event); }\n onLanguageModelCallStart(event: unknown) {\n return this.notify('onLanguageModelCallStart', event);\n }\n onLanguageModelCallEnd(event: unknown) {\n return this.notify('onLanguageModelCallEnd', event);\n }\n onToolExecutionStart(event: unknown) {\n return this.notify('onToolExecutionStart', event);\n }\n onToolExecutionEnd(event: unknown) {\n return this.notify('onToolExecutionEnd', event);\n }\n onStepEnd(event: unknown) { return this.notify('onStepEnd', event); }\n onStepFinish(event: unknown) { return this.notify('onStepFinish', event); }\n onObjectStepStart(event: unknown) {\n return this.notify('onObjectStepStart', event);\n }\n onObjectStepEnd(event: unknown) {\n return this.notify('onObjectStepEnd', event);\n }\n onEmbedStart(event: unknown) { return this.notify('onEmbedStart', event); }\n onEmbedEnd(event: unknown) { return this.notify('onEmbedEnd', event); }\n onRerankStart(event: unknown) { return this.notify('onRerankStart', event); }\n onRerankEnd(event: unknown) { return this.notify('onRerankEnd', event); }\n onEnd(event: unknown) { return this.notify('onEnd', event); }\n onAbort(event: unknown) { return this.notify('onAbort', event); }\n onError(event: unknown) { return this.notify('onError', event); }\n\n async executeLanguageModelCall<T>(options: {\n execute: () => PromiseLike<T>;\n } & Record<string, unknown>): Promise<T> {\n const delegate = await this.getDelegate();\n const fn = delegate.executeLanguageModelCall;\n return typeof fn === 'function'\n ? Reflect.apply(fn, delegate, [options])\n : options.execute();\n }\n\n async executeTool<T>(options: {\n execute: () => PromiseLike<T>;\n } & Record<string, unknown>): Promise<T> {\n const delegate = await this.getDelegate();\n const fn = delegate.executeTool;\n return typeof fn === 'function'\n ? Reflect.apply(fn, delegate, [options])\n : options.execute();\n }\n}\n\nexport function createAITelemetry(\n opts: CreateAITelemetryOptions = {},\n): AITelemetryConfig {\n const userMeta = opts.metadata ?? {};\n const neatlogsTracer = getRoutingNeatlogsTracer(TRACER_NAME);\n const callerTracer = opts.tracer;\n const tracer = callerTracer\n ? createMirroredTracer(callerTracer, neatlogsTracer)\n : neatlogsTracer;\n const metadata = callerTracer\n ? { ...userMeta }\n : { ...userMeta, neatlogsWrapped: true };\n return {\n isEnabled: true,\n recordInputs: true,\n recordOutputs: true,\n // Hand the AI SDK an isolation-aware tracer: it calls startActiveSpan()\n // internally, which would otherwise parent its native spans from the foreign\n // global context AND push them onto it (so a co-tenant's next span inherits\n // ours). The facade routes both through the private Neatlogs context.\n tracer,\n ...(opts.functionId !== undefined ? { functionId: opts.functionId } : {}),\n // The marker is an implementation detail used only when Neatlogs owns the\n // telemetry stream. Do not leak it into caller-owned providers.\n metadata,\n integrations: [new LazyV7OpenTelemetryIntegration(tracer, metadata)],\n };\n}\n\n// -- Span attributes ---------------------------------------------------------\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return '';\n }\n}\n\nfunction setInputValue(span: Span, opts: Record<string, unknown>): void {\n // For generateText/streamText — only capture prompt or messages, not full model config\n if (opts && ('prompt' in opts || 'messages' in opts)) {\n const input = opts.messages ?? opts.prompt;\n const stringified = safeStringify(input);\n if (stringified) {\n span.setAttribute('input.value', stringified);\n }\n return;\n }\n const stringified = safeStringify(opts);\n if (stringified) {\n span.setAttribute('input.value', stringified);\n }\n}\n\nfunction setOutputValue(span: Span, result: unknown): void {\n if (result && typeof result === 'object') {\n const r = result as Record<string, unknown>;\n // GenerateTextResult / StreamTextResult — extract meaningful fields\n if ('text' in r && 'finishReason' in r) {\n const text = String(r.text ?? '');\n if (text) {\n span.setAttribute('output.value', text);\n }\n if (r.finishReason) {\n span.setAttribute('neatlogs.llm.finish_reason', String(r.finishReason));\n }\n return;\n }\n // GenerateObjectResult — the structured object is the output, not `text`.\n // Without this the envelope (object+usage+response+…) gets stringified whole.\n if ('object' in r && 'finishReason' in r) {\n if (r.object !== undefined) {\n span.setAttribute('output.value', safeStringify(r.object));\n }\n if (r.finishReason) {\n span.setAttribute('neatlogs.llm.finish_reason', String(r.finishReason));\n }\n return;\n }\n }\n const stringified = safeStringify(result);\n if (stringified) {\n span.setAttribute('output.value', stringified);\n }\n}\n\n// Extract output from a streamText/streamObject `onFinish` event. The event\n// extends StepResult, so `text` (streamText) / `object` (streamObject) sit at\n// the top level alongside `finishReason` — but the event also carries `steps`,\n// `usage`, etc., so we pull only the meaningful fields instead of stringifying\n// the whole envelope.\nfunction setStreamOutputValue(span: Span, event: unknown): void {\n if (!event || typeof event !== 'object') return;\n const e = event as Record<string, unknown>;\n if (typeof e.text === 'string' && e.text) {\n span.setAttribute('output.value', e.text);\n } else if ('object' in e && e.object !== undefined) {\n const stringified = safeStringify(e.object);\n if (stringified) span.setAttribute('output.value', stringified);\n }\n if (e.finishReason) {\n span.setAttribute('neatlogs.llm.finish_reason', String(e.finishReason));\n }\n}\n\n// -- Wrapping ----------------------------------------------------------------\n\ntype WrappedFunctionName =\n | 'generateText'\n | 'streamText'\n | 'generateObject'\n | 'streamObject'\n | 'embed'\n | 'embedMany'\n | 'rerank';\n\nconst WRAPPED_FUNCTIONS: readonly WrappedFunctionName[] = [\n 'generateText',\n 'streamText',\n 'generateObject',\n 'streamObject',\n 'embed',\n 'embedMany',\n 'rerank',\n] as const;\n\ntype WrappedAgentConstructorName = 'ToolLoopAgent' | 'Experimental_Agent';\n\nconst WRAPPED_AGENT_CONSTRUCTORS: readonly WrappedAgentConstructorName[] = [\n 'ToolLoopAgent',\n 'Experimental_Agent',\n] as const;\n\ntype AgentConstructor = new (...args: any[]) => unknown;\n\nconst wrappedExports = new WeakSet<Function>();\nconst wrapperByOriginal = new WeakMap<Function, Function>();\n\n/**\n * Wrap the `ai` module namespace so that every supported generation, embedding,\n * and reranking call:\n *\n * 1. Opens a parent OTel span on the active TracerProvider.\n * 2. Forces the version-appropriate telemetry option, merging user metadata.\n * 3. Records input/output on the parent span and propagates errors.\n *\n * `ToolLoopAgent` (and AI SDK v6's `Experimental_Agent` alias) is wrapped at\n * construction time so its internal model and tool calls receive the same native\n * telemetry configuration. Other exports pass through unchanged.\n */\nexport function wrapAISDK<T extends Record<string, unknown>>(aiModule: T): T {\n const wrapped: Record<string, unknown> = { ...aiModule };\n // Vitest and some bundlers expose module namespaces through proxies which\n // throw when a missing export is read. Check membership before accessing the\n // v7-only registerTelemetry export so v6 and partial module mocks stay safe.\n const hasRegisterTelemetry =\n 'registerTelemetry' in aiModule &&\n typeof Reflect.get(aiModule, 'registerTelemetry') === 'function';\n const telemetryKey: TelemetryKey =\n hasRegisterTelemetry ? 'telemetry' : 'experimental_telemetry';\n\n for (const name of WRAPPED_FUNCTIONS) {\n const original = aiModule[name];\n if (typeof original !== 'function') continue;\n\n const existing = getExistingWrapper(original);\n if (existing) {\n wrapped[name] = existing;\n continue;\n }\n\n if (name === 'streamText' || name === 'streamObject') {\n wrapped[name] = cacheWrapper(\n original,\n createStreamWrapper(name, original as (opts: any) => unknown, telemetryKey),\n );\n } else {\n wrapped[name] = cacheWrapper(\n original,\n createAsyncWrapper(\n name,\n original as (opts: any) => Promise<unknown>,\n telemetryKey,\n ),\n );\n }\n }\n\n for (const name of WRAPPED_AGENT_CONSTRUCTORS) {\n const original = aiModule[name];\n if (typeof original !== 'function') continue;\n\n const existing = getExistingWrapper(original);\n wrapped[name] =\n existing ??\n cacheWrapper(\n original,\n createAgentConstructorWrapper(original as AgentConstructor, telemetryKey),\n );\n }\n\n return wrapped as T;\n}\n\nfunction getExistingWrapper(original: Function): Function | undefined {\n if (wrappedExports.has(original)) return original;\n return wrapperByOriginal.get(original);\n}\n\nfunction cacheWrapper(original: Function, wrapped: Function): Function {\n wrapperByOriginal.set(original, wrapped);\n wrappedExports.add(wrapped);\n return wrapped;\n}\n\nfunction createAgentConstructorWrapper(\n original: AgentConstructor,\n telemetryKey: TelemetryKey,\n): AgentConstructor {\n return new Proxy(original, {\n construct(target, args, newTarget) {\n if (\n args.length === 0 ||\n typeof args[0] !== 'object' ||\n args[0] === null\n ) {\n return Reflect.construct(target, args, newTarget);\n }\n\n const settings = mergeAgentSettings(args[0], telemetryKey);\n return Reflect.construct(target, [settings, ...args.slice(1)], newTarget);\n },\n });\n}\n\nfunction mergeAgentSettings(settings: any, telemetryKey: TelemetryKey): any {\n const merged = mergeTelemetry(settings, telemetryKey);\n const userPrepareCall = settings.prepareCall;\n if (typeof userPrepareCall !== 'function') return merged;\n\n return {\n ...merged,\n prepareCall: async function wrappedPrepareCall(\n this: unknown,\n ...args: any[]\n ) {\n const prepared = await Reflect.apply(userPrepareCall, this, args);\n return prepared == null\n ? prepared\n : mergeTelemetry(\n prepared,\n telemetryKey,\n settings.telemetry ?? settings.experimental_telemetry,\n );\n },\n };\n}\n\nfunction rootSpanKind(name: WrappedFunctionName): string {\n if (name === 'embed' || name === 'embedMany' || name === 'rerank')\n return 'CHAIN';\n return 'WORKFLOW';\n}\n\nfunction getParentContext() {\n // Our parent comes solely from the private span store; a\n // foreign provider's active span must never become our ancestor.\n return getNeatlogsParentContext();\n}\n\nfunction createAsyncWrapper(\n name: WrappedFunctionName,\n original: (opts: any) => Promise<unknown>,\n telemetryKey: TelemetryKey,\n): (opts: any) => Promise<unknown> {\n return async function wrappedAsyncFn(opts: any): Promise<unknown> {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n // startSpan (NOT startActiveSpan) + withNeatlogsSpan: startActiveSpan would\n // push our span onto the GLOBAL OTel context, so a foreign tracer's\n // startSpan() inside generateText() would read it as parent and inherit our\n // trace id. withNeatlogsSpan carries the parent in the private store in\n // the private context, leaving the global context untouched.\n const parentContext = getParentContext();\n const span = tracer.startSpan(\n `ai.${name}`,\n { attributes: { 'openinference.span.kind': rootSpanKind(name) } },\n parentContext,\n );\n return withNeatlogsSpan(\n span,\n async () => {\n try {\n const isEmbedOrRerank =\n name === 'embed' || name === 'embedMany' || name === 'rerank';\n if (!isEmbedOrRerank) {\n setInputValue(span, opts);\n }\n if (name === 'rerank' && opts?.query) {\n span.setAttribute('ai.rerank.query', String(opts.query));\n }\n const merged = mergeTelemetry(opts, telemetryKey);\n const result = await original(merged);\n if (!isEmbedOrRerank) {\n setOutputValue(span, result);\n }\n return result;\n } catch (err) {\n recordSpanError(span, err);\n throw err;\n } finally {\n span.end();\n }\n },\n parentContext,\n );\n };\n}\n\n// streamText/streamObject return synchronously while the model keeps producing\n// tokens for seconds afterwards. Ending the span in a `finally` (as a plain sync\n// wrapper would) closes it in ~2ms with no output — the output only exists once\n// the stream finishes. Instead we keep the span open and end it from the AI SDK's\n// `onFinish` callback, where the final text/object is available. Any user-provided\n// `onFinish` is preserved and invoked first.\nfunction createStreamWrapper(\n name: WrappedFunctionName,\n original: (opts: any) => unknown,\n telemetryKey: TelemetryKey,\n): (opts: any) => unknown {\n return function wrappedStreamFn(opts: any): unknown {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n // startSpan + withNeatlogsSpan (see createAsyncWrapper) so streamText's\n // internals never see our span on the global OTel context. The span stays\n // open past the run scope and is ended from onFinish/onError.\n const parentContext = getParentContext();\n const span = tracer.startSpan(\n `ai.${name}`,\n { attributes: { 'openinference.span.kind': rootSpanKind(name) } },\n parentContext,\n );\n return withNeatlogsSpan(\n span,\n () => {\n let spanEnded = false;\n const endOnce = () => {\n if (spanEnded) return;\n spanEnded = true;\n span.end();\n };\n try {\n setInputValue(span, opts);\n const merged = mergeTelemetry(opts, telemetryKey);\n const userOnFinish = opts?.onFinish;\n const userOnError = opts?.onError;\n const wrappedOpts = {\n ...merged,\n onFinish: async (event: any) => {\n try {\n setStreamOutputValue(span, event);\n } finally {\n endOnce();\n }\n if (typeof userOnFinish === 'function') {\n return userOnFinish(event);\n }\n },\n onError: (event: any) => {\n recordSpanError(span, (event && event.error) ?? event);\n endOnce();\n if (typeof userOnError === 'function') {\n return userOnError(event);\n }\n },\n };\n return original(wrappedOpts);\n } catch (err) {\n // Synchronous throw (e.g. bad arguments) — the stream never started.\n recordSpanError(span, err);\n endOnce();\n throw err;\n }\n },\n parentContext,\n );\n };\n}\n\nfunction createMirroredSpan(primary: Span, secondary: Span): Span {\n const mirrored: Span = {\n spanContext() {\n // The caller-owned tracer remains the process-global context owner. Its\n // context is therefore the one external instrumentation must observe.\n return primary.spanContext();\n },\n setAttribute(key, value) {\n primary.setAttribute(key, value);\n secondary.setAttribute(key, value);\n return mirrored;\n },\n setAttributes(attributes) {\n primary.setAttributes(attributes);\n secondary.setAttributes(attributes);\n return mirrored;\n },\n addEvent(name, attributesOrStartTime, startTime) {\n primary.addEvent(name, attributesOrStartTime, startTime);\n secondary.addEvent(name, attributesOrStartTime, startTime);\n return mirrored;\n },\n addLink(link) {\n primary.addLink(link);\n secondary.addLink(link);\n return mirrored;\n },\n addLinks(links) {\n primary.addLinks(links);\n secondary.addLinks(links);\n return mirrored;\n },\n setStatus(status) {\n primary.setStatus(status);\n secondary.setStatus(status);\n return mirrored;\n },\n updateName(name) {\n primary.updateName(name);\n secondary.updateName(name);\n return mirrored;\n },\n end(endTime) {\n primary.end(endTime);\n secondary.end(endTime);\n },\n isRecording() {\n return primary.isRecording() || secondary.isRecording();\n },\n recordException(exception, time) {\n primary.recordException(exception, time);\n secondary.recordException(exception, time);\n },\n };\n return mirrored;\n}\n\n/**\n * Mirror one AI SDK telemetry stream to two isolated tracer pipelines.\n *\n * The caller-owned tracer is deliberately outermost so its normal global OTel\n * activation and parentage stay unchanged. The Neatlogs routing tracer keeps\n * its span active only in Neatlogs' private AsyncLocalStorage context.\n */\nfunction createMirroredTracer(primary: Tracer, secondary: Tracer): Tracer {\n return {\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n const primarySpan = primary.startSpan(name, options, context);\n const secondarySpan = secondary.startSpan(name, options);\n return createMirroredSpan(primarySpan, secondarySpan);\n },\n startActiveSpan: (<F extends (span: Span) => unknown>(\n name: string,\n arg2?: SpanOptions | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> => {\n let options: SpanOptions | undefined;\n let context: Context | undefined;\n let fn: F;\n\n if (typeof arg2 === 'function') {\n fn = arg2;\n } else if (typeof arg3 === 'function') {\n options = arg2;\n fn = arg3;\n } else {\n options = arg2;\n context = arg3 as Context;\n fn = arg4!;\n }\n\n const runSecondary = (primarySpan: Span): ReturnType<F> => {\n const onSecondarySpan = (secondarySpan: Span) =>\n fn(createMirroredSpan(primarySpan, secondarySpan)) as ReturnType<F>;\n return options === undefined\n ? secondary.startActiveSpan(name, onSecondarySpan)\n : secondary.startActiveSpan(name, options, onSecondarySpan);\n };\n\n if (context !== undefined) {\n return primary.startActiveSpan(\n name,\n options ?? {},\n context,\n runSecondary,\n ) as ReturnType<F>;\n }\n return options === undefined\n ? (primary.startActiveSpan(name, runSecondary) as ReturnType<F>)\n : (primary.startActiveSpan(name, options, runSecondary) as ReturnType<F>);\n }) as Tracer['startActiveSpan'],\n };\n}\n\ntype TelemetryKey = 'telemetry' | 'experimental_telemetry';\n\nfunction isNeatlogsV7Integration(\n integration: unknown,\n): integration is LazyV7OpenTelemetryIntegration {\n return (\n typeof integration === 'object' &&\n integration !== null &&\n NEATLOGS_V7_INTEGRATION in integration\n );\n}\n\nfunction mergeTelemetry(\n opts: any,\n telemetryKey: TelemetryKey,\n fallbackTelemetry?: any,\n): any {\n const legacyTelemetry = opts?.experimental_telemetry ?? {};\n const v7Telemetry = opts?.telemetry ?? {};\n const preferredTelemetry =\n telemetryKey === 'telemetry'\n ? { ...legacyTelemetry, ...v7Telemetry }\n : { ...v7Telemetry, ...legacyTelemetry };\n const requestedTelemetry = {\n ...fallbackTelemetry,\n ...preferredTelemetry,\n metadata: {\n ...fallbackTelemetry?.metadata,\n ...legacyTelemetry.metadata,\n ...v7Telemetry.metadata,\n },\n };\n const existingNeatlogsIntegration = Array.isArray(\n requestedTelemetry.integrations,\n )\n ? requestedTelemetry.integrations.find(isNeatlogsV7Integration)\n : undefined;\n const baseTelemetry: AITelemetryConfig = existingNeatlogsIntegration\n ? {\n isEnabled: true,\n recordInputs: true,\n recordOutputs: true,\n tracer: requestedTelemetry.tracer as Tracer,\n ...(requestedTelemetry.functionId !== undefined\n ? { functionId: requestedTelemetry.functionId }\n : {}),\n metadata: requestedTelemetry.metadata,\n integrations: [existingNeatlogsIntegration],\n }\n : createAITelemetry({\n functionId: requestedTelemetry.functionId,\n metadata: requestedTelemetry.metadata,\n tracer: requestedTelemetry.tracer as Tracer | undefined,\n });\n const callerTracer = requestedTelemetry.tracer as Tracer | undefined;\n const hasCallerTracer = callerTracer !== undefined;\n const requestedIntegrations = Array.isArray(requestedTelemetry.integrations)\n ? requestedTelemetry.integrations.filter(\n (integration: unknown) => !isNeatlogsV7Integration(integration),\n )\n : [];\n const { telemetry: _telemetry, experimental_telemetry: _legacy, ...rest } =\n opts ?? {};\n\n return {\n ...rest,\n [telemetryKey]: {\n ...baseTelemetry,\n ...requestedTelemetry,\n isEnabled: true,\n recordInputs: requestedTelemetry.recordInputs ?? true,\n recordOutputs: requestedTelemetry.recordOutputs ?? true,\n tracer: baseTelemetry.tracer,\n // Do not add Neatlogs-only marker metadata to a caller-owned telemetry\n // pipeline such as Laminar. Both providers receive the same AI SDK span\n // data, while their providers, parent contexts, and exporters stay separate.\n metadata: hasCallerTracer\n ? requestedTelemetry.metadata\n : baseTelemetry.metadata,\n integrations: [...baseTelemetry.integrations, ...requestedIntegrations],\n },\n };\n}\n\nfunction recordSpanError(span: Span, err: unknown): void {\n if (err instanceof Error) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });\n span.recordException(err);\n } else {\n span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });\n }\n}\n","/**\n * Neatlogs-owned tracing state.\n *\n * Spans are created by the private Neatlogs provider and their parent is carried\n * in a private context key. The process-global OpenTelemetry span is\n * deliberately left untouched so other observability SDKs cannot export or\n * become parents of Neatlogs spans.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n ROOT_CONTEXT,\n INVALID_SPAN_CONTEXT,\n createContextKey,\n trace as otelTrace,\n type Context,\n type Span,\n type SpanOptions,\n type Tracer,\n type TracerProvider,\n} from '@opentelemetry/api';\nimport { getActiveClient } from './active-client.js';\n\n// Carries the trace-ROOT span down the private context so descendants can target\n// it (e.g. setTraceOutput). getActiveNeatlogsSpan() returns the innermost span,\n// which is not the root once nested; this key preserves the root reference.\nconst NEATLOGS_ROOT_SPAN_KEY = createContextKey('neatlogs.root_span');\n\n// Entry points are bundled independently (`neatlogs`, `neatlogs/openai`,\n// `neatlogs/ai`, `neatlogs/mastra`, … each in both CJS and ESM), so every piece\n// of shared tracing state — the private span store AND the resolved provider /\n// provider — must live on `globalThis` behind a `Symbol.for` key.\n// Otherwise `init()` (run from the `neatlogs` bundle) sets `_provider` in ITS\n// module copy while a wrapper imported from `neatlogs/openai` reads a different,\n// still-null copy and silently falls back to the foreign global provider.\nconst PRIVATE_SPAN_STORAGE_KEY = Symbol.for(\n 'neatlogs.private_span_async_local_storage',\n);\nconst PRIVATE_PROVIDER_STATE_KEY = Symbol.for(\n 'neatlogs.private_provider_state',\n);\ninterface PrivateProviderState {\n provider: TracerProvider | null;\n}\ntype NeatlogsGlobal = typeof globalThis & {\n [PRIVATE_SPAN_STORAGE_KEY]?: AsyncLocalStorage<Context>;\n [PRIVATE_PROVIDER_STATE_KEY]?: PrivateProviderState;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\n// Stores the full Neatlogs Context (parent span PLUS any threaded values such as\n// trace()'s prompt-template keys), not just the span. We never\n// activate the OTel global context, so this private store is the ONLY channel\n// through which those values propagate down to descendant spans.\nconst privateContextStorage =\n neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] ??\n (neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] = new AsyncLocalStorage<Context>());\nconst providerState: PrivateProviderState =\n neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] ??\n (neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] = {\n provider: null,\n });\n// Wrappers may be constructed or accidentally invoked before init(). They must\n// never fall back to a foreign process-global provider, so pre-init calls use a\n// local no-op tracer and safely emit no exported spans.\nconst preInitTracer: Tracer = {\n startSpan(): Span {\n return otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n _name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n const fn =\n typeof arg2 === 'function'\n ? arg2\n : typeof arg3 === 'function'\n ? arg3\n : arg4;\n return fn!(otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT)) as ReturnType<F>;\n },\n};\n\n/** @internal Configure the provider used by Neatlogs-created spans. */\nexport function _setNeatlogsProvider(provider: TracerProvider | null): void {\n providerState.provider = provider;\n}\n\n/** Resolve a tracer from the private provider when one is configured. */\nexport function getNeatlogsTracer(name: string): Tracer {\n const client = getActiveClient();\n if (client) return client.getTracer(name);\n return providerState.provider?.getTracer(name) ?? preInitTracer;\n}\n\n/** A reusable tracer facade that resolves the active Client on every call. */\nexport function getRoutingNeatlogsTracer(name: string): Tracer {\n return {\n startSpan(spanName: string, options?: SpanOptions, context?: Context): Span {\n return isolateTracer(getNeatlogsTracer(name)).startSpan(\n spanName,\n options,\n context,\n );\n },\n startActiveSpan: ((...args: any[]) =>\n (isolateTracer(getNeatlogsTracer(name)).startActiveSpan as (...inner: any[]) => any)(\n ...args,\n )) as Tracer['startActiveSpan'],\n };\n}\n\n/**\n * @internal The private Neatlogs provider, or null before\n * init(). Used by integrations that must repoint a self-instrumenting library's\n * captured provider onto ours.\n */\nexport function getNeatlogsProvider(): TracerProvider | null {\n const client = getActiveClient();\n if (client) return client.tracerProvider;\n return providerState.provider;\n}\n\n/** Run a Client callback without inheriting another pipeline's private span. */\nexport function runWithFreshNeatlogsContext<T>(fn: () => T): T {\n return privateContextStorage.run(ROOT_CONTEXT, fn);\n}\n\n/**\n * Wrap a tracer so that spans it creates parent from — and, for\n * `startActiveSpan`, activate on — the PRIVATE Neatlogs context instead of the\n * global one.\n *\n * We hand this to libraries that create their own spans off a tracer we give\n * them (the Vercel AI SDK's `experimental_telemetry.tracer`, which calls\n * `tracer.startActiveSpan()` internally). Without the facade the AI SDK's native\n * spans would parent from `context.active()` — the foreign co-tenant's context —\n * and `startActiveSpan` would push them onto the GLOBAL context, so a foreign\n * tracer's next span reads our native span as its parent. Both directions leak.\n *\n */\nexport function isolateTracer(tracer: Tracer): Tracer {\n const facade: Tracer = {\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n const parent = context ?? getNeatlogsActiveContext();\n return tracer.startSpan(name, options, parent);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n // Normalize the 2/3/4-arg overloads of startActiveSpan.\n let options: SpanOptions | undefined;\n let context: Context | undefined;\n let fn: F;\n if (typeof arg2 === 'function') {\n fn = arg2 as F;\n } else if (typeof arg3 === 'function') {\n options = arg2 as SpanOptions;\n fn = arg3 as F;\n } else {\n options = arg2 as SpanOptions;\n context = arg3 as Context;\n fn = arg4 as F;\n }\n const parent = context ?? getNeatlogsActiveContext();\n const span = tracer.startSpan(name, options, parent);\n return withNeatlogsSpan(span, () => fn(span), parent) as ReturnType<F>;\n },\n };\n return facade;\n}\n\n/**\n * The base context to build new Neatlogs spans and values on. NEVER contains a\n * foreign provider's span: it reads our private store, or ROOT_CONTEXT when\n * nothing is active.\n */\nexport function getNeatlogsActiveContext(): Context {\n return privateContextStorage.getStore() ?? ROOT_CONTEXT;\n}\n\n/** Return only the active Neatlogs span (never a foreign provider's span). */\nexport function getActiveNeatlogsSpan(): Span | undefined {\n return otelTrace.getSpan(getNeatlogsActiveContext());\n}\n\n/**\n * Return the trace-ROOT Neatlogs span, or undefined when no trace is active.\n *\n * Unlike {@link getActiveNeatlogsSpan} (innermost), this is the outermost span\n * of the current trace — the one the backend derives trace-level output from\n * (`parent_span_id=''`). It is stashed on the private context the first time a\n * span becomes active, so nested calls still resolve to the root.\n */\nexport function getNeatlogsRootSpan(): Span | undefined {\n return getNeatlogsActiveContext().getValue(NEATLOGS_ROOT_SPAN_KEY) as\n | Span\n | undefined;\n}\n\n/**\n * Build a parent context that cannot contain a foreign provider's span.\n *\n * The active Neatlogs context already carries the parent span AND any values\n * the caller threaded in upstream (e.g. `trace()`'s prompt-template values), so\n * those values reach the span processor via `onStart(parentContext)`. An\n * explicit `baseContext` (a caller's own value-carrying context) is honored as-is.\n */\nexport function getNeatlogsParentContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * A base context for callers that thread parent linkage themselves\n * (callback/event handlers that keep their own run-id → span map: LangChain,\n * OpenAI-Agents, Claude Agent SDK).\n *\n * This is the ACTIVE Neatlogs context — the private store's\n * context if a Neatlogs `trace()`/`span()` encloses this call, else\n * ROOT_CONTEXT. So a handler's own root/entry span nests under an enclosing\n * Neatlogs trace (preserving its session + end-user id) when one exists, and\n * auto-roots cleanly when one doesn't. A foreign provider's active span can\n * never leak in as an ancestor because the global context is never read.\n */\nexport function getNeatlogsBaseContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * Build an execution context for a Neatlogs span while preserving the active\n * foreign context. The span rides our private context store.\n */\nexport function getNeatlogsExecutionContext(\n span: Span,\n baseContext: Context = ROOT_CONTEXT,\n): Context {\n return otelTrace.setSpan(baseContext, span);\n}\n\n/**\n * Run a callback with a Neatlogs span active under the appropriate policy.\n *\n * The stored context is `setSpan(base, span)` — carrying the span PLUS whatever\n * values `base` holds — so threaded values (prompt templates)\n * propagate to descendant spans through our private store instead of the global\n * OTel context we deliberately never touch.\n */\nexport function withNeatlogsSpan<T>(\n span: Span,\n fn: () => T,\n baseContext?: Context,\n rootSpan?: Span,\n): T {\n const base = baseContext ?? getNeatlogsActiveContext();\n let ctx = otelTrace.setSpan(base, span);\n // The first span activated in a context with no root recorded IS the root of\n // this trace; remember it so descendants (setTraceOutput) can target it.\n if (base.getValue(NEATLOGS_ROOT_SPAN_KEY) === undefined) {\n ctx = ctx.setValue(NEATLOGS_ROOT_SPAN_KEY, rootSpan ?? span);\n }\n return privateContextStorage.run(ctx, fn);\n}\n\n/**\n * @internal Run with a private Neatlogs parent without treating that parent as\n * a locally-recording trace root. This is used for an extracted remote parent:\n * the first local recording span should remain the target for local trace-level\n * output, while still inheriting the remote trace/span IDs.\n */\nexport function withNeatlogsRemoteParent<T>(span: Span, fn: () => T): T {\n return privateContextStorage.run(otelTrace.setSpan(ROOT_CONTEXT, span), fn);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Tracer, TracerProvider } from '@opentelemetry/api';\n\nexport interface ActiveNeatlogsClient {\n readonly workflowName: string;\n readonly tracerProvider: TracerProvider;\n getTracer(scope: string): Tracer;\n getLogger(): any | null;\n}\n\nconst ACTIVE_CLIENT_STORAGE_KEY = Symbol.for(\n 'neatlogs.active_client_async_local_storage',\n);\ntype NeatlogsGlobal = typeof globalThis & {\n [ACTIVE_CLIENT_STORAGE_KEY]?: AsyncLocalStorage<ActiveNeatlogsClient>;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\nconst storage =\n neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] ??\n (neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] =\n new AsyncLocalStorage<ActiveNeatlogsClient>());\n\nexport function getActiveClient(): ActiveNeatlogsClient | undefined {\n return storage.getStore();\n}\n\nexport function runWithClient<T>(\n client: ActiveNeatlogsClient,\n fn: () => T,\n): T {\n return storage.run(client, fn);\n}\n"],"mappings":"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","names":["import_api","import_node_async_hooks","neatlogsGlobal","otelTrace","otelTrace","stringified"]}