neatlogs 1.1.6 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +16 -27
  2. package/dist/ai-sdk.cjs +142 -54
  3. package/dist/ai-sdk.cjs.map +1 -1
  4. package/dist/ai-sdk.mjs +145 -53
  5. package/dist/ai-sdk.mjs.map +1 -1
  6. package/dist/anthropic.cjs +65 -29
  7. package/dist/anthropic.cjs.map +1 -1
  8. package/dist/anthropic.mjs +73 -36
  9. package/dist/anthropic.mjs.map +1 -1
  10. package/dist/azure-openai.cjs +65 -29
  11. package/dist/azure-openai.cjs.map +1 -1
  12. package/dist/azure-openai.mjs +73 -36
  13. package/dist/azure-openai.mjs.map +1 -1
  14. package/dist/bedrock.cjs +65 -29
  15. package/dist/bedrock.cjs.map +1 -1
  16. package/dist/bedrock.mjs +73 -36
  17. package/dist/bedrock.mjs.map +1 -1
  18. package/dist/claude-agent-sdk.cjs +55 -15
  19. package/dist/claude-agent-sdk.cjs.map +1 -1
  20. package/dist/claude-agent-sdk.mjs +52 -8
  21. package/dist/claude-agent-sdk.mjs.map +1 -1
  22. package/dist/google-genai.cjs +69 -35
  23. package/dist/google-genai.cjs.map +1 -1
  24. package/dist/google-genai.mjs +77 -42
  25. package/dist/google-genai.mjs.map +1 -1
  26. package/dist/index.cjs +963 -682
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.ts +44 -2
  29. package/dist/index.mjs +893 -609
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/langchain.cjs +46 -12
  32. package/dist/langchain.cjs.map +1 -1
  33. package/dist/langchain.mjs +54 -19
  34. package/dist/langchain.mjs.map +1 -1
  35. package/dist/mastra-wrap.cjs +330 -46
  36. package/dist/mastra-wrap.cjs.map +1 -1
  37. package/dist/mastra-wrap.mjs +331 -41
  38. package/dist/mastra-wrap.mjs.map +1 -1
  39. package/dist/openai-agents.cjs +45 -9
  40. package/dist/openai-agents.cjs.map +1 -1
  41. package/dist/openai-agents.mjs +45 -5
  42. package/dist/openai-agents.mjs.map +1 -1
  43. package/dist/openai.cjs +65 -29
  44. package/dist/openai.cjs.map +1 -1
  45. package/dist/openai.mjs +73 -36
  46. package/dist/openai.mjs.map +1 -1
  47. package/dist/opencode-plugin.cjs +1 -1
  48. package/dist/opencode-plugin.cjs.map +1 -1
  49. package/dist/opencode-plugin.mjs +1 -1
  50. package/dist/opencode-plugin.mjs.map +1 -1
  51. package/dist/openrouter-agent.cjs +48 -12
  52. package/dist/openrouter-agent.cjs.map +1 -1
  53. package/dist/openrouter-agent.mjs +56 -19
  54. package/dist/openrouter-agent.mjs.map +1 -1
  55. package/dist/pi-agent.cjs +45 -9
  56. package/dist/pi-agent.cjs.map +1 -1
  57. package/dist/pi-agent.mjs +45 -6
  58. package/dist/pi-agent.mjs.map +1 -1
  59. package/dist/strands.cjs +4 -136
  60. package/dist/strands.cjs.map +1 -1
  61. package/dist/strands.d.ts +5 -24
  62. package/dist/strands.mjs +4 -136
  63. package/dist/strands.mjs.map +1 -1
  64. package/dist/vertex-ai.cjs +69 -35
  65. package/dist/vertex-ai.cjs.map +1 -1
  66. package/dist/vertex-ai.mjs +77 -42
  67. package/dist/vertex-ai.mjs.map +1 -1
  68. package/package.json +2 -7
@@ -24,7 +24,47 @@ __export(mastra_wrap_exports, {
24
24
  wrapMastraRerank: () => wrapMastraRerank
25
25
  });
26
26
  module.exports = __toCommonJS(mastra_wrap_exports);
27
+ var import_api2 = require("@opentelemetry/api");
28
+
29
+ // src/core/provider.ts
30
+ var import_node_async_hooks = require("async_hooks");
27
31
  var import_api = require("@opentelemetry/api");
32
+ var PRIVATE_SPAN_STORAGE_KEY = /* @__PURE__ */ Symbol.for(
33
+ "neatlogs.private_span_async_local_storage"
34
+ );
35
+ var PRIVATE_PROVIDER_STATE_KEY = /* @__PURE__ */ Symbol.for(
36
+ "neatlogs.private_provider_state"
37
+ );
38
+ var neatlogsGlobal = globalThis;
39
+ var privateContextStorage = neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] ?? (neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] = new import_node_async_hooks.AsyncLocalStorage());
40
+ var providerState = neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] ?? (neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] = {
41
+ provider: null
42
+ });
43
+ var preInitTracer = {
44
+ startSpan() {
45
+ return import_api.trace.wrapSpanContext(import_api.INVALID_SPAN_CONTEXT);
46
+ },
47
+ startActiveSpan(_name, arg2, arg3, arg4) {
48
+ const fn = typeof arg2 === "function" ? arg2 : typeof arg3 === "function" ? arg3 : arg4;
49
+ return fn(import_api.trace.wrapSpanContext(import_api.INVALID_SPAN_CONTEXT));
50
+ }
51
+ };
52
+ function getNeatlogsTracer(name) {
53
+ return providerState.provider?.getTracer(name) ?? preInitTracer;
54
+ }
55
+ function getNeatlogsActiveContext() {
56
+ return privateContextStorage.getStore() ?? import_api.ROOT_CONTEXT;
57
+ }
58
+ function getNeatlogsParentContext(baseContext) {
59
+ return baseContext ?? getNeatlogsActiveContext();
60
+ }
61
+ function withNeatlogsSpan(span, fn, baseContext) {
62
+ const base = baseContext ?? getNeatlogsActiveContext();
63
+ const ctx = import_api.trace.setSpan(base, span);
64
+ return privateContextStorage.run(ctx, fn);
65
+ }
66
+
67
+ // src/mastra-wrap.ts
28
68
  var TRACER_NAME = "neatlogs.mastra";
29
69
  var PATCH_FLAG = "_neatlogs_patched";
30
70
  function wrapMastra(entity) {
@@ -52,7 +92,14 @@ function wrapMastra(entity) {
52
92
  }
53
93
  function wrapMastraRerank(rerankFn) {
54
94
  return (async function tracedRerank(...args) {
55
- return withSpan("mastra.rerank", { "neatlogs.span.kind": "RERANKER" }, (span) => {
95
+ return withSpan("mastra.rerank", {
96
+ "neatlogs.span.kind": "RERANKER",
97
+ "input.value": safeStringify({
98
+ documents: args?.[0],
99
+ query: args?.[1],
100
+ options: args?.[3]
101
+ })
102
+ }, (span) => {
56
103
  const results = args?.[0];
57
104
  const query = args?.[1];
58
105
  const options = args?.[3];
@@ -64,7 +111,7 @@ function wrapMastraRerank(rerankFn) {
64
111
  if (options?.topK != null) span.setAttribute("neatlogs.reranker.top_k", options.topK);
65
112
  return Promise.resolve(rerankFn(...args)).then((result) => {
66
113
  span.setAttribute("neatlogs.reranker.output_documents", safeStringify(result));
67
- span.setAttribute("output.value", safeStringify(result));
114
+ span.setAttribute("output.value", toOutputValue(result));
68
115
  return result;
69
116
  });
70
117
  });
@@ -100,6 +147,7 @@ function patchAgentMethod(agent, method, streaming) {
100
147
  const model = extractModelId(agent.model);
101
148
  installAgentLlmHook(agent);
102
149
  installAgentToolHooks(agent);
150
+ patchDynamicToolsets(opts?.toolsets);
103
151
  const attrs = {
104
152
  "neatlogs.span.kind": "AGENT",
105
153
  "neatlogs.agent.name": agentName,
@@ -111,12 +159,15 @@ function patchAgentMethod(agent, method, streaming) {
111
159
  }
112
160
  if (streaming) attrs["neatlogs.llm.is_streaming"] = true;
113
161
  if (streaming) {
114
- const tracer = import_api.trace.getTracer(TRACER_NAME);
115
- const span = tracer.startSpan(`mastra.agent.${agentName}`, { attributes: attrs }, import_api.context.active());
116
- const ctx = import_api.trace.setSpan(import_api.context.active(), span);
162
+ const tracer = getNeatlogsTracer(TRACER_NAME);
163
+ const span = tracer.startSpan(
164
+ `mastra.agent.${agentName}`,
165
+ { attributes: attrs },
166
+ getNeatlogsParentContext()
167
+ );
117
168
  try {
118
- const result = await import_api.context.with(ctx, () => orig(input, opts));
119
- return wrapStreamingOutput(result, span, ctx);
169
+ const result = await withNeatlogsSpan(span, () => orig(input, opts));
170
+ return wrapStreamingOutput(result, span);
120
171
  } catch (err) {
121
172
  recordError(span, err);
122
173
  span.end();
@@ -130,6 +181,15 @@ function patchAgentMethod(agent, method, streaming) {
130
181
  });
131
182
  };
132
183
  }
184
+ function patchDynamicToolsets(toolsets) {
185
+ if (!toolsets || typeof toolsets !== "object") return;
186
+ for (const [toolsetName, tools] of Object.entries(toolsets)) {
187
+ if (!tools || typeof tools !== "object") continue;
188
+ for (const [key, tool] of Object.entries(tools)) {
189
+ patchToolExecute(tool, `${toolsetName}.${key}`);
190
+ }
191
+ }
192
+ }
133
193
  function installAgentLlmHook(agent) {
134
194
  if (agent.__neatlogs_llm_hook || typeof agent.getLLM !== "function") return;
135
195
  agent.__neatlogs_llm_hook = true;
@@ -163,17 +223,19 @@ function patchModelInPlace(model) {
163
223
  const promptInput = callOpts?.prompt ?? callOpts?.messages;
164
224
  if (promptInput !== void 0) attrs["input.value"] = safeStringify(promptInput);
165
225
  captureInvocationParams(attrs, callOpts);
166
- return withActiveSpan(`mastra.llm.${modelId || "model"}.${fn}`, attrs, async (span) => {
226
+ const spanName = `mastra.llm.${modelId || "model"}.${fn}`;
227
+ if (isStream) {
228
+ return traceStreamingModelCall(spanName, attrs, callOpts, orig);
229
+ }
230
+ return withActiveSpan(spanName, attrs, async (span) => {
167
231
  const result = await orig(callOpts);
168
- if (!isStream) finalizeModelResult(span, result);
169
- else if (result?.usage) recordUsage(span, result.usage);
232
+ finalizeModelResult(span, result);
170
233
  return result;
171
234
  });
172
235
  };
173
236
  }
174
237
  }
175
238
  function installAgentToolHooks(agent) {
176
- if (agent.__neatlogs_tool_hook) return;
177
239
  let tools;
178
240
  try {
179
241
  tools = typeof agent.listTools === "function" ? agent.listTools() : void 0;
@@ -181,7 +243,6 @@ function installAgentToolHooks(agent) {
181
243
  tools = void 0;
182
244
  }
183
245
  if (!tools || typeof tools !== "object") return;
184
- agent.__neatlogs_tool_hook = true;
185
246
  for (const [key, tool] of Object.entries(tools)) {
186
247
  patchToolExecute(tool, key);
187
248
  }
@@ -200,7 +261,7 @@ function patchToolExecute(tool, key) {
200
261
  if (tool.description) attrs["neatlogs.tool.description"] = String(tool.description);
201
262
  return withActiveSpan(`mastra.tool.${toolName}`, attrs, async (span) => {
202
263
  const result = await orig(params, options);
203
- span.setAttribute("output.value", safeStringify(result));
264
+ span.setAttribute("output.value", toOutputValue(result));
204
265
  return result;
205
266
  });
206
267
  };
@@ -223,16 +284,17 @@ function patchRunMethod(run, method, workflowName) {
223
284
  run[method] = async function tracedRunMethod(startOpts) {
224
285
  const attrs = {
225
286
  "neatlogs.span.kind": "WORKFLOW",
226
- "neatlogs.workflow.name": workflowName
287
+ "neatlogs.workflow.name": workflowName,
288
+ "input.value": safeStringify(startOpts ?? {})
227
289
  };
228
- if (startOpts?.inputData !== void 0) {
229
- attrs["input.value"] = safeStringify(startOpts.inputData);
230
- }
290
+ if (startOpts?.inputData !== void 0) attrs["input.value"] = safeStringify(startOpts.inputData);
231
291
  return withActiveSpan(`mastra.workflow.${workflowName}`, attrs, async (span) => {
232
292
  const result = await orig(startOpts);
233
293
  if (result?.status) span.setAttribute("neatlogs.metadata", safeStringify({ status: result.status }));
234
294
  if (result?.result !== void 0) {
235
295
  span.setAttribute("output.value", safeStringify(result.result));
296
+ } else {
297
+ span.setAttribute("output.value", toOutputValue(result));
236
298
  }
237
299
  return result;
238
300
  });
@@ -260,7 +322,7 @@ function patchVectorOp(vector, op, kind) {
260
322
  if (kind === "RETRIEVER" && params?.topK != null) attrs["neatlogs.retriever.top_k"] = params.topK;
261
323
  return withActiveSpan(`mastra.vector.${op}`, attrs, async (span) => {
262
324
  const result = await orig(params);
263
- span.setAttribute("output.value", safeStringify(result));
325
+ span.setAttribute("output.value", toOutputValue(result));
264
326
  return result;
265
327
  });
266
328
  };
@@ -278,23 +340,38 @@ function patchMemory(memory) {
278
340
  };
279
341
  return withActiveSpan(`mastra.memory.${op}`, attrs, async (span) => {
280
342
  const result = await orig(...args);
281
- span.setAttribute("output.value", safeStringify(result));
343
+ span.setAttribute("output.value", summarizeMemoryOutput(op, args?.[0], result));
282
344
  return result;
283
345
  });
284
346
  };
285
347
  }
286
348
  }
349
+ function summarizeMemoryOutput(op, input, result) {
350
+ if (result !== void 0) return toOutputValue(result);
351
+ const summary = { completed: true };
352
+ if (op === "saveMessages") {
353
+ summary.messageCount = Array.isArray(input?.messages) ? input.messages.length : 0;
354
+ } else if (op === "deleteMessages") {
355
+ const ids = input?.messageIds ?? input?.ids;
356
+ if (Array.isArray(ids)) summary.requestedCount = ids.length;
357
+ } else if (op === "recall") {
358
+ summary.resultCount = 0;
359
+ }
360
+ return safeStringify(summary);
361
+ }
287
362
  function patchDocument(doc) {
288
363
  if (typeof doc.chunk !== "function") return;
289
364
  const orig = doc.chunk.bind(doc);
290
365
  doc.chunk = async function tracedChunk(...args) {
291
366
  const attrs = {
292
367
  "neatlogs.span.kind": "CHAIN",
293
- "neatlogs.db.operation": "chunk"
368
+ "neatlogs.db.operation": "chunk",
369
+ "input.value": safeStringify(args)
294
370
  };
295
371
  return withActiveSpan("mastra.document.chunk", attrs, async (span) => {
296
372
  const result = await orig(...args);
297
373
  if (Array.isArray(result)) span.setAttribute("neatlogs.db.documents_count", result.length);
374
+ span.setAttribute("output.value", toOutputValue(result));
298
375
  return result;
299
376
  });
300
377
  };
@@ -317,9 +394,10 @@ function wrapRootMastra(mastra) {
317
394
  }
318
395
  });
319
396
  }
320
- function wrapStreamingOutput(output, span, ctx) {
397
+ function wrapStreamingOutput(output, span) {
321
398
  if (!output) {
322
- span.setStatus({ code: import_api.SpanStatusCode.OK });
399
+ span.setAttribute("output.value", toOutputValue(output));
400
+ span.setStatus({ code: import_api2.SpanStatusCode.OK });
323
401
  span.end();
324
402
  return output;
325
403
  }
@@ -328,7 +406,7 @@ function wrapStreamingOutput(output, span, ctx) {
328
406
  if (ended) return;
329
407
  ended = true;
330
408
  if (err) recordError(span, err);
331
- else span.setStatus({ code: import_api.SpanStatusCode.OK });
409
+ else span.setStatus({ code: import_api2.SpanStatusCode.OK });
332
410
  span.end();
333
411
  };
334
412
  if (output.text && typeof output.text.then === "function") {
@@ -342,6 +420,11 @@ function wrapStreamingOutput(output, span, ctx) {
342
420
  if (typeof text === "string" && text) {
343
421
  span.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
344
422
  span.setAttribute("neatlogs.llm.output_messages.0.content", text);
423
+ span.setAttribute("output.value", text);
424
+ } else {
425
+ span.setAttribute("output.value", safeStringify({
426
+ finishReason: finishReason ?? "completed"
427
+ }));
345
428
  }
346
429
  if (usage) recordUsage(span, usage);
347
430
  if (finishReason) span.setAttribute("neatlogs.llm.stop_reason", normalizeFinishReason(finishReason));
@@ -351,7 +434,7 @@ function wrapStreamingOutput(output, span, ctx) {
351
434
  }
352
435
  };
353
436
  void finalize();
354
- return rebindStreamContext(output, ctx);
437
+ return rebindStreamContext(output, span);
355
438
  }
356
439
  if (output[Symbol.asyncIterator]) {
357
440
  const origIterator = output[Symbol.asyncIterator].bind(output);
@@ -362,8 +445,12 @@ function wrapStreamingOutput(output, span, ctx) {
362
445
  const iterator = origIterator();
363
446
  const finish = () => {
364
447
  if (textParts.length) {
448
+ const text = textParts.join("");
365
449
  span.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
366
- span.setAttribute("neatlogs.llm.output_messages.0.content", textParts.join(""));
450
+ span.setAttribute("neatlogs.llm.output_messages.0.content", text);
451
+ span.setAttribute("output.value", text);
452
+ } else {
453
+ span.setAttribute("output.value", safeStringify({ streamCompleted: true }));
367
454
  }
368
455
  endOnce();
369
456
  };
@@ -410,29 +497,62 @@ function wrapStreamingOutput(output, span, ctx) {
410
497
  endOnce();
411
498
  return output;
412
499
  }
413
- function rebindStreamContext(output, ctx) {
500
+ function rebindStreamContext(output, span) {
414
501
  const STREAM_PROPS = /* @__PURE__ */ new Set(["textStream", "fullStream", "objectStream", "elementStream"]);
415
502
  return new Proxy(output, {
416
503
  get(target, prop, receiver) {
417
504
  const value = Reflect.get(target, prop, receiver);
418
505
  if (typeof prop === "string" && STREAM_PROPS.has(prop) && value && value[Symbol.asyncIterator]) {
419
- const origIterator = value[Symbol.asyncIterator].bind(value);
420
- return {
421
- [Symbol.asyncIterator]() {
422
- return import_api.context.with(ctx, () => origIterator());
506
+ return new Proxy(value, {
507
+ get(stream, streamProp, streamReceiver) {
508
+ if (streamProp === Symbol.asyncIterator) {
509
+ return () => wrapBoundIterator(stream[Symbol.asyncIterator](), span);
510
+ }
511
+ const streamValue = Reflect.get(stream, streamProp, streamReceiver);
512
+ if (streamProp === "getReader" && typeof streamValue === "function") {
513
+ return (...args) => {
514
+ const reader = Reflect.apply(streamValue, stream, args);
515
+ return new Proxy(reader, {
516
+ get(readerTarget, readerProp, readerReceiver) {
517
+ const readerValue = Reflect.get(readerTarget, readerProp, readerReceiver);
518
+ if (typeof readerValue !== "function") return readerValue;
519
+ if (readerProp === "read" || readerProp === "cancel") {
520
+ return (...readerArgs) => withNeatlogsSpan(
521
+ span,
522
+ () => Reflect.apply(readerValue, readerTarget, readerArgs)
523
+ );
524
+ }
525
+ return readerValue.bind(readerTarget);
526
+ }
527
+ });
528
+ };
529
+ }
530
+ return typeof streamValue === "function" ? streamValue.bind(stream) : streamValue;
423
531
  }
424
- };
532
+ });
425
533
  }
426
534
  if (typeof value === "function") return value.bind(target);
427
535
  return value;
428
536
  }
429
537
  });
430
538
  }
539
+ function wrapBoundIterator(iterator, span) {
540
+ return {
541
+ next: (...args) => withNeatlogsSpan(span, () => iterator.next(...args)),
542
+ return: iterator.return ? (...args) => withNeatlogsSpan(span, () => iterator.return(...args)) : void 0,
543
+ throw: iterator.throw ? (...args) => withNeatlogsSpan(span, () => iterator.throw(...args)) : void 0
544
+ };
545
+ }
431
546
  function finalizeAgentResult(span, result) {
432
- if (!result) return;
547
+ if (result === void 0) {
548
+ span.setAttribute("output.value", toOutputValue(result));
549
+ return;
550
+ }
433
551
  if (result.text) {
552
+ const text = String(result.text);
434
553
  span.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
435
- span.setAttribute("neatlogs.llm.output_messages.0.content", String(result.text));
554
+ span.setAttribute("neatlogs.llm.output_messages.0.content", text);
555
+ span.setAttribute("output.value", text);
436
556
  }
437
557
  if (Array.isArray(result.toolCalls)) {
438
558
  for (let i = 0; i < result.toolCalls.length; i++) {
@@ -440,16 +560,26 @@ function finalizeAgentResult(span, result) {
440
560
  const p = tc.payload ?? tc;
441
561
  setToolCall(span, i, p.toolName ?? p.name, p.args ?? p.arguments, p.toolCallId ?? p.id);
442
562
  }
563
+ if (!result.text) {
564
+ span.setAttribute("output.value", safeStringify({ toolCalls: result.toolCalls }));
565
+ }
443
566
  }
444
567
  if (result.usage) recordUsage(span, result.usage);
445
568
  if (result.finishReason) span.setAttribute("neatlogs.llm.stop_reason", normalizeFinishReason(result.finishReason));
446
569
  if (result.model) span.setAttribute("neatlogs.llm.model_name", result.model);
570
+ if (!result.text && !Array.isArray(result.toolCalls)) {
571
+ span.setAttribute("output.value", safeStringify(result));
572
+ }
447
573
  }
448
574
  function finalizeModelResult(span, result) {
449
- if (!result) return;
575
+ if (result === void 0) {
576
+ span.setAttribute("output.value", toOutputValue(result));
577
+ return;
578
+ }
450
579
  if (typeof result.text === "string" && result.text) {
451
580
  span.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
452
581
  span.setAttribute("neatlogs.llm.output_messages.0.content", result.text);
582
+ span.setAttribute("output.value", result.text);
453
583
  } else if (Array.isArray(result.content)) {
454
584
  const text = result.content.filter((p) => p?.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
455
585
  if (text) {
@@ -462,10 +592,131 @@ function finalizeModelResult(span, result) {
462
592
  setToolCall(span, i, tc.toolName, tc.input ?? tc.args, tc.toolCallId);
463
593
  }
464
594
  span.setAttribute("output.value", safeStringify(result.content));
595
+ } else {
596
+ span.setAttribute("output.value", safeStringify(result));
465
597
  }
466
598
  if (result.usage) recordUsage(span, result.usage);
467
599
  span.setAttribute("neatlogs.llm.stop_reason", normalizeFinishReason(result.finishReason));
468
600
  }
601
+ async function traceStreamingModelCall(spanName, attrs, callOpts, orig) {
602
+ const tracer = getNeatlogsTracer(TRACER_NAME);
603
+ const span = tracer.startSpan(
604
+ spanName,
605
+ { attributes: attrs },
606
+ getNeatlogsParentContext()
607
+ );
608
+ try {
609
+ const result = await withNeatlogsSpan(span, () => orig(callOpts));
610
+ return wrapModelStreamingResult(result, span);
611
+ } catch (err) {
612
+ recordError(span, err);
613
+ span.end();
614
+ throw err;
615
+ }
616
+ }
617
+ function wrapModelStreamingResult(result, span) {
618
+ const stream = result?.stream;
619
+ if (!stream || typeof stream.getReader !== "function") {
620
+ if (result?.usage) recordUsage(span, result.usage);
621
+ span.setAttribute("output.value", safeStringify(result ?? { streamCompleted: true }));
622
+ span.setStatus({ code: import_api2.SpanStatusCode.OK });
623
+ span.end();
624
+ return result;
625
+ }
626
+ const capture = { textParts: [], toolCalls: [] };
627
+ let ended = false;
628
+ const endOnce = (err) => {
629
+ if (ended) return;
630
+ ended = true;
631
+ if (err) {
632
+ recordError(span, err);
633
+ } else {
634
+ finalizeModelStreamSpan(span, capture);
635
+ span.setStatus({ code: import_api2.SpanStatusCode.OK });
636
+ }
637
+ span.end();
638
+ };
639
+ const sourceReader = stream.getReader();
640
+ const wrappedStream = new ReadableStream({
641
+ async pull(controller) {
642
+ try {
643
+ const next = await withNeatlogsSpan(span, () => sourceReader.read());
644
+ if (next.done) {
645
+ endOnce();
646
+ controller.close();
647
+ return;
648
+ }
649
+ captureModelStreamPart(span, capture, next.value);
650
+ controller.enqueue(next.value);
651
+ } catch (err) {
652
+ endOnce(err);
653
+ controller.error(err);
654
+ }
655
+ },
656
+ async cancel(reason) {
657
+ try {
658
+ await withNeatlogsSpan(span, () => sourceReader.cancel(reason));
659
+ endOnce();
660
+ } catch (err) {
661
+ endOnce(err);
662
+ throw err;
663
+ }
664
+ }
665
+ });
666
+ return new Proxy(result, {
667
+ get(target, prop, receiver) {
668
+ if (prop === "stream") return wrappedStream;
669
+ const value = Reflect.get(target, prop, receiver);
670
+ return typeof value === "function" ? value.bind(target) : value;
671
+ }
672
+ });
673
+ }
674
+ function captureModelStreamPart(span, capture, part) {
675
+ const type = part?.type;
676
+ if (type === "text-delta") {
677
+ const text = part.delta ?? part.text ?? part.payload?.text;
678
+ if (typeof text === "string" && text) capture.textParts.push(text);
679
+ }
680
+ if (type === "tool-call") {
681
+ const index = capture.toolCalls.length;
682
+ const toolCall = {
683
+ id: part.toolCallId ?? part.id,
684
+ name: part.toolName ?? part.name,
685
+ arguments: part.input ?? part.args ?? part.arguments
686
+ };
687
+ capture.toolCalls.push(toolCall);
688
+ setToolCall(span, index, toolCall.name, toolCall.arguments, toolCall.id);
689
+ }
690
+ if (type === "finish") {
691
+ capture.finishReason = part.finishReason;
692
+ capture.usage = part.usage;
693
+ }
694
+ if (part?.usage) capture.usage = part.usage;
695
+ if (part?.finishReason !== void 0) capture.finishReason = part.finishReason;
696
+ }
697
+ function finalizeModelStreamSpan(span, capture) {
698
+ const text = capture.textParts.join("");
699
+ if (text) {
700
+ span.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
701
+ span.setAttribute("neatlogs.llm.output_messages.0.content", text);
702
+ }
703
+ if (capture.usage) recordUsage(span, capture.usage);
704
+ if (capture.finishReason !== void 0) {
705
+ span.setAttribute(
706
+ "neatlogs.llm.stop_reason",
707
+ normalizeFinishReason(capture.finishReason)
708
+ );
709
+ }
710
+ if (text && capture.toolCalls.length === 0) {
711
+ span.setAttribute("output.value", text);
712
+ return;
713
+ }
714
+ span.setAttribute("output.value", safeStringify({
715
+ ...text ? { text } : {},
716
+ ...capture.toolCalls.length ? { toolCalls: capture.toolCalls } : {},
717
+ finishReason: capture.finishReason ?? "completed"
718
+ }));
719
+ }
469
720
  function normalizeFinishReason(fr) {
470
721
  if (fr == null) return "";
471
722
  if (typeof fr === "string") return fr;
@@ -521,21 +772,36 @@ function recordUsage(span, usage) {
521
772
  const prompt = tokenValue(usage.promptTokens ?? usage.inputTokens ?? usage.input_tokens);
522
773
  const completion = tokenValue(usage.completionTokens ?? usage.outputTokens ?? usage.output_tokens);
523
774
  const total = tokenValue(usage.totalTokens);
775
+ const reasoning = tokenValue(
776
+ usage.reasoningTokens ?? usage.outputTokens?.reasoning ?? usage.output_tokens?.reasoning
777
+ );
778
+ const cacheRead = tokenValue(
779
+ usage.cachedInputTokens ?? usage.cacheReadInputTokens ?? usage.cache_read_input_tokens ?? usage.inputTokens?.cacheRead ?? usage.input_tokens?.cache_read
780
+ );
781
+ const cacheWrite = tokenValue(
782
+ usage.cacheCreationInputTokens ?? usage.cacheWriteInputTokens ?? usage.cache_creation_input_tokens ?? usage.inputTokens?.cacheWrite ?? usage.input_tokens?.cache_write
783
+ );
524
784
  if (prompt != null) span.setAttribute("neatlogs.llm.token_count.prompt", prompt);
525
785
  if (completion != null) span.setAttribute("neatlogs.llm.token_count.completion", completion);
786
+ if (reasoning != null) span.setAttribute("neatlogs.llm.token_count.reasoning", reasoning);
787
+ if (cacheRead != null) span.setAttribute("neatlogs.llm.token_count.cache_read", cacheRead);
788
+ if (cacheWrite != null) span.setAttribute("neatlogs.llm.token_count.cache_write", cacheWrite);
526
789
  if (total != null) span.setAttribute("neatlogs.llm.token_count.total", total);
527
790
  else if (prompt != null && completion != null) {
528
791
  span.setAttribute("neatlogs.llm.token_count.total", prompt + completion);
529
792
  }
530
793
  }
531
794
  function withActiveSpan(name, attrs, fn) {
532
- const tracer = import_api.trace.getTracer(TRACER_NAME);
533
- const span = tracer.startSpan(name, { attributes: attrs }, import_api.context.active());
534
- const ctx = import_api.trace.setSpan(import_api.context.active(), span);
535
- return import_api.context.with(ctx, async () => {
795
+ const tracer = getNeatlogsTracer(TRACER_NAME);
796
+ const span = tracer.startSpan(
797
+ name,
798
+ { attributes: attrs },
799
+ getNeatlogsParentContext()
800
+ );
801
+ return withNeatlogsSpan(span, async () => {
536
802
  try {
537
803
  const result = await fn(span);
538
- span.setStatus({ code: import_api.SpanStatusCode.OK });
804
+ span.setStatus({ code: import_api2.SpanStatusCode.OK });
539
805
  return result;
540
806
  } catch (err) {
541
807
  recordError(span, err);
@@ -546,10 +812,16 @@ function withActiveSpan(name, attrs, fn) {
546
812
  });
547
813
  }
548
814
  function withSpan(name, attrs, fn) {
549
- const tracer = import_api.trace.getTracer(TRACER_NAME);
550
- const span = tracer.startSpan(name, { attributes: attrs }, import_api.context.active());
551
- return Promise.resolve().then(() => fn(span)).then((result) => {
552
- span.setStatus({ code: import_api.SpanStatusCode.OK });
815
+ const tracer = getNeatlogsTracer(TRACER_NAME);
816
+ const span = tracer.startSpan(
817
+ name,
818
+ { attributes: attrs },
819
+ getNeatlogsParentContext()
820
+ );
821
+ return Promise.resolve(
822
+ withNeatlogsSpan(span, () => fn(span))
823
+ ).then((result) => {
824
+ span.setStatus({ code: import_api2.SpanStatusCode.OK });
553
825
  span.end();
554
826
  return result;
555
827
  }).catch((err) => {
@@ -575,18 +847,30 @@ function toInputValue(input) {
575
847
  }
576
848
  function safeStringify(value) {
577
849
  if (typeof value === "string") return value;
850
+ if (value === void 0) {
851
+ return JSON.stringify({ value_type: "undefined" });
852
+ }
578
853
  try {
579
854
  return JSON.stringify(value) ?? "";
580
855
  } catch {
581
- return "";
856
+ return JSON.stringify({
857
+ serialization_error: "circular_or_unsupported_value",
858
+ value_type: typeof value
859
+ });
582
860
  }
583
861
  }
862
+ function toOutputValue(value) {
863
+ return safeStringify(value === void 0 ? { completed: true } : value);
864
+ }
584
865
  function recordError(span, err) {
866
+ span.setAttribute("output.value", safeStringify({
867
+ error: err instanceof Error ? { name: err.name, message: err.message } : { message: String(err) }
868
+ }));
585
869
  if (err instanceof Error) {
586
- span.setStatus({ code: import_api.SpanStatusCode.ERROR, message: err.message });
870
+ span.setStatus({ code: import_api2.SpanStatusCode.ERROR, message: err.message });
587
871
  span.recordException(err);
588
872
  } else {
589
- span.setStatus({ code: import_api.SpanStatusCode.ERROR, message: String(err) });
873
+ span.setStatus({ code: import_api2.SpanStatusCode.ERROR, message: String(err) });
590
874
  }
591
875
  }
592
876
  // Annotate the CommonJS export names for ESM import in node: