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 +12 -9
- package/dist/ai-sdk.cjs +162 -24
- package/dist/ai-sdk.cjs.map +1 -1
- package/dist/ai-sdk.d.ts +13 -4
- package/dist/ai-sdk.mjs +152 -24
- package/dist/ai-sdk.mjs.map +1 -1
- package/dist/cli.cjs +12 -8
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +12 -8
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +167 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +167 -35
- package/dist/index.mjs.map +1 -1
- package/dist/opencode-plugin.cjs +1 -1
- package/dist/opencode-plugin.cjs.map +1 -1
- package/dist/opencode-plugin.mjs +1 -1
- package/dist/opencode-plugin.mjs.map +1 -1
- package/package.json +13 -3
package/dist/ai-sdk.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { Tracer, AttributeValue } from '@opentelemetry/api';
|
|
|
4
4
|
* Vercel AI SDK wrapper — inline implementation.
|
|
5
5
|
*
|
|
6
6
|
* Wraps `generateText`, `streamText`, `generateObject`, `streamObject` from
|
|
7
|
-
* the `ai` package with OTel parent spans + forced telemetry.
|
|
8
|
-
*
|
|
7
|
+
* the `ai` package with OTel parent spans + forced telemetry. AI SDK v7's
|
|
8
|
+
* optional OpenTelemetry adapter is loaded only when its integration runs.
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* import { wrapAISDK } from 'neatlogs';
|
|
@@ -30,6 +30,15 @@ interface AITelemetryConfig {
|
|
|
30
30
|
tracer: Tracer;
|
|
31
31
|
functionId?: string;
|
|
32
32
|
metadata: Record<string, AttributeValue>;
|
|
33
|
+
/** AI SDK v7 telemetry integrations. Ignored by AI SDK v6. */
|
|
34
|
+
integrations: V7TelemetryIntegration[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Small structural surface shared by the AI SDK v6 and v7 telemetry integration types.
|
|
38
|
+
* Keeping this local avoids making either AI SDK version part of Neatlogs' public type identity.
|
|
39
|
+
*/
|
|
40
|
+
interface V7TelemetryIntegration {
|
|
41
|
+
onStart(event: unknown): Promise<void>;
|
|
33
42
|
}
|
|
34
43
|
declare function createAITelemetry(opts?: CreateAITelemetryOptions): AITelemetryConfig;
|
|
35
44
|
/**
|
|
@@ -37,10 +46,10 @@ declare function createAITelemetry(opts?: CreateAITelemetryOptions): AITelemetry
|
|
|
37
46
|
* and reranking call:
|
|
38
47
|
*
|
|
39
48
|
* 1. Opens a parent OTel span on the active TracerProvider.
|
|
40
|
-
* 2. Forces
|
|
49
|
+
* 2. Forces the version-appropriate telemetry option, merging user metadata.
|
|
41
50
|
* 3. Records input/output on the parent span and propagates errors.
|
|
42
51
|
*
|
|
43
|
-
* AI SDK v6's `
|
|
52
|
+
* `ToolLoopAgent` (and AI SDK v6's `Experimental_Agent` alias) is wrapped at
|
|
44
53
|
* construction time so its internal model and tool calls receive the same native
|
|
45
54
|
* telemetry configuration. Other exports pass through unchanged.
|
|
46
55
|
*/
|
package/dist/ai-sdk.mjs
CHANGED
|
@@ -108,10 +108,104 @@ function withNeatlogsSpan(span, fn, baseContext, rootSpan) {
|
|
|
108
108
|
|
|
109
109
|
// src/ai-sdk.ts
|
|
110
110
|
var TRACER_NAME = "neatlogs.ai-sdk";
|
|
111
|
+
var NEATLOGS_V7_INTEGRATION = /* @__PURE__ */ Symbol("neatlogs.ai-sdk.v7-integration");
|
|
112
|
+
var LazyV7OpenTelemetryIntegration = class {
|
|
113
|
+
constructor(tracer, metadata) {
|
|
114
|
+
this.tracer = tracer;
|
|
115
|
+
this.metadata = metadata;
|
|
116
|
+
}
|
|
117
|
+
tracer;
|
|
118
|
+
metadata;
|
|
119
|
+
[NEATLOGS_V7_INTEGRATION] = true;
|
|
120
|
+
delegatePromise;
|
|
121
|
+
getDelegate() {
|
|
122
|
+
return this.delegatePromise ??= import("@ai-sdk/otel").then(
|
|
123
|
+
({ OpenTelemetry }) => new OpenTelemetry({
|
|
124
|
+
tracer: this.tracer,
|
|
125
|
+
enrichSpan: () => this.metadata
|
|
126
|
+
})
|
|
127
|
+
).catch((error) => {
|
|
128
|
+
const detail = error instanceof Error ? `: ${error.message}` : "";
|
|
129
|
+
throw new Error(
|
|
130
|
+
"Vercel AI SDK v7 telemetry requires the optional @ai-sdk/otel peer dependency" + detail
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async notify(method, event) {
|
|
135
|
+
const delegate = await this.getDelegate();
|
|
136
|
+
const fn = delegate[method];
|
|
137
|
+
if (typeof fn === "function") {
|
|
138
|
+
await Reflect.apply(fn, delegate, [event]);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
onStart(event) {
|
|
142
|
+
return this.notify("onStart", event);
|
|
143
|
+
}
|
|
144
|
+
onStepStart(event) {
|
|
145
|
+
return this.notify("onStepStart", event);
|
|
146
|
+
}
|
|
147
|
+
onLanguageModelCallStart(event) {
|
|
148
|
+
return this.notify("onLanguageModelCallStart", event);
|
|
149
|
+
}
|
|
150
|
+
onLanguageModelCallEnd(event) {
|
|
151
|
+
return this.notify("onLanguageModelCallEnd", event);
|
|
152
|
+
}
|
|
153
|
+
onToolExecutionStart(event) {
|
|
154
|
+
return this.notify("onToolExecutionStart", event);
|
|
155
|
+
}
|
|
156
|
+
onToolExecutionEnd(event) {
|
|
157
|
+
return this.notify("onToolExecutionEnd", event);
|
|
158
|
+
}
|
|
159
|
+
onStepEnd(event) {
|
|
160
|
+
return this.notify("onStepEnd", event);
|
|
161
|
+
}
|
|
162
|
+
onStepFinish(event) {
|
|
163
|
+
return this.notify("onStepFinish", event);
|
|
164
|
+
}
|
|
165
|
+
onObjectStepStart(event) {
|
|
166
|
+
return this.notify("onObjectStepStart", event);
|
|
167
|
+
}
|
|
168
|
+
onObjectStepEnd(event) {
|
|
169
|
+
return this.notify("onObjectStepEnd", event);
|
|
170
|
+
}
|
|
171
|
+
onEmbedStart(event) {
|
|
172
|
+
return this.notify("onEmbedStart", event);
|
|
173
|
+
}
|
|
174
|
+
onEmbedEnd(event) {
|
|
175
|
+
return this.notify("onEmbedEnd", event);
|
|
176
|
+
}
|
|
177
|
+
onRerankStart(event) {
|
|
178
|
+
return this.notify("onRerankStart", event);
|
|
179
|
+
}
|
|
180
|
+
onRerankEnd(event) {
|
|
181
|
+
return this.notify("onRerankEnd", event);
|
|
182
|
+
}
|
|
183
|
+
onEnd(event) {
|
|
184
|
+
return this.notify("onEnd", event);
|
|
185
|
+
}
|
|
186
|
+
onAbort(event) {
|
|
187
|
+
return this.notify("onAbort", event);
|
|
188
|
+
}
|
|
189
|
+
onError(event) {
|
|
190
|
+
return this.notify("onError", event);
|
|
191
|
+
}
|
|
192
|
+
async executeLanguageModelCall(options) {
|
|
193
|
+
const delegate = await this.getDelegate();
|
|
194
|
+
const fn = delegate.executeLanguageModelCall;
|
|
195
|
+
return typeof fn === "function" ? Reflect.apply(fn, delegate, [options]) : options.execute();
|
|
196
|
+
}
|
|
197
|
+
async executeTool(options) {
|
|
198
|
+
const delegate = await this.getDelegate();
|
|
199
|
+
const fn = delegate.executeTool;
|
|
200
|
+
return typeof fn === "function" ? Reflect.apply(fn, delegate, [options]) : options.execute();
|
|
201
|
+
}
|
|
202
|
+
};
|
|
111
203
|
function createAITelemetry(opts = {}) {
|
|
112
204
|
const userMeta = opts.metadata ?? {};
|
|
113
205
|
const neatlogsTracer = getRoutingNeatlogsTracer(TRACER_NAME);
|
|
114
206
|
const callerTracer = opts.tracer;
|
|
207
|
+
const tracer = callerTracer ? createMirroredTracer(callerTracer, neatlogsTracer) : neatlogsTracer;
|
|
208
|
+
const metadata = callerTracer ? { ...userMeta } : { ...userMeta, neatlogsWrapped: true };
|
|
115
209
|
return {
|
|
116
210
|
isEnabled: true,
|
|
117
211
|
recordInputs: true,
|
|
@@ -120,11 +214,12 @@ function createAITelemetry(opts = {}) {
|
|
|
120
214
|
// internally, which would otherwise parent its native spans from the foreign
|
|
121
215
|
// global context AND push them onto it (so a co-tenant's next span inherits
|
|
122
216
|
// ours). The facade routes both through the private Neatlogs context.
|
|
123
|
-
tracer
|
|
217
|
+
tracer,
|
|
124
218
|
...opts.functionId !== void 0 ? { functionId: opts.functionId } : {},
|
|
125
219
|
// The marker is an implementation detail used only when Neatlogs owns the
|
|
126
220
|
// telemetry stream. Do not leak it into caller-owned providers.
|
|
127
|
-
metadata
|
|
221
|
+
metadata,
|
|
222
|
+
integrations: [new LazyV7OpenTelemetryIntegration(tracer, metadata)]
|
|
128
223
|
};
|
|
129
224
|
}
|
|
130
225
|
function safeStringify(value) {
|
|
@@ -157,7 +252,7 @@ function setOutputValue(span, result) {
|
|
|
157
252
|
span.setAttribute("output.value", text);
|
|
158
253
|
}
|
|
159
254
|
if (r.finishReason) {
|
|
160
|
-
span.setAttribute("
|
|
255
|
+
span.setAttribute("neatlogs.llm.finish_reason", String(r.finishReason));
|
|
161
256
|
}
|
|
162
257
|
return;
|
|
163
258
|
}
|
|
@@ -166,7 +261,7 @@ function setOutputValue(span, result) {
|
|
|
166
261
|
span.setAttribute("output.value", safeStringify(r.object));
|
|
167
262
|
}
|
|
168
263
|
if (r.finishReason) {
|
|
169
|
-
span.setAttribute("
|
|
264
|
+
span.setAttribute("neatlogs.llm.finish_reason", String(r.finishReason));
|
|
170
265
|
}
|
|
171
266
|
return;
|
|
172
267
|
}
|
|
@@ -186,7 +281,7 @@ function setStreamOutputValue(span, event) {
|
|
|
186
281
|
if (stringified) span.setAttribute("output.value", stringified);
|
|
187
282
|
}
|
|
188
283
|
if (e.finishReason) {
|
|
189
|
-
span.setAttribute("
|
|
284
|
+
span.setAttribute("neatlogs.llm.finish_reason", String(e.finishReason));
|
|
190
285
|
}
|
|
191
286
|
}
|
|
192
287
|
var WRAPPED_FUNCTIONS = [
|
|
@@ -206,6 +301,8 @@ var wrappedExports = /* @__PURE__ */ new WeakSet();
|
|
|
206
301
|
var wrapperByOriginal = /* @__PURE__ */ new WeakMap();
|
|
207
302
|
function wrapAISDK(aiModule) {
|
|
208
303
|
const wrapped = { ...aiModule };
|
|
304
|
+
const hasRegisterTelemetry = "registerTelemetry" in aiModule && typeof Reflect.get(aiModule, "registerTelemetry") === "function";
|
|
305
|
+
const telemetryKey = hasRegisterTelemetry ? "telemetry" : "experimental_telemetry";
|
|
209
306
|
for (const name of WRAPPED_FUNCTIONS) {
|
|
210
307
|
const original = aiModule[name];
|
|
211
308
|
if (typeof original !== "function") continue;
|
|
@@ -217,12 +314,16 @@ function wrapAISDK(aiModule) {
|
|
|
217
314
|
if (name === "streamText" || name === "streamObject") {
|
|
218
315
|
wrapped[name] = cacheWrapper(
|
|
219
316
|
original,
|
|
220
|
-
createStreamWrapper(name, original)
|
|
317
|
+
createStreamWrapper(name, original, telemetryKey)
|
|
221
318
|
);
|
|
222
319
|
} else {
|
|
223
320
|
wrapped[name] = cacheWrapper(
|
|
224
321
|
original,
|
|
225
|
-
createAsyncWrapper(
|
|
322
|
+
createAsyncWrapper(
|
|
323
|
+
name,
|
|
324
|
+
original,
|
|
325
|
+
telemetryKey
|
|
326
|
+
)
|
|
226
327
|
);
|
|
227
328
|
}
|
|
228
329
|
}
|
|
@@ -232,7 +333,7 @@ function wrapAISDK(aiModule) {
|
|
|
232
333
|
const existing = getExistingWrapper(original);
|
|
233
334
|
wrapped[name] = existing ?? cacheWrapper(
|
|
234
335
|
original,
|
|
235
|
-
createAgentConstructorWrapper(original)
|
|
336
|
+
createAgentConstructorWrapper(original, telemetryKey)
|
|
236
337
|
);
|
|
237
338
|
}
|
|
238
339
|
return wrapped;
|
|
@@ -246,26 +347,30 @@ function cacheWrapper(original, wrapped) {
|
|
|
246
347
|
wrappedExports.add(wrapped);
|
|
247
348
|
return wrapped;
|
|
248
349
|
}
|
|
249
|
-
function createAgentConstructorWrapper(original) {
|
|
350
|
+
function createAgentConstructorWrapper(original, telemetryKey) {
|
|
250
351
|
return new Proxy(original, {
|
|
251
352
|
construct(target, args, newTarget) {
|
|
252
353
|
if (args.length === 0 || typeof args[0] !== "object" || args[0] === null) {
|
|
253
354
|
return Reflect.construct(target, args, newTarget);
|
|
254
355
|
}
|
|
255
|
-
const settings = mergeAgentSettings(args[0]);
|
|
356
|
+
const settings = mergeAgentSettings(args[0], telemetryKey);
|
|
256
357
|
return Reflect.construct(target, [settings, ...args.slice(1)], newTarget);
|
|
257
358
|
}
|
|
258
359
|
});
|
|
259
360
|
}
|
|
260
|
-
function mergeAgentSettings(settings) {
|
|
261
|
-
const merged = mergeTelemetry(settings);
|
|
361
|
+
function mergeAgentSettings(settings, telemetryKey) {
|
|
362
|
+
const merged = mergeTelemetry(settings, telemetryKey);
|
|
262
363
|
const userPrepareCall = settings.prepareCall;
|
|
263
364
|
if (typeof userPrepareCall !== "function") return merged;
|
|
264
365
|
return {
|
|
265
366
|
...merged,
|
|
266
367
|
prepareCall: async function wrappedPrepareCall(...args) {
|
|
267
368
|
const prepared = await Reflect.apply(userPrepareCall, this, args);
|
|
268
|
-
return prepared == null ? prepared : mergeTelemetry(
|
|
369
|
+
return prepared == null ? prepared : mergeTelemetry(
|
|
370
|
+
prepared,
|
|
371
|
+
telemetryKey,
|
|
372
|
+
settings.telemetry ?? settings.experimental_telemetry
|
|
373
|
+
);
|
|
269
374
|
}
|
|
270
375
|
};
|
|
271
376
|
}
|
|
@@ -277,7 +382,7 @@ function rootSpanKind(name) {
|
|
|
277
382
|
function getParentContext() {
|
|
278
383
|
return getNeatlogsParentContext();
|
|
279
384
|
}
|
|
280
|
-
function createAsyncWrapper(name, original) {
|
|
385
|
+
function createAsyncWrapper(name, original, telemetryKey) {
|
|
281
386
|
return async function wrappedAsyncFn(opts) {
|
|
282
387
|
const tracer = getNeatlogsTracer(TRACER_NAME);
|
|
283
388
|
const parentContext = getParentContext();
|
|
@@ -297,7 +402,7 @@ function createAsyncWrapper(name, original) {
|
|
|
297
402
|
if (name === "rerank" && opts?.query) {
|
|
298
403
|
span.setAttribute("ai.rerank.query", String(opts.query));
|
|
299
404
|
}
|
|
300
|
-
const merged = mergeTelemetry(opts);
|
|
405
|
+
const merged = mergeTelemetry(opts, telemetryKey);
|
|
301
406
|
const result = await original(merged);
|
|
302
407
|
if (!isEmbedOrRerank) {
|
|
303
408
|
setOutputValue(span, result);
|
|
@@ -314,7 +419,7 @@ function createAsyncWrapper(name, original) {
|
|
|
314
419
|
);
|
|
315
420
|
};
|
|
316
421
|
}
|
|
317
|
-
function createStreamWrapper(name, original) {
|
|
422
|
+
function createStreamWrapper(name, original, telemetryKey) {
|
|
318
423
|
return function wrappedStreamFn(opts) {
|
|
319
424
|
const tracer = getNeatlogsTracer(TRACER_NAME);
|
|
320
425
|
const parentContext = getParentContext();
|
|
@@ -334,7 +439,7 @@ function createStreamWrapper(name, original) {
|
|
|
334
439
|
};
|
|
335
440
|
try {
|
|
336
441
|
setInputValue(span, opts);
|
|
337
|
-
const merged = mergeTelemetry(opts);
|
|
442
|
+
const merged = mergeTelemetry(opts, telemetryKey);
|
|
338
443
|
const userOnFinish = opts?.onFinish;
|
|
339
444
|
const userOnError = opts?.onError;
|
|
340
445
|
const wrappedOpts = {
|
|
@@ -459,25 +564,47 @@ function createMirroredTracer(primary, secondary) {
|
|
|
459
564
|
})
|
|
460
565
|
};
|
|
461
566
|
}
|
|
462
|
-
function
|
|
567
|
+
function isNeatlogsV7Integration(integration) {
|
|
568
|
+
return typeof integration === "object" && integration !== null && NEATLOGS_V7_INTEGRATION in integration;
|
|
569
|
+
}
|
|
570
|
+
function mergeTelemetry(opts, telemetryKey, fallbackTelemetry) {
|
|
571
|
+
const legacyTelemetry = opts?.experimental_telemetry ?? {};
|
|
572
|
+
const v7Telemetry = opts?.telemetry ?? {};
|
|
573
|
+
const preferredTelemetry = telemetryKey === "telemetry" ? { ...legacyTelemetry, ...v7Telemetry } : { ...v7Telemetry, ...legacyTelemetry };
|
|
463
574
|
const requestedTelemetry = {
|
|
464
575
|
...fallbackTelemetry,
|
|
465
|
-
...
|
|
576
|
+
...preferredTelemetry,
|
|
466
577
|
metadata: {
|
|
467
578
|
...fallbackTelemetry?.metadata,
|
|
468
|
-
...
|
|
579
|
+
...legacyTelemetry.metadata,
|
|
580
|
+
...v7Telemetry.metadata
|
|
469
581
|
}
|
|
470
582
|
};
|
|
471
|
-
const
|
|
583
|
+
const existingNeatlogsIntegration = Array.isArray(
|
|
584
|
+
requestedTelemetry.integrations
|
|
585
|
+
) ? requestedTelemetry.integrations.find(isNeatlogsV7Integration) : void 0;
|
|
586
|
+
const baseTelemetry = existingNeatlogsIntegration ? {
|
|
587
|
+
isEnabled: true,
|
|
588
|
+
recordInputs: true,
|
|
589
|
+
recordOutputs: true,
|
|
590
|
+
tracer: requestedTelemetry.tracer,
|
|
591
|
+
...requestedTelemetry.functionId !== void 0 ? { functionId: requestedTelemetry.functionId } : {},
|
|
592
|
+
metadata: requestedTelemetry.metadata,
|
|
593
|
+
integrations: [existingNeatlogsIntegration]
|
|
594
|
+
} : createAITelemetry({
|
|
472
595
|
functionId: requestedTelemetry.functionId,
|
|
473
596
|
metadata: requestedTelemetry.metadata,
|
|
474
597
|
tracer: requestedTelemetry.tracer
|
|
475
598
|
});
|
|
476
599
|
const callerTracer = requestedTelemetry.tracer;
|
|
477
600
|
const hasCallerTracer = callerTracer !== void 0;
|
|
601
|
+
const requestedIntegrations = Array.isArray(requestedTelemetry.integrations) ? requestedTelemetry.integrations.filter(
|
|
602
|
+
(integration) => !isNeatlogsV7Integration(integration)
|
|
603
|
+
) : [];
|
|
604
|
+
const { telemetry: _telemetry, experimental_telemetry: _legacy, ...rest } = opts ?? {};
|
|
478
605
|
return {
|
|
479
|
-
...
|
|
480
|
-
|
|
606
|
+
...rest,
|
|
607
|
+
[telemetryKey]: {
|
|
481
608
|
...baseTelemetry,
|
|
482
609
|
...requestedTelemetry,
|
|
483
610
|
isEnabled: true,
|
|
@@ -487,7 +614,8 @@ function mergeTelemetry(opts, fallbackTelemetry) {
|
|
|
487
614
|
// Do not add Neatlogs-only marker metadata to a caller-owned telemetry
|
|
488
615
|
// pipeline such as Laminar. Both providers receive the same AI SDK span
|
|
489
616
|
// data, while their providers, parent contexts, and exporters stay separate.
|
|
490
|
-
metadata: hasCallerTracer ? requestedTelemetry.metadata : baseTelemetry.metadata
|
|
617
|
+
metadata: hasCallerTracer ? requestedTelemetry.metadata : baseTelemetry.metadata,
|
|
618
|
+
integrations: [...baseTelemetry.integrations, ...requestedIntegrations]
|
|
491
619
|
}
|
|
492
620
|
};
|
|
493
621
|
}
|
package/dist/ai-sdk.mjs.map
CHANGED
|
@@ -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":["AsyncLocalStorage","neatlogsGlobal","AsyncLocalStorage","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":["AsyncLocalStorage","neatlogsGlobal","AsyncLocalStorage","stringified"]}
|
package/dist/cli.cjs
CHANGED
|
@@ -7104,7 +7104,7 @@ var TELEMETRY_CONFLICT_PRECEDENCE = Object.freeze(
|
|
|
7104
7104
|
);
|
|
7105
7105
|
|
|
7106
7106
|
// src/version.ts
|
|
7107
|
-
var __version__ = "1.1.
|
|
7107
|
+
var __version__ = "1.1.22";
|
|
7108
7108
|
|
|
7109
7109
|
// src/init.ts
|
|
7110
7110
|
var path2 = __toESM(require("path"));
|
|
@@ -10523,12 +10523,16 @@ var ObservableBatchLogRecordProcessor = class extends import_sdk_logs.BatchLogRe
|
|
|
10523
10523
|
// src/core/log.ts
|
|
10524
10524
|
var import_node_async_hooks5 = require("async_hooks");
|
|
10525
10525
|
var logger13 = getLogger();
|
|
10526
|
-
var
|
|
10527
|
-
var
|
|
10526
|
+
var LOG_RUNTIME_STATE_KEY = /* @__PURE__ */ Symbol.for("neatlogs.log_runtime_state");
|
|
10527
|
+
var neatlogsGlobal3 = globalThis;
|
|
10528
|
+
var logRuntimeState = neatlogsGlobal3[LOG_RUNTIME_STATE_KEY] ?? (neatlogsGlobal3[LOG_RUNTIME_STATE_KEY] = {
|
|
10529
|
+
otelLogger: null,
|
|
10530
|
+
debugMode: false
|
|
10531
|
+
});
|
|
10528
10532
|
var stdoutCaptureContext = new import_node_async_hooks5.AsyncLocalStorage();
|
|
10529
10533
|
function _setOtelLogger(otelLogger, debug) {
|
|
10530
|
-
|
|
10531
|
-
|
|
10534
|
+
logRuntimeState.otelLogger = otelLogger;
|
|
10535
|
+
logRuntimeState.debugMode = debug;
|
|
10532
10536
|
}
|
|
10533
10537
|
|
|
10534
10538
|
// src/prompt/client.ts
|
|
@@ -11357,7 +11361,7 @@ var _logProvider = null;
|
|
|
11357
11361
|
var _spanProcessor = null;
|
|
11358
11362
|
var _transportSpanProcessors = [];
|
|
11359
11363
|
var _completionProcessor = null;
|
|
11360
|
-
var
|
|
11364
|
+
var _debugMode = false;
|
|
11361
11365
|
var _deliveryDiagnostics = new DeliveryDiagnostics();
|
|
11362
11366
|
var _initIdentity = null;
|
|
11363
11367
|
var _effectiveSampleRate = 1;
|
|
@@ -11649,7 +11653,7 @@ async function _performInit(options) {
|
|
|
11649
11653
|
if (options.debug) {
|
|
11650
11654
|
enableDebugLogging();
|
|
11651
11655
|
}
|
|
11652
|
-
|
|
11656
|
+
_debugMode = options.debug ?? false;
|
|
11653
11657
|
const resolvedWorkflowName = _resolveWorkflowName(options.workflowName);
|
|
11654
11658
|
const endpoint = resolveInitEndpoint(options.endpoint);
|
|
11655
11659
|
const baseUrl = resolveIngestBaseUrl(endpoint);
|
|
@@ -11987,7 +11991,7 @@ async function _performShutdown(terminationReason, timeoutMs) {
|
|
|
11987
11991
|
_spanProcessor = null;
|
|
11988
11992
|
_transportSpanProcessors = [];
|
|
11989
11993
|
_completionProcessor = null;
|
|
11990
|
-
|
|
11994
|
+
_debugMode = false;
|
|
11991
11995
|
_effectiveSampleRate = 1;
|
|
11992
11996
|
_exportEnabled = false;
|
|
11993
11997
|
_queueMaxSize = 2048;
|