neatlogs 1.0.8 → 1.0.10

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/dist/bedrock.cjs CHANGED
@@ -24,12 +24,158 @@ __export(bedrock_exports, {
24
24
  wrapBedrock: () => wrapBedrock
25
25
  });
26
26
  module.exports = __toCommonJS(bedrock_exports);
27
+ var import_api4 = require("@opentelemetry/api");
28
+
29
+ // src/core/auto-root.ts
30
+ var import_api3 = require("@opentelemetry/api");
31
+
32
+ // src/core/context.ts
33
+ var import_api2 = require("@opentelemetry/api");
34
+
35
+ // src/prompt/template.ts
36
+ var import_node_async_hooks = require("async_hooks");
37
+ var _promptStorage = new import_node_async_hooks.AsyncLocalStorage();
38
+ var _userPromptStorage = new import_node_async_hooks.AsyncLocalStorage();
39
+
40
+ // src/core/logger.ts
41
+ var LOG_LEVELS = {
42
+ DEBUG: 0,
43
+ INFO: 1,
44
+ WARN: 2,
45
+ ERROR: 3,
46
+ NONE: 4
47
+ };
48
+ var _logLevel = "INFO";
49
+ var _disabled = false;
50
+ function _getConfiguredLevel() {
51
+ const envLevel = process.env.NEATLOGS_LOG_LEVEL?.toUpperCase();
52
+ if (envLevel && envLevel in LOG_LEVELS) {
53
+ return envLevel;
54
+ }
55
+ return "INFO";
56
+ }
57
+ _logLevel = _getConfiguredLevel();
58
+ function getLogger() {
59
+ return {
60
+ debug(message, ...args) {
61
+ if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.DEBUG) {
62
+ console.debug(`[neatlogs] ${message}`, ...args);
63
+ }
64
+ },
65
+ info(message, ...args) {
66
+ if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.INFO) {
67
+ console.info(`[neatlogs] ${message}`, ...args);
68
+ }
69
+ },
70
+ warn(message, ...args) {
71
+ if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.WARN) {
72
+ console.warn(`[neatlogs] ${message}`, ...args);
73
+ }
74
+ },
75
+ error(message, ...args) {
76
+ if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.ERROR) {
77
+ console.error(`[neatlogs] ${message}`, ...args);
78
+ }
79
+ }
80
+ };
81
+ }
82
+
83
+ // src/core/mask.ts
84
+ var logger = getLogger();
85
+
86
+ // src/decorators/base.ts
27
87
  var import_api = require("@opentelemetry/api");
88
+ var logger2 = getLogger();
89
+
90
+ // src/core/context.ts
91
+ var logger3 = getLogger();
92
+ var _sessionConfig = {};
93
+ function getSessionConfig() {
94
+ return { ..._sessionConfig };
95
+ }
96
+ var PROMPT_VARIABLES_KEY = (0, import_api2.createContextKey)("neatlogs.prompt_variables");
97
+ var PROMPT_TEMPLATE_KEY = (0, import_api2.createContextKey)("neatlogs.prompt_template");
98
+ var PROMPT_VERSION_KEY = (0, import_api2.createContextKey)("neatlogs.prompt_version");
99
+ var USER_PROMPT_TEMPLATE_KEY = (0, import_api2.createContextKey)("neatlogs.user_prompt_template");
100
+ var USER_PROMPT_VARIABLES_KEY = (0, import_api2.createContextKey)("neatlogs.user_prompt_variables");
101
+
102
+ // src/core/auto-root.ts
103
+ var ROOT_KINDS = /* @__PURE__ */ new Set(["workflow", "chain", "agent", "mcp_tool"]);
104
+ function autoRootEnabled() {
105
+ const val = (process.env.NEATLOGS_AUTO_ROOT ?? "").trim().toLowerCase();
106
+ return !["false", "0", "no", "off"].includes(val);
107
+ }
108
+ function resolveRootWorkflowName() {
109
+ try {
110
+ const name = getSessionConfig()?.workflowName;
111
+ if (typeof name === "string" && name.trim()) return name;
112
+ } catch {
113
+ }
114
+ return "workflow";
115
+ }
116
+ function wrapSpanWithRoot(child, root) {
117
+ let ended = false;
118
+ return new Proxy(child, {
119
+ get(target, prop, _receiver) {
120
+ if (prop === "end") {
121
+ return (...args) => {
122
+ if (ended) return;
123
+ ended = true;
124
+ try {
125
+ target.end(...args);
126
+ } finally {
127
+ try {
128
+ root.end();
129
+ } catch {
130
+ }
131
+ }
132
+ };
133
+ }
134
+ const value = Reflect.get(target, prop, target);
135
+ return typeof value === "function" ? value.bind(target) : value;
136
+ }
137
+ });
138
+ }
139
+ var AutoRootTracer = class {
140
+ constructor(_tracer) {
141
+ this._tracer = _tracer;
142
+ }
143
+ _tracer;
144
+ startSpan(name, options, context) {
145
+ const kind = String(
146
+ options?.attributes?.["neatlogs.span.kind"] ?? ""
147
+ ).toLowerCase();
148
+ const ctx = context ?? import_api3.context.active();
149
+ const parent = import_api3.trace.getSpan(ctx);
150
+ const needsRoot = autoRootEnabled() && !ROOT_KINDS.has(kind) && !(parent !== void 0 && parent.isRecording());
151
+ if (!needsRoot) {
152
+ return this._tracer.startSpan(name, options, context);
153
+ }
154
+ const root = this._tracer.startSpan(
155
+ resolveRootWorkflowName(),
156
+ { attributes: { "neatlogs.span.kind": "workflow", "neatlogs.auto_root": true } },
157
+ ctx
158
+ );
159
+ const childCtx = import_api3.trace.setSpan(ctx, root);
160
+ const child = this._tracer.startSpan(name, options, childCtx);
161
+ return wrapSpanWithRoot(child, root);
162
+ }
163
+ // startActiveSpan is used by traceTool (callback-scoped, always under an
164
+ // active span in practice) — pass straight through, no auto-root.
165
+ startActiveSpan = ((...args) => this._tracer.startActiveSpan(
166
+ ...args
167
+ ));
168
+ };
169
+ function getProviderTracer(name) {
170
+ return new AutoRootTracer(import_api3.trace.getTracer(name));
171
+ }
172
+
173
+ // src/bedrock.ts
28
174
  var TRACER_NAME = "neatlogs.bedrock";
29
175
  var PROVIDER = "bedrock";
30
176
  function traceTool(name, fn) {
31
177
  return async function tracedTool(args) {
32
- const tracer = import_api.trace.getTracer(TRACER_NAME);
178
+ const tracer = getProviderTracer(TRACER_NAME);
33
179
  return tracer.startActiveSpan(
34
180
  `tool.${name}`,
35
181
  {
@@ -39,12 +185,12 @@ function traceTool(name, fn) {
39
185
  "input.value": safeStringify(args)
40
186
  }
41
187
  },
42
- import_api.context.active(),
188
+ import_api4.context.active(),
43
189
  async (span) => {
44
190
  try {
45
191
  const result = await fn(args);
46
192
  span.setAttribute("output.value", safeStringify(result));
47
- span.setStatus({ code: import_api.SpanStatusCode.OK });
193
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
48
194
  return result;
49
195
  } catch (err) {
50
196
  recordError(span, err);
@@ -90,7 +236,7 @@ function vendorFromModel(modelId) {
90
236
  return vendor || "bedrock";
91
237
  }
92
238
  function startSpan(name, modelId, isStream) {
93
- return import_api.trace.getTracer(TRACER_NAME).startSpan(name, {
239
+ return getProviderTracer(TRACER_NAME).startSpan(name, {
94
240
  attributes: {
95
241
  "neatlogs.span.kind": "LLM",
96
242
  "neatlogs.llm.provider": PROVIDER,
@@ -98,7 +244,7 @@ function startSpan(name, modelId, isStream) {
98
244
  "neatlogs.llm.model_name": String(modelId ?? ""),
99
245
  "neatlogs.llm.is_streaming": isStream
100
246
  }
101
- }, import_api.context.active());
247
+ }, import_api4.context.active());
102
248
  }
103
249
  function tracedConverse(originalSend, command, input, rest, isStream) {
104
250
  const span = startSpan(
@@ -107,8 +253,8 @@ function tracedConverse(originalSend, command, input, rest, isStream) {
107
253
  isStream
108
254
  );
109
255
  setConverseInput(span, input);
110
- const ctx = import_api.trace.setSpan(import_api.context.active(), span);
111
- const promise = import_api.context.with(ctx, () => originalSend(command, ...rest));
256
+ const ctx = import_api4.trace.setSpan(import_api4.context.active(), span);
257
+ const promise = import_api4.context.with(ctx, () => originalSend(command, ...rest));
112
258
  return promise.then(
113
259
  (response) => {
114
260
  if (isStream) {
@@ -188,7 +334,7 @@ function finalizeConverse(span, response) {
188
334
  }
189
335
  if (response?.stopReason) span.setAttribute("neatlogs.llm.finish_reason", String(response.stopReason));
190
336
  setConverseUsage(span, response?.usage);
191
- span.setStatus({ code: import_api.SpanStatusCode.OK });
337
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
192
338
  span.end();
193
339
  }
194
340
  function setConverseUsage(span, usage) {
@@ -202,7 +348,7 @@ function setConverseUsage(span, usage) {
202
348
  function wrapConverseStream(response, span) {
203
349
  const stream = response?.stream;
204
350
  if (!stream || typeof stream[Symbol.asyncIterator] !== "function") {
205
- span.setStatus({ code: import_api.SpanStatusCode.OK });
351
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
206
352
  span.end();
207
353
  return response;
208
354
  }
@@ -270,7 +416,7 @@ function finalizeConverseStream(span, textParts, toolCalls, finishReason, usage)
270
416
  }
271
417
  if (finishReason) span.setAttribute("neatlogs.llm.finish_reason", String(finishReason));
272
418
  setConverseUsage(span, usage);
273
- span.setStatus({ code: import_api.SpanStatusCode.OK });
419
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
274
420
  span.end();
275
421
  }
276
422
  function isEmbeddingModel(modelId) {
@@ -282,13 +428,13 @@ function tracedInvokeModel(originalSend, command, input, rest, isStream) {
282
428
  const bodyIn = decodeBody(input?.body);
283
429
  let span;
284
430
  if (isEmbedding) {
285
- span = import_api.trace.getTracer(TRACER_NAME).startSpan("bedrock.invoke_model", {
431
+ span = getProviderTracer(TRACER_NAME).startSpan("bedrock.invoke_model", {
286
432
  attributes: {
287
433
  "neatlogs.span.kind": "EMBEDDING",
288
434
  "neatlogs.llm.provider": PROVIDER,
289
435
  "neatlogs.embedding.model_name": String(input?.modelId ?? "")
290
436
  }
291
- }, import_api.context.active());
437
+ }, import_api4.context.active());
292
438
  const text = bodyIn?.inputText ?? bodyIn?.texts ?? bodyIn?.input_text;
293
439
  if (text) {
294
440
  span.setAttribute("neatlogs.embedding.text", typeof text === "string" ? text : safeStringify(text));
@@ -301,8 +447,8 @@ function tracedInvokeModel(originalSend, command, input, rest, isStream) {
301
447
  );
302
448
  setInvokeInput(span, vendor, bodyIn);
303
449
  }
304
- const ctx = import_api.trace.setSpan(import_api.context.active(), span);
305
- const promise = import_api.context.with(ctx, () => originalSend(command, ...rest));
450
+ const ctx = import_api4.trace.setSpan(import_api4.context.active(), span);
451
+ const promise = import_api4.context.with(ctx, () => originalSend(command, ...rest));
306
452
  return promise.then(
307
453
  (response) => {
308
454
  if (isStream) {
@@ -315,7 +461,7 @@ function tracedInvokeModel(originalSend, command, input, rest, isStream) {
315
461
  finalizeInvoke(span, vendor, decodeBody(response?.body));
316
462
  }
317
463
  } catch {
318
- span.setStatus({ code: import_api.SpanStatusCode.OK });
464
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
319
465
  span.end();
320
466
  }
321
467
  return response;
@@ -340,7 +486,7 @@ function finalizeInvokeEmbedding(span, body) {
340
486
  span.setAttribute("neatlogs.llm.token_count.prompt", body.inputTextTokenCount);
341
487
  span.setAttribute("neatlogs.embedding.token_count", body.inputTextTokenCount);
342
488
  }
343
- span.setStatus({ code: import_api.SpanStatusCode.OK });
489
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
344
490
  span.end();
345
491
  }
346
492
  function decodeBody(body) {
@@ -448,13 +594,13 @@ function finalizeInvoke(span, vendor, body) {
448
594
  span.setAttribute("neatlogs.llm.token_count.total", promptTokens + completionTokens);
449
595
  }
450
596
  if (finishReason) span.setAttribute("neatlogs.llm.finish_reason", String(finishReason));
451
- span.setStatus({ code: import_api.SpanStatusCode.OK });
597
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
452
598
  span.end();
453
599
  }
454
600
  function wrapInvokeStream(response, span, vendor) {
455
601
  const body = response?.body;
456
602
  if (!body || typeof body[Symbol.asyncIterator] !== "function") {
457
- span.setStatus({ code: import_api.SpanStatusCode.OK });
603
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
458
604
  span.end();
459
605
  return response;
460
606
  }
@@ -472,7 +618,7 @@ function wrapInvokeStream(response, span, vendor) {
472
618
  if (promptTokens != null) span.setAttribute("neatlogs.llm.token_count.prompt", promptTokens);
473
619
  if (completionTokens != null) span.setAttribute("neatlogs.llm.token_count.completion", completionTokens);
474
620
  if (finishReason) span.setAttribute("neatlogs.llm.finish_reason", String(finishReason));
475
- span.setStatus({ code: import_api.SpanStatusCode.OK });
621
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
476
622
  span.end();
477
623
  };
478
624
  const wrappedBody = {
@@ -525,10 +671,10 @@ function safeStringify(value) {
525
671
  }
526
672
  function recordError(span, err) {
527
673
  if (err instanceof Error) {
528
- span.setStatus({ code: import_api.SpanStatusCode.ERROR, message: err.message });
674
+ span.setStatus({ code: import_api4.SpanStatusCode.ERROR, message: err.message });
529
675
  span.recordException(err);
530
676
  } else {
531
- span.setStatus({ code: import_api.SpanStatusCode.ERROR, message: String(err) });
677
+ span.setStatus({ code: import_api4.SpanStatusCode.ERROR, message: String(err) });
532
678
  }
533
679
  span.end();
534
680
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bedrock.ts"],"sourcesContent":["/**\n * Neatlogs AWS Bedrock wrapper.\n *\n * The AWS SDK v3 `BedrockRuntimeClient` dispatches every API through\n * `client.send(new XCommand({...}))`. This wrapper intercepts `send`, inspects\n * the command, and traces the Converse and InvokeModel APIs. Token extraction\n * handles Claude, Titan, and Llama response formats.\n *\n * Usage:\n * import { wrapBedrock } from 'neatlogs/bedrock';\n * import { BedrockRuntimeClient, ConverseCommand } from '@aws-sdk/client-bedrock-runtime';\n * const client = wrapBedrock(new BedrockRuntimeClient({ region: 'us-east-1' }));\n * await client.send(new ConverseCommand({ modelId, messages }));\n *\n * `neatlogs.llm.provider` is always `bedrock`; `neatlogs.llm.system` is the\n * underlying model vendor (anthropic / amazon / meta / ...), inferred from modelId.\n */\n\nimport { trace, context as otelContext, SpanStatusCode, type Span } from '@opentelemetry/api';\n\nconst TRACER_NAME = 'neatlogs.bedrock';\nconst PROVIDER = 'bedrock';\n\n/**\n * Wrap a tool/function implementation to emit TOOL spans when executed.\n *\n * Usage:\n * const getWeather = traceTool('get_weather', async (args: { city: string }) => {\n * return `Weather in ${args.city}: sunny`;\n * });\n */\nexport function traceTool<TArgs = any, TResult = any>(\n name: string,\n fn: (args: TArgs) => TResult | Promise<TResult>,\n): (args: TArgs) => Promise<TResult> {\n return async function tracedTool(args: TArgs): Promise<TResult> {\n const tracer = trace.getTracer(TRACER_NAME);\n return tracer.startActiveSpan(\n `tool.${name}`,\n {\n attributes: {\n 'neatlogs.span.kind': 'TOOL',\n 'neatlogs.tool.name': name,\n 'input.value': safeStringify(args),\n },\n },\n otelContext.active(),\n async (span) => {\n try {\n const result = await fn(args);\n span.setAttribute('output.value', safeStringify(result));\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n } finally {\n span.end();\n }\n },\n );\n };\n}\n\nexport function wrapBedrock<T extends object>(client: T): T {\n const c = client as any;\n if (c._neatlogsBedrockPatched) return client;\n if (typeof c.send !== 'function') return client;\n\n const originalSend = c.send.bind(c);\n\n c.send = function (command: any, ...rest: any[]): any {\n const name = command?.constructor?.name ?? '';\n const input = command?.input ?? {};\n\n if (name === 'ConverseCommand') {\n return tracedConverse(originalSend, command, input, rest, false);\n }\n if (name === 'ConverseStreamCommand') {\n return tracedConverse(originalSend, command, input, rest, true);\n }\n if (name === 'InvokeModelCommand') {\n return tracedInvokeModel(originalSend, command, input, rest, false);\n }\n if (name === 'InvokeModelWithResponseStreamCommand') {\n return tracedInvokeModel(originalSend, command, input, rest, true);\n }\n\n return originalSend(command, ...rest);\n };\n\n c._neatlogsBedrockPatched = true;\n return client;\n}\n\n// ---------------------------------------------------------------------------\n// Vendor / span helpers\n// ---------------------------------------------------------------------------\n\nfunction vendorFromModel(modelId: any): string {\n let tail = String(modelId ?? '').split('/').pop() ?? '';\n for (const prefix of ['us.', 'eu.', 'apac.', 'us-gov.']) {\n if (tail.startsWith(prefix)) tail = tail.slice(prefix.length);\n }\n const vendor = tail.includes('.') ? tail.split('.')[0] : '';\n return vendor || 'bedrock';\n}\n\nfunction startSpan(name: string, modelId: any, isStream: boolean): Span {\n return trace.getTracer(TRACER_NAME).startSpan(name, {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': vendorFromModel(modelId),\n 'neatlogs.llm.model_name': String(modelId ?? ''),\n 'neatlogs.llm.is_streaming': isStream,\n },\n }, otelContext.active());\n}\n\n// ---------------------------------------------------------------------------\n// Converse API\n// ---------------------------------------------------------------------------\n\nfunction tracedConverse(\n originalSend: (...a: any[]) => any,\n command: any,\n input: any,\n rest: any[],\n isStream: boolean,\n): any {\n const span = startSpan(\n isStream ? 'bedrock.converse_stream' : 'bedrock.converse',\n input?.modelId,\n isStream,\n );\n setConverseInput(span, input);\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => originalSend(command, ...rest));\n\n return promise.then(\n (response: any) => {\n if (isStream) {\n return wrapConverseStream(response, span);\n }\n finalizeConverse(span, response);\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n}\n\nfunction setConverseInput(span: Span, input: any): void {\n let idx = 0;\n\n if (Array.isArray(input?.system)) {\n const text = input.system.map((b: any) => b?.text ?? '').join(' ').trim();\n if (text) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'system');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, text);\n idx++;\n }\n }\n\n for (const msg of input?.messages ?? []) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, msg?.role ?? 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, converseBlocksToText(msg?.content));\n idx++;\n }\n\n const cfg = input?.inferenceConfig ?? {};\n if (cfg.temperature != null) span.setAttribute('neatlogs.llm.temperature', cfg.temperature);\n if (cfg.topP != null) span.setAttribute('neatlogs.llm.top_p', cfg.topP);\n if (cfg.maxTokens != null) span.setAttribute('neatlogs.llm.max_tokens', cfg.maxTokens);\n\n const tools = input?.toolConfig?.tools ?? [];\n for (let i = 0; i < tools.length; i++) {\n const spec = tools[i]?.toolSpec ?? {};\n if (spec.name) span.setAttribute(`neatlogs.llm.tools.${i}.name`, spec.name);\n if (spec.description) span.setAttribute(`neatlogs.llm.tools.${i}.description`, spec.description);\n if (spec.inputSchema) span.setAttribute(`neatlogs.llm.tools.${i}.input_schema`, safeStringify(spec.inputSchema));\n }\n}\n\nfunction converseBlocksToText(content: any): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return safeStringify(content);\n const parts: string[] = [];\n for (const block of content) {\n if (block && typeof block === 'object') {\n if ('text' in block) parts.push(String(block.text));\n else if ('toolResult' in block) parts.push(safeStringify(block.toolResult));\n else if ('toolUse' in block) parts.push(safeStringify(block.toolUse));\n else parts.push(safeStringify(block));\n } else {\n parts.push(String(block));\n }\n }\n return parts.join('\\n');\n}\n\nfunction finalizeConverse(span: Span, response: any): void {\n const content = response?.output?.message?.content ?? [];\n const textParts: string[] = [];\n let toolIdx = 0;\n\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n if ('text' in block) {\n textParts.push(String(block.text));\n } else if ('toolUse' in block) {\n const tu = block.toolUse;\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.id`, String(tu?.toolUseId ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.name`, String(tu?.name ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.arguments`, safeStringify(tu?.input ?? {}));\n toolIdx++;\n }\n }\n\n if (textParts.length) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', textParts.join(''));\n }\n if (response?.stopReason) span.setAttribute('neatlogs.llm.finish_reason', String(response.stopReason));\n setConverseUsage(span, response?.usage);\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\nfunction setConverseUsage(span: Span, usage: any): void {\n if (!usage) return;\n if (usage.inputTokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.inputTokens);\n if (usage.outputTokens != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.outputTokens);\n if (usage.totalTokens != null) span.setAttribute('neatlogs.llm.token_count.total', usage.totalTokens);\n if (usage.cacheReadInputTokens != null) span.setAttribute('neatlogs.llm.token_count.cache_read', usage.cacheReadInputTokens);\n if (usage.cacheWriteInputTokens != null) span.setAttribute('neatlogs.llm.token_count.cache_write', usage.cacheWriteInputTokens);\n}\n\nfunction wrapConverseStream(response: any, span: Span): any {\n const stream = response?.stream;\n if (!stream || typeof stream[Symbol.asyncIterator] !== 'function') {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n }\n\n const originalIterator = stream[Symbol.asyncIterator].bind(stream);\n const textParts: string[] = [];\n const toolCalls: Record<number, { id: string; name: string; arguments: string }> = {};\n let finishReason = '';\n let usage: any = null;\n\n const wrappedStream = {\n [Symbol.asyncIterator]() {\n const iterator = originalIterator();\n return {\n async next(): Promise<IteratorResult<any>> {\n try {\n const result = await iterator.next();\n if (result.done) {\n finalizeConverseStream(span, textParts, toolCalls, finishReason, usage);\n return result;\n }\n const ev = result.value;\n const delta = ev?.contentBlockDelta?.delta;\n if (delta?.text) textParts.push(delta.text);\n if (delta?.toolUse?.input) {\n const idx = ev.contentBlockDelta.contentBlockIndex ?? 0;\n toolCalls[idx] = toolCalls[idx] ?? { id: '', name: '', arguments: '' };\n toolCalls[idx].arguments += delta.toolUse.input;\n }\n const startBlk = ev?.contentBlockStart?.start?.toolUse;\n if (startBlk) {\n const idx = ev.contentBlockStart.contentBlockIndex ?? 0;\n toolCalls[idx] = toolCalls[idx] ?? { id: '', name: '', arguments: '' };\n toolCalls[idx].name = startBlk.name ?? '';\n toolCalls[idx].id = startBlk.toolUseId ?? '';\n }\n if (ev?.messageStop?.stopReason) finishReason = ev.messageStop.stopReason;\n if (ev?.metadata?.usage) usage = ev.metadata.usage;\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n }\n },\n async return(value?: any): Promise<IteratorResult<any>> {\n finalizeConverseStream(span, textParts, toolCalls, finishReason, usage);\n return iterator.return?.(value) ?? { done: true, value: undefined };\n },\n };\n },\n };\n\n response.stream = wrappedStream;\n return response;\n}\n\nfunction finalizeConverseStream(\n span: Span,\n textParts: string[],\n toolCalls: Record<number, { id: string; name: string; arguments: string }>,\n finishReason: string,\n usage: any,\n): void {\n const full = textParts.join('');\n if (full) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', full);\n }\n let j = 0;\n for (const tc of Object.values(toolCalls)) {\n if (tc.id) span.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, tc.id);\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.name);\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, tc.arguments);\n j++;\n }\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(finishReason));\n setConverseUsage(span, usage);\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\n// ---------------------------------------------------------------------------\n// InvokeModel API (vendor-specific body formats)\n// ---------------------------------------------------------------------------\n\nfunction isEmbeddingModel(modelId: any): boolean {\n return String(modelId ?? '').toLowerCase().includes('embed');\n}\n\nfunction tracedInvokeModel(\n originalSend: (...a: any[]) => any,\n command: any,\n input: any,\n rest: any[],\n isStream: boolean,\n): any {\n const vendor = vendorFromModel(input?.modelId);\n const isEmbedding = !isStream && isEmbeddingModel(input?.modelId);\n const bodyIn = decodeBody(input?.body);\n\n let span: Span;\n if (isEmbedding) {\n span = trace.getTracer(TRACER_NAME).startSpan('bedrock.invoke_model', {\n attributes: {\n 'neatlogs.span.kind': 'EMBEDDING',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.embedding.model_name': String(input?.modelId ?? ''),\n },\n }, otelContext.active());\n const text = bodyIn?.inputText ?? bodyIn?.texts ?? bodyIn?.input_text;\n if (text) {\n span.setAttribute('neatlogs.embedding.text', (typeof text === 'string' ? text : safeStringify(text)));\n }\n } else {\n span = startSpan(\n isStream ? 'bedrock.invoke_model_with_response_stream' : 'bedrock.invoke_model',\n input?.modelId,\n isStream,\n );\n setInvokeInput(span, vendor, bodyIn);\n }\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => originalSend(command, ...rest));\n\n return promise.then(\n (response: any) => {\n if (isStream) {\n return wrapInvokeStream(response, span, vendor);\n }\n try {\n if (isEmbedding) {\n finalizeInvokeEmbedding(span, decodeBody(response?.body));\n } else {\n finalizeInvoke(span, vendor, decodeBody(response?.body));\n }\n } catch {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n }\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n}\n\nfunction finalizeInvokeEmbedding(span: Span, body: any): void {\n const emb = body?.embedding;\n const embs = body?.embeddings;\n if (Array.isArray(emb)) {\n span.setAttribute('neatlogs.embedding.count', 1);\n span.setAttribute('neatlogs.embedding.dimensions', emb.length);\n } else if (Array.isArray(embs) && embs.length) {\n span.setAttribute('neatlogs.embedding.count', embs.length);\n if (Array.isArray(embs[0])) span.setAttribute('neatlogs.embedding.dimensions', embs[0].length);\n }\n if (body?.inputTextTokenCount != null) {\n span.setAttribute('neatlogs.llm.token_count.prompt', body.inputTextTokenCount);\n span.setAttribute('neatlogs.embedding.token_count', body.inputTextTokenCount);\n }\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\nfunction decodeBody(body: any): any {\n try {\n if (body == null) return {};\n if (typeof body === 'string') return JSON.parse(body);\n // Uint8Array (AWS SDK v3 returns the response body as bytes)\n if (body instanceof Uint8Array) return JSON.parse(new TextDecoder().decode(body));\n if (typeof body === 'object' && typeof body.byteLength === 'number') {\n return JSON.parse(new TextDecoder().decode(body));\n }\n if (typeof body === 'object') return body;\n } catch {\n /* fall through */\n }\n return {};\n}\n\nfunction setInvokeInput(span: Span, vendor: string, body: any): void {\n let idx = 0;\n if (body?.system) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'system');\n span.setAttribute(\n `neatlogs.llm.input_messages.${idx}.content`,\n typeof body.system === 'string' ? body.system : safeStringify(body.system),\n );\n idx++;\n }\n if (Array.isArray(body?.messages)) {\n for (const msg of body.messages) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, msg?.role ?? 'user');\n span.setAttribute(\n `neatlogs.llm.input_messages.${idx}.content`,\n typeof msg?.content === 'string' ? msg.content : safeStringify(msg?.content),\n );\n idx++;\n }\n } else if (body?.prompt) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, String(body.prompt));\n } else if (body?.inputText) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, String(body.inputText));\n }\n\n if (body?.temperature != null) span.setAttribute('neatlogs.llm.temperature', body.temperature);\n if (body?.top_p != null) span.setAttribute('neatlogs.llm.top_p', body.top_p);\n const maxTokens = body?.max_tokens ?? body?.maxTokens ?? body?.max_tokens_to_sample;\n if (maxTokens != null) span.setAttribute('neatlogs.llm.max_tokens', maxTokens);\n const cfg = body?.textGenerationConfig;\n if (cfg) {\n if (cfg.temperature != null) span.setAttribute('neatlogs.llm.temperature', cfg.temperature);\n if (cfg.topP != null) span.setAttribute('neatlogs.llm.top_p', cfg.topP);\n if (cfg.maxTokenCount != null) span.setAttribute('neatlogs.llm.max_tokens', cfg.maxTokenCount);\n }\n}\n\nfunction finalizeInvoke(span: Span, vendor: string, body: any): void {\n let text: string | undefined;\n let promptTokens: number | undefined;\n let completionTokens: number | undefined;\n let finishReason: string | undefined;\n\n if (vendor === 'anthropic') {\n if (Array.isArray(body?.content)) {\n text = body.content.filter((b: any) => b?.type === 'text').map((b: any) => b.text).join('');\n let toolIdx = 0;\n for (const b of body.content) {\n if (b?.type === 'tool_use') {\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.id`, String(b.id ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.name`, String(b.name ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.arguments`, safeStringify(b.input ?? {}));\n toolIdx++;\n }\n }\n } else if (body?.completion != null) {\n text = body.completion;\n }\n promptTokens = body?.usage?.input_tokens;\n completionTokens = body?.usage?.output_tokens;\n finishReason = body?.stop_reason;\n } else if (vendor === 'amazon') {\n const r = Array.isArray(body?.results) ? body.results[0] : undefined;\n if (r) {\n text = r.outputText;\n completionTokens = r.tokenCount;\n finishReason = r.completionReason;\n }\n promptTokens = body?.inputTextTokenCount;\n } else if (vendor === 'meta') {\n text = body?.generation;\n promptTokens = body?.prompt_token_count;\n completionTokens = body?.generation_token_count;\n finishReason = body?.stop_reason;\n } else if (vendor === 'cohere') {\n const g = Array.isArray(body?.generations) ? body.generations[0] : undefined;\n if (g) {\n text = g.text;\n finishReason = g.finish_reason;\n }\n } else {\n text = body?.generation ?? body?.completion ?? body?.outputText;\n }\n\n if (text) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', String(text));\n }\n if (promptTokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', promptTokens);\n if (completionTokens != null) span.setAttribute('neatlogs.llm.token_count.completion', completionTokens);\n if (promptTokens != null && completionTokens != null) {\n span.setAttribute('neatlogs.llm.token_count.total', promptTokens + completionTokens);\n }\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(finishReason));\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\nfunction wrapInvokeStream(response: any, span: Span, vendor: string): any {\n const body = response?.body;\n if (!body || typeof body[Symbol.asyncIterator] !== 'function') {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n }\n\n const originalIterator = body[Symbol.asyncIterator].bind(body);\n const textParts: string[] = [];\n let promptTokens: number | undefined;\n let completionTokens: number | undefined;\n let finishReason: string | undefined;\n\n const finalize = () => {\n const full = textParts.join('');\n if (full) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', full);\n }\n if (promptTokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', promptTokens);\n if (completionTokens != null) span.setAttribute('neatlogs.llm.token_count.completion', completionTokens);\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(finishReason));\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n };\n\n const wrappedBody = {\n [Symbol.asyncIterator]() {\n const iterator = originalIterator();\n return {\n async next(): Promise<IteratorResult<any>> {\n try {\n const result = await iterator.next();\n if (result.done) {\n finalize();\n return result;\n }\n const data = decodeBody(result.value?.chunk?.bytes);\n if (data?.type === 'content_block_delta') {\n textParts.push(data?.delta?.text ?? '');\n } else if (data?.type === 'message_delta') {\n if (data?.delta?.stop_reason) finishReason = data.delta.stop_reason;\n if (data?.usage?.output_tokens != null) completionTokens = data.usage.output_tokens;\n }\n if (data?.outputText) textParts.push(data.outputText);\n if (data?.generation) textParts.push(data.generation);\n const metrics = data?.['amazon-bedrock-invocationMetrics'];\n if (metrics) {\n promptTokens = metrics.inputTokenCount ?? promptTokens;\n completionTokens = metrics.outputTokenCount ?? completionTokens;\n }\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n }\n },\n async return(value?: any): Promise<IteratorResult<any>> {\n finalize();\n return iterator.return?.(value) ?? { done: true, value: undefined };\n },\n };\n },\n };\n\n response.body = wrappedBody;\n return response;\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nfunction safeStringify(value: unknown): string {\n try {\n return typeof value === 'string' ? value : JSON.stringify(value);\n } catch {\n return '';\n }\n}\n\nfunction recordError(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 span.end();\n}\n"],"mappings":"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","names":["otelContext"]}
1
+ {"version":3,"sources":["../src/bedrock.ts","../src/core/auto-root.ts","../src/core/context.ts","../src/prompt/template.ts","../src/core/logger.ts","../src/core/mask.ts","../src/decorators/base.ts"],"sourcesContent":["/**\n * Neatlogs AWS Bedrock wrapper.\n *\n * The AWS SDK v3 `BedrockRuntimeClient` dispatches every API through\n * `client.send(new XCommand({...}))`. This wrapper intercepts `send`, inspects\n * the command, and traces the Converse and InvokeModel APIs. Token extraction\n * handles Claude, Titan, and Llama response formats.\n *\n * Usage:\n * import { wrapBedrock } from 'neatlogs/bedrock';\n * import { BedrockRuntimeClient, ConverseCommand } from '@aws-sdk/client-bedrock-runtime';\n * const client = wrapBedrock(new BedrockRuntimeClient({ region: 'us-east-1' }));\n * await client.send(new ConverseCommand({ modelId, messages }));\n *\n * `neatlogs.llm.provider` is always `bedrock`; `neatlogs.llm.system` is the\n * underlying model vendor (anthropic / amazon / meta / ...), inferred from modelId.\n */\n\nimport { trace, context as otelContext, SpanStatusCode, type Span } from '@opentelemetry/api';\nimport { getProviderTracer } from './core/auto-root.js';\n\nconst TRACER_NAME = 'neatlogs.bedrock';\nconst PROVIDER = 'bedrock';\n\n/**\n * Wrap a tool/function implementation to emit TOOL spans when executed.\n *\n * Usage:\n * const getWeather = traceTool('get_weather', async (args: { city: string }) => {\n * return `Weather in ${args.city}: sunny`;\n * });\n */\nexport function traceTool<TArgs = any, TResult = any>(\n name: string,\n fn: (args: TArgs) => TResult | Promise<TResult>,\n): (args: TArgs) => Promise<TResult> {\n return async function tracedTool(args: TArgs): Promise<TResult> {\n const tracer = getProviderTracer(TRACER_NAME);\n return tracer.startActiveSpan(\n `tool.${name}`,\n {\n attributes: {\n 'neatlogs.span.kind': 'TOOL',\n 'neatlogs.tool.name': name,\n 'input.value': safeStringify(args),\n },\n },\n otelContext.active(),\n async (span) => {\n try {\n const result = await fn(args);\n span.setAttribute('output.value', safeStringify(result));\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n } finally {\n span.end();\n }\n },\n );\n };\n}\n\nexport function wrapBedrock<T extends object>(client: T): T {\n const c = client as any;\n if (c._neatlogsBedrockPatched) return client;\n if (typeof c.send !== 'function') return client;\n\n const originalSend = c.send.bind(c);\n\n c.send = function (command: any, ...rest: any[]): any {\n const name = command?.constructor?.name ?? '';\n const input = command?.input ?? {};\n\n if (name === 'ConverseCommand') {\n return tracedConverse(originalSend, command, input, rest, false);\n }\n if (name === 'ConverseStreamCommand') {\n return tracedConverse(originalSend, command, input, rest, true);\n }\n if (name === 'InvokeModelCommand') {\n return tracedInvokeModel(originalSend, command, input, rest, false);\n }\n if (name === 'InvokeModelWithResponseStreamCommand') {\n return tracedInvokeModel(originalSend, command, input, rest, true);\n }\n\n return originalSend(command, ...rest);\n };\n\n c._neatlogsBedrockPatched = true;\n return client;\n}\n\n// ---------------------------------------------------------------------------\n// Vendor / span helpers\n// ---------------------------------------------------------------------------\n\nfunction vendorFromModel(modelId: any): string {\n let tail = String(modelId ?? '').split('/').pop() ?? '';\n for (const prefix of ['us.', 'eu.', 'apac.', 'us-gov.']) {\n if (tail.startsWith(prefix)) tail = tail.slice(prefix.length);\n }\n const vendor = tail.includes('.') ? tail.split('.')[0] : '';\n return vendor || 'bedrock';\n}\n\nfunction startSpan(name: string, modelId: any, isStream: boolean): Span {\n return getProviderTracer(TRACER_NAME).startSpan(name, {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': vendorFromModel(modelId),\n 'neatlogs.llm.model_name': String(modelId ?? ''),\n 'neatlogs.llm.is_streaming': isStream,\n },\n }, otelContext.active());\n}\n\n// ---------------------------------------------------------------------------\n// Converse API\n// ---------------------------------------------------------------------------\n\nfunction tracedConverse(\n originalSend: (...a: any[]) => any,\n command: any,\n input: any,\n rest: any[],\n isStream: boolean,\n): any {\n const span = startSpan(\n isStream ? 'bedrock.converse_stream' : 'bedrock.converse',\n input?.modelId,\n isStream,\n );\n setConverseInput(span, input);\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => originalSend(command, ...rest));\n\n return promise.then(\n (response: any) => {\n if (isStream) {\n return wrapConverseStream(response, span);\n }\n finalizeConverse(span, response);\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n}\n\nfunction setConverseInput(span: Span, input: any): void {\n let idx = 0;\n\n if (Array.isArray(input?.system)) {\n const text = input.system.map((b: any) => b?.text ?? '').join(' ').trim();\n if (text) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'system');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, text);\n idx++;\n }\n }\n\n for (const msg of input?.messages ?? []) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, msg?.role ?? 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, converseBlocksToText(msg?.content));\n idx++;\n }\n\n const cfg = input?.inferenceConfig ?? {};\n if (cfg.temperature != null) span.setAttribute('neatlogs.llm.temperature', cfg.temperature);\n if (cfg.topP != null) span.setAttribute('neatlogs.llm.top_p', cfg.topP);\n if (cfg.maxTokens != null) span.setAttribute('neatlogs.llm.max_tokens', cfg.maxTokens);\n\n const tools = input?.toolConfig?.tools ?? [];\n for (let i = 0; i < tools.length; i++) {\n const spec = tools[i]?.toolSpec ?? {};\n if (spec.name) span.setAttribute(`neatlogs.llm.tools.${i}.name`, spec.name);\n if (spec.description) span.setAttribute(`neatlogs.llm.tools.${i}.description`, spec.description);\n if (spec.inputSchema) span.setAttribute(`neatlogs.llm.tools.${i}.input_schema`, safeStringify(spec.inputSchema));\n }\n}\n\nfunction converseBlocksToText(content: any): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return safeStringify(content);\n const parts: string[] = [];\n for (const block of content) {\n if (block && typeof block === 'object') {\n if ('text' in block) parts.push(String(block.text));\n else if ('toolResult' in block) parts.push(safeStringify(block.toolResult));\n else if ('toolUse' in block) parts.push(safeStringify(block.toolUse));\n else parts.push(safeStringify(block));\n } else {\n parts.push(String(block));\n }\n }\n return parts.join('\\n');\n}\n\nfunction finalizeConverse(span: Span, response: any): void {\n const content = response?.output?.message?.content ?? [];\n const textParts: string[] = [];\n let toolIdx = 0;\n\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n if ('text' in block) {\n textParts.push(String(block.text));\n } else if ('toolUse' in block) {\n const tu = block.toolUse;\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.id`, String(tu?.toolUseId ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.name`, String(tu?.name ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.arguments`, safeStringify(tu?.input ?? {}));\n toolIdx++;\n }\n }\n\n if (textParts.length) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', textParts.join(''));\n }\n if (response?.stopReason) span.setAttribute('neatlogs.llm.finish_reason', String(response.stopReason));\n setConverseUsage(span, response?.usage);\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\nfunction setConverseUsage(span: Span, usage: any): void {\n if (!usage) return;\n if (usage.inputTokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.inputTokens);\n if (usage.outputTokens != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.outputTokens);\n if (usage.totalTokens != null) span.setAttribute('neatlogs.llm.token_count.total', usage.totalTokens);\n if (usage.cacheReadInputTokens != null) span.setAttribute('neatlogs.llm.token_count.cache_read', usage.cacheReadInputTokens);\n if (usage.cacheWriteInputTokens != null) span.setAttribute('neatlogs.llm.token_count.cache_write', usage.cacheWriteInputTokens);\n}\n\nfunction wrapConverseStream(response: any, span: Span): any {\n const stream = response?.stream;\n if (!stream || typeof stream[Symbol.asyncIterator] !== 'function') {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n }\n\n const originalIterator = stream[Symbol.asyncIterator].bind(stream);\n const textParts: string[] = [];\n const toolCalls: Record<number, { id: string; name: string; arguments: string }> = {};\n let finishReason = '';\n let usage: any = null;\n\n const wrappedStream = {\n [Symbol.asyncIterator]() {\n const iterator = originalIterator();\n return {\n async next(): Promise<IteratorResult<any>> {\n try {\n const result = await iterator.next();\n if (result.done) {\n finalizeConverseStream(span, textParts, toolCalls, finishReason, usage);\n return result;\n }\n const ev = result.value;\n const delta = ev?.contentBlockDelta?.delta;\n if (delta?.text) textParts.push(delta.text);\n if (delta?.toolUse?.input) {\n const idx = ev.contentBlockDelta.contentBlockIndex ?? 0;\n toolCalls[idx] = toolCalls[idx] ?? { id: '', name: '', arguments: '' };\n toolCalls[idx].arguments += delta.toolUse.input;\n }\n const startBlk = ev?.contentBlockStart?.start?.toolUse;\n if (startBlk) {\n const idx = ev.contentBlockStart.contentBlockIndex ?? 0;\n toolCalls[idx] = toolCalls[idx] ?? { id: '', name: '', arguments: '' };\n toolCalls[idx].name = startBlk.name ?? '';\n toolCalls[idx].id = startBlk.toolUseId ?? '';\n }\n if (ev?.messageStop?.stopReason) finishReason = ev.messageStop.stopReason;\n if (ev?.metadata?.usage) usage = ev.metadata.usage;\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n }\n },\n async return(value?: any): Promise<IteratorResult<any>> {\n finalizeConverseStream(span, textParts, toolCalls, finishReason, usage);\n return iterator.return?.(value) ?? { done: true, value: undefined };\n },\n };\n },\n };\n\n response.stream = wrappedStream;\n return response;\n}\n\nfunction finalizeConverseStream(\n span: Span,\n textParts: string[],\n toolCalls: Record<number, { id: string; name: string; arguments: string }>,\n finishReason: string,\n usage: any,\n): void {\n const full = textParts.join('');\n if (full) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', full);\n }\n let j = 0;\n for (const tc of Object.values(toolCalls)) {\n if (tc.id) span.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, tc.id);\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.name);\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, tc.arguments);\n j++;\n }\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(finishReason));\n setConverseUsage(span, usage);\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\n// ---------------------------------------------------------------------------\n// InvokeModel API (vendor-specific body formats)\n// ---------------------------------------------------------------------------\n\nfunction isEmbeddingModel(modelId: any): boolean {\n return String(modelId ?? '').toLowerCase().includes('embed');\n}\n\nfunction tracedInvokeModel(\n originalSend: (...a: any[]) => any,\n command: any,\n input: any,\n rest: any[],\n isStream: boolean,\n): any {\n const vendor = vendorFromModel(input?.modelId);\n const isEmbedding = !isStream && isEmbeddingModel(input?.modelId);\n const bodyIn = decodeBody(input?.body);\n\n let span: Span;\n if (isEmbedding) {\n span = getProviderTracer(TRACER_NAME).startSpan('bedrock.invoke_model', {\n attributes: {\n 'neatlogs.span.kind': 'EMBEDDING',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.embedding.model_name': String(input?.modelId ?? ''),\n },\n }, otelContext.active());\n const text = bodyIn?.inputText ?? bodyIn?.texts ?? bodyIn?.input_text;\n if (text) {\n span.setAttribute('neatlogs.embedding.text', (typeof text === 'string' ? text : safeStringify(text)));\n }\n } else {\n span = startSpan(\n isStream ? 'bedrock.invoke_model_with_response_stream' : 'bedrock.invoke_model',\n input?.modelId,\n isStream,\n );\n setInvokeInput(span, vendor, bodyIn);\n }\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => originalSend(command, ...rest));\n\n return promise.then(\n (response: any) => {\n if (isStream) {\n return wrapInvokeStream(response, span, vendor);\n }\n try {\n if (isEmbedding) {\n finalizeInvokeEmbedding(span, decodeBody(response?.body));\n } else {\n finalizeInvoke(span, vendor, decodeBody(response?.body));\n }\n } catch {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n }\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n}\n\nfunction finalizeInvokeEmbedding(span: Span, body: any): void {\n const emb = body?.embedding;\n const embs = body?.embeddings;\n if (Array.isArray(emb)) {\n span.setAttribute('neatlogs.embedding.count', 1);\n span.setAttribute('neatlogs.embedding.dimensions', emb.length);\n } else if (Array.isArray(embs) && embs.length) {\n span.setAttribute('neatlogs.embedding.count', embs.length);\n if (Array.isArray(embs[0])) span.setAttribute('neatlogs.embedding.dimensions', embs[0].length);\n }\n if (body?.inputTextTokenCount != null) {\n span.setAttribute('neatlogs.llm.token_count.prompt', body.inputTextTokenCount);\n span.setAttribute('neatlogs.embedding.token_count', body.inputTextTokenCount);\n }\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\nfunction decodeBody(body: any): any {\n try {\n if (body == null) return {};\n if (typeof body === 'string') return JSON.parse(body);\n // Uint8Array (AWS SDK v3 returns the response body as bytes)\n if (body instanceof Uint8Array) return JSON.parse(new TextDecoder().decode(body));\n if (typeof body === 'object' && typeof body.byteLength === 'number') {\n return JSON.parse(new TextDecoder().decode(body));\n }\n if (typeof body === 'object') return body;\n } catch {\n /* fall through */\n }\n return {};\n}\n\nfunction setInvokeInput(span: Span, vendor: string, body: any): void {\n let idx = 0;\n if (body?.system) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'system');\n span.setAttribute(\n `neatlogs.llm.input_messages.${idx}.content`,\n typeof body.system === 'string' ? body.system : safeStringify(body.system),\n );\n idx++;\n }\n if (Array.isArray(body?.messages)) {\n for (const msg of body.messages) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, msg?.role ?? 'user');\n span.setAttribute(\n `neatlogs.llm.input_messages.${idx}.content`,\n typeof msg?.content === 'string' ? msg.content : safeStringify(msg?.content),\n );\n idx++;\n }\n } else if (body?.prompt) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, String(body.prompt));\n } else if (body?.inputText) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, String(body.inputText));\n }\n\n if (body?.temperature != null) span.setAttribute('neatlogs.llm.temperature', body.temperature);\n if (body?.top_p != null) span.setAttribute('neatlogs.llm.top_p', body.top_p);\n const maxTokens = body?.max_tokens ?? body?.maxTokens ?? body?.max_tokens_to_sample;\n if (maxTokens != null) span.setAttribute('neatlogs.llm.max_tokens', maxTokens);\n const cfg = body?.textGenerationConfig;\n if (cfg) {\n if (cfg.temperature != null) span.setAttribute('neatlogs.llm.temperature', cfg.temperature);\n if (cfg.topP != null) span.setAttribute('neatlogs.llm.top_p', cfg.topP);\n if (cfg.maxTokenCount != null) span.setAttribute('neatlogs.llm.max_tokens', cfg.maxTokenCount);\n }\n}\n\nfunction finalizeInvoke(span: Span, vendor: string, body: any): void {\n let text: string | undefined;\n let promptTokens: number | undefined;\n let completionTokens: number | undefined;\n let finishReason: string | undefined;\n\n if (vendor === 'anthropic') {\n if (Array.isArray(body?.content)) {\n text = body.content.filter((b: any) => b?.type === 'text').map((b: any) => b.text).join('');\n let toolIdx = 0;\n for (const b of body.content) {\n if (b?.type === 'tool_use') {\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.id`, String(b.id ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.name`, String(b.name ?? ''));\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.arguments`, safeStringify(b.input ?? {}));\n toolIdx++;\n }\n }\n } else if (body?.completion != null) {\n text = body.completion;\n }\n promptTokens = body?.usage?.input_tokens;\n completionTokens = body?.usage?.output_tokens;\n finishReason = body?.stop_reason;\n } else if (vendor === 'amazon') {\n const r = Array.isArray(body?.results) ? body.results[0] : undefined;\n if (r) {\n text = r.outputText;\n completionTokens = r.tokenCount;\n finishReason = r.completionReason;\n }\n promptTokens = body?.inputTextTokenCount;\n } else if (vendor === 'meta') {\n text = body?.generation;\n promptTokens = body?.prompt_token_count;\n completionTokens = body?.generation_token_count;\n finishReason = body?.stop_reason;\n } else if (vendor === 'cohere') {\n const g = Array.isArray(body?.generations) ? body.generations[0] : undefined;\n if (g) {\n text = g.text;\n finishReason = g.finish_reason;\n }\n } else {\n text = body?.generation ?? body?.completion ?? body?.outputText;\n }\n\n if (text) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', String(text));\n }\n if (promptTokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', promptTokens);\n if (completionTokens != null) span.setAttribute('neatlogs.llm.token_count.completion', completionTokens);\n if (promptTokens != null && completionTokens != null) {\n span.setAttribute('neatlogs.llm.token_count.total', promptTokens + completionTokens);\n }\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(finishReason));\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\nfunction wrapInvokeStream(response: any, span: Span, vendor: string): any {\n const body = response?.body;\n if (!body || typeof body[Symbol.asyncIterator] !== 'function') {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n }\n\n const originalIterator = body[Symbol.asyncIterator].bind(body);\n const textParts: string[] = [];\n let promptTokens: number | undefined;\n let completionTokens: number | undefined;\n let finishReason: string | undefined;\n\n const finalize = () => {\n const full = textParts.join('');\n if (full) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', full);\n }\n if (promptTokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', promptTokens);\n if (completionTokens != null) span.setAttribute('neatlogs.llm.token_count.completion', completionTokens);\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(finishReason));\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n };\n\n const wrappedBody = {\n [Symbol.asyncIterator]() {\n const iterator = originalIterator();\n return {\n async next(): Promise<IteratorResult<any>> {\n try {\n const result = await iterator.next();\n if (result.done) {\n finalize();\n return result;\n }\n const data = decodeBody(result.value?.chunk?.bytes);\n if (data?.type === 'content_block_delta') {\n textParts.push(data?.delta?.text ?? '');\n } else if (data?.type === 'message_delta') {\n if (data?.delta?.stop_reason) finishReason = data.delta.stop_reason;\n if (data?.usage?.output_tokens != null) completionTokens = data.usage.output_tokens;\n }\n if (data?.outputText) textParts.push(data.outputText);\n if (data?.generation) textParts.push(data.generation);\n const metrics = data?.['amazon-bedrock-invocationMetrics'];\n if (metrics) {\n promptTokens = metrics.inputTokenCount ?? promptTokens;\n completionTokens = metrics.outputTokenCount ?? completionTokens;\n }\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n }\n },\n async return(value?: any): Promise<IteratorResult<any>> {\n finalize();\n return iterator.return?.(value) ?? { done: true, value: undefined };\n },\n };\n },\n };\n\n response.body = wrappedBody;\n return response;\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nfunction safeStringify(value: unknown): string {\n try {\n return typeof value === 'string' ? value : JSON.stringify(value);\n } catch {\n return '';\n }\n}\n\nfunction recordError(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 span.end();\n}\n","/**\n * Auto-root for direct-provider wrappers.\n *\n * The backend only renders a trace once it contains a *parentless* span of a\n * root-eligible kind (WORKFLOW / CHAIN / AGENT / MCP_TOOL). Direct-provider\n * wrappers (wrapOpenAI, wrapAnthropic, wrapBedrock, ...) only ever emit\n * non-root spans (LLM / EMBEDDING / TOOL). So a bare\n * `const client = wrapOpenAI(new OpenAI())` with no surrounding `span()` /\n * `trace()` produces an orphan span and the trace never renders.\n *\n * `getProviderTracer(name)` returns a Tracer facade used *only* by those\n * direct-provider wrappers: when `startSpan` would otherwise produce a\n * parentless, non-root span, it transparently opens a WORKFLOW root (named\n * after the configured `workflowName`) and ends it when the provider span\n * ends. Every wrapper path — non-streaming, streaming finalize, error —\n * funnels through `span.end()`, so wrapping `end()` covers them all with no\n * changes to the wrappers' streaming code.\n *\n * Framework wrappers (langchain, mastra, openai-agents, ai-sdk, ...) keep\n * using `trace.getTracer(...)` directly — they already emit their own root and\n * thread context explicitly, so auto-root must never fire for them.\n */\n\nimport {\n trace as otelTrace,\n context as otelContext,\n type Tracer,\n type Span,\n type Context,\n type SpanOptions,\n} from '@opentelemetry/api';\n\nimport { getSessionConfig } from './context.js';\n\n// A parentless span of one of these kinds already satisfies the backend's\n// root requirement, so it must NOT be wrapped in another root.\nconst ROOT_KINDS = new Set(['workflow', 'chain', 'agent', 'mcp_tool']);\n\nfunction autoRootEnabled(): boolean {\n const val = (process.env.NEATLOGS_AUTO_ROOT ?? '').trim().toLowerCase();\n return !['false', '0', 'no', 'off'].includes(val);\n}\n\nfunction resolveRootWorkflowName(): string {\n try {\n const name = getSessionConfig()?.workflowName;\n if (typeof name === 'string' && name.trim()) return name;\n } catch {\n /* ignore */\n }\n return 'workflow';\n}\n\n/**\n * Wrap a provider span so that ending it also ends the auto-created WORKFLOW\n * root. A Proxy keeps this transparent across OTel versions: every property /\n * method except `end` passes straight through to the child span.\n */\nfunction wrapSpanWithRoot(child: Span, root: Span): Span {\n let ended = false;\n return new Proxy(child, {\n get(target, prop, _receiver) {\n if (prop === 'end') {\n return (...args: any[]): void => {\n if (ended) return;\n ended = true;\n try {\n (target.end as (...a: any[]) => void)(...args);\n } finally {\n try {\n root.end();\n } catch {\n /* ignore */\n }\n }\n };\n }\n const value = Reflect.get(target, prop, target);\n return typeof value === 'function' ? value.bind(target) : value;\n },\n });\n}\n\n/**\n * Self-root helper for callback/event-driven handlers (LangChain, etc.).\n *\n * A callback handler builds its own parent context per run-id rather than going\n * through {@link AutoRootTracer}. When a run BEGINS with a non-root kind (a bare\n * `llm.invoke()` fires the LLM callback with no chain above it; a standalone\n * tool/retriever similarly), the span it creates is parentless and non-root, so\n * the backend can't anchor the trace and it never renders. Call this when there\n * is no LangChain parent: if the kind is non-root and nothing is actively\n * recording in `baseCtx`, it opens a WORKFLOW root and returns it plus the\n * child context to create the span in. The caller MUST end the returned\n * `root` after the child span ends (see {@link endAutoRoot}).\n *\n * Returns `{ root, ctx }` when a root was opened, or `{ root: undefined, ctx: baseCtx }`\n * when no auto-root is needed (root-eligible kind, already-recording parent, or\n * disabled).\n */\nexport function maybeOpenAutoRoot(\n tracer: Tracer,\n kind: string,\n baseCtx: Context,\n): { root: Span | undefined; ctx: Context } {\n const k = String(kind ?? '').toLowerCase();\n const existing = otelTrace.getSpan(baseCtx);\n if (\n !autoRootEnabled() ||\n ROOT_KINDS.has(k) ||\n (existing !== undefined && existing.isRecording())\n ) {\n return { root: undefined, ctx: baseCtx };\n }\n const root = tracer.startSpan(\n resolveRootWorkflowName(),\n { attributes: { 'neatlogs.span.kind': 'workflow', 'neatlogs.auto_root': true } },\n baseCtx,\n );\n return { root, ctx: otelTrace.setSpan(baseCtx, root) };\n}\n\n/** End an auto-root opened by {@link maybeOpenAutoRoot}. Safe on undefined. */\nexport function endAutoRoot(root: Span | undefined): void {\n if (!root) return;\n try {\n root.end();\n } catch {\n /* ignore */\n }\n}\n\nclass AutoRootTracer implements Tracer {\n constructor(private readonly _tracer: Tracer) {}\n\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n const kind = String(\n (options?.attributes as Record<string, unknown> | undefined)?.[\n 'neatlogs.span.kind'\n ] ?? '',\n ).toLowerCase();\n\n const ctx = context ?? otelContext.active();\n const parent = otelTrace.getSpan(ctx);\n const needsRoot =\n autoRootEnabled() &&\n !ROOT_KINDS.has(kind) &&\n !(parent !== undefined && parent.isRecording());\n\n if (!needsRoot) {\n return this._tracer.startSpan(name, options, context);\n }\n\n const root = this._tracer.startSpan(\n resolveRootWorkflowName(),\n { attributes: { 'neatlogs.span.kind': 'workflow', 'neatlogs.auto_root': true } },\n ctx,\n );\n const childCtx = otelTrace.setSpan(ctx, root);\n const child = this._tracer.startSpan(name, options, childCtx);\n return wrapSpanWithRoot(child, root);\n }\n\n // startActiveSpan is used by traceTool (callback-scoped, always under an\n // active span in practice) — pass straight through, no auto-root.\n startActiveSpan = ((...args: any[]) =>\n (this._tracer.startActiveSpan as (...a: any[]) => any)(\n ...args,\n )) as Tracer['startActiveSpan'];\n}\n\n/**\n * Tracer for direct-provider wrappers (wrapOpenAI, wrapAnthropic, ...).\n * Identical to `trace.getTracer(name)` but adds transparent auto-root so a\n * bare `wrapOpenAI(new OpenAI())` renders a trace without a manual `span()` /\n * `trace()` wrapper. Do NOT use for framework wrappers.\n */\nexport function getProviderTracer(name: string): Tracer {\n return new AutoRootTracer(otelTrace.getTracer(name));\n}\n","/**\n * Context wrapper for manual span creation.\n *\n * Provides the `trace()` function — the TypeScript equivalent of the Python\n * `trace()` context manager. Creates an OTel span, sets prompt template/variable\n * context, and executes the user callback within the span.\n *\n * @example\n * ```typescript\n * await trace({ name: 'my-trace' }, async (span) => {\n * // user code runs here with the span active\n * });\n * ```\n */\n\nimport {\n trace as otelTrace,\n context as otelContext,\n createContextKey,\n ROOT_CONTEXT,\n SpanStatusCode,\n type Span,\n} from '@opentelemetry/api';\nimport { PromptContext, UserPromptContext, PromptTemplate, UserPromptTemplate } from '../prompt/template.js';\nimport { registerMask } from './mask.js';\n\nimport { getLogger } from './logger.js';\nimport { safeJsonDumps, serializeObj } from '../decorators/base.js';\nimport type { TraceOptions, MaskFunction } from '../types.js';\n\nconst logger = getLogger();\n\n// ---------------------------------------------------------------------------\n// Module-level session config (set by init.ts via _setSessionConfig)\n// ---------------------------------------------------------------------------\n\nlet _sessionConfig: Record<string, any> = {};\n\n/**\n * Set the session configuration. Called by init() during SDK setup.\n * @internal\n */\nexport function _setSessionConfig(config: Record<string, any>): void {\n _sessionConfig = config;\n}\n\n/**\n * Get a copy of the current session configuration.\n */\nexport function getSessionConfig(): Record<string, any> {\n return { ..._sessionConfig };\n}\n\n// ---------------------------------------------------------------------------\n// OTel context keys for prompt data propagation\n// ---------------------------------------------------------------------------\n\nexport const PROMPT_VARIABLES_KEY = createContextKey('neatlogs.prompt_variables');\nexport const PROMPT_TEMPLATE_KEY = createContextKey('neatlogs.prompt_template');\nexport const PROMPT_VERSION_KEY = createContextKey('neatlogs.prompt_version');\nexport const USER_PROMPT_TEMPLATE_KEY = createContextKey('neatlogs.user_prompt_template');\nexport const USER_PROMPT_VARIABLES_KEY = createContextKey('neatlogs.user_prompt_variables');\n\n// ---------------------------------------------------------------------------\n// Known TraceOptions keys (not forwarded as extra span attributes)\n// ---------------------------------------------------------------------------\n\nconst KNOWN_OPTION_KEYS = new Set([\n 'name',\n 'kind',\n 'input',\n 'promptTemplate',\n 'promptVariables',\n 'userPromptTemplate',\n 'userPromptVariables',\n 'version',\n 'mask',\n 'attributes',\n]);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Set standard and extra attributes on a span.\n * @internal\n */\nexport function _setSpanAttributes(\n span: Span,\n kind: string | undefined,\n attributes: Record<string, any>,\n): void {\n span.setAttribute('neatlogs.internal', true);\n span.setAttribute('openinference.span.kind', kind ?? 'CHAIN');\n\n for (const [key, value] of Object.entries(attributes)) {\n span.setAttribute(key, value);\n }\n}\n\n/**\n * After the user callback completes, capture prompt variables that were\n * set by PromptTemplate.compile() / UserPromptTemplate.compile() and\n * record them as span attributes.\n * @internal\n */\nexport function _finalizePromptCapture(\n span: Span,\n isPromptTemplateObj: boolean,\n isUserPromptTemplateObj: boolean,\n): void {\n if (isPromptTemplateObj) {\n const capturedVars = PromptContext.getVariables();\n if (capturedVars) {\n span.setAttribute(\n 'llm.prompt_template_variables',\n JSON.stringify(capturedVars),\n );\n logger.debug(\n `[trace] Auto-captured variables from PromptContext: ${Object.keys(capturedVars).join(', ')}`,\n );\n }\n }\n\n if (isUserPromptTemplateObj) {\n const capturedUserVars = UserPromptContext.getVariables();\n if (capturedUserVars) {\n span.setAttribute(\n 'llm.user_prompt_template_variables',\n JSON.stringify(capturedUserVars),\n );\n logger.debug(\n `[trace] Auto-captured variables from UserPromptContext: ${Object.keys(capturedUserVars).join(', ')}`,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main trace() function\n// ---------------------------------------------------------------------------\n\n/**\n * Async callback wrapper for manual span creation with prompt tracking.\n *\n * Creates an OTel span, optionally sets prompt template/variable context,\n * and executes the provided callback within the span.\n *\n * **Session-Aware Trace Creation:**\n * - If `session_id` is set in init() AND no active parent span exists,\n * this creates a NEW root trace (for multi-turn conversations).\n * - Otherwise, creates a normal child span within the existing trace.\n *\n * @param options - Trace configuration options\n * @param fn - Callback that receives the active span\n * @returns The return value of the callback\n *\n * @example\n * ```typescript\n * // Basic usage\n * await trace({ name: 'my-pipeline' }, async (span) => {\n * await step1();\n * await step2();\n * });\n *\n * // With prompt template\n * const template = new PromptTemplate('Hello {{name}}');\n * await trace({ name: 'prompt', promptTemplate: template }, async (span) => {\n * const rendered = template.compile({ name: 'world' });\n * // ...\n * });\n * ```\n */\nexport async function trace<T>(\n options: TraceOptions,\n fn: (span: Span) => T | Promise<T>,\n): Promise<T> {\n const {\n name,\n kind,\n input,\n promptTemplate,\n promptVariables,\n userPromptTemplate,\n userPromptVariables,\n version,\n mask,\n attributes: explicitAttributes,\n ...extraOptions\n } = options;\n\n const sessionConfig = getSessionConfig();\n const sessionId = sessionConfig.sessionId;\n\n // Determine whether we are inside an existing active trace\n const currentSpan = otelTrace.getSpan(otelContext.active());\n const isInActiveTrace = currentSpan !== undefined && currentSpan.isRecording();\n const shouldCreateRootTrace = !!sessionId && !isInActiveTrace;\n\n // ---------------------------------------------------------------------------\n // Process prompt templates\n // ---------------------------------------------------------------------------\n\n let templateString: string | undefined;\n let isPromptTemplateObj = false;\n\n if (promptTemplate !== undefined) {\n if (promptTemplate instanceof PromptTemplate) {\n isPromptTemplateObj = true;\n const t = promptTemplate.template;\n templateString = typeof t === 'string' ? t : JSON.stringify(t);\n logger.debug(\n `[trace] Using PromptTemplate object with variables: ${promptTemplate.variables.join(', ')}`,\n );\n } else if (typeof promptTemplate === 'string') {\n templateString = promptTemplate;\n } else {\n const t = promptTemplate.template;\n templateString = typeof t === 'string' ? t : JSON.stringify(t);\n }\n }\n\n let userTemplateString: string | undefined;\n let isUserPromptTemplateObj = false;\n\n if (userPromptTemplate !== undefined) {\n if (userPromptTemplate instanceof UserPromptTemplate) {\n isUserPromptTemplateObj = true;\n const t = userPromptTemplate.template;\n userTemplateString = typeof t === 'string' ? t : JSON.stringify(t);\n logger.debug(\n `[trace] Using UserPromptTemplate object with variables: ${userPromptTemplate.variables.join(', ')}`,\n );\n } else if (typeof userPromptTemplate === 'string') {\n userTemplateString = userPromptTemplate;\n } else {\n const t = userPromptTemplate.template;\n userTemplateString = typeof t === 'string' ? t : JSON.stringify(t);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Build OTel context with prompt values\n // ---------------------------------------------------------------------------\n\n let ctx = otelContext.active();\n\n const variablesJson = promptVariables ? JSON.stringify(promptVariables) : undefined;\n const userVariablesJson = userPromptVariables ? JSON.stringify(userPromptVariables) : undefined;\n\n if (variablesJson) {\n ctx = ctx.setValue(PROMPT_VARIABLES_KEY, variablesJson);\n logger.debug(`[trace] Set neatlogs.prompt_variables in context: ${variablesJson}`);\n }\n if (templateString) {\n ctx = ctx.setValue(PROMPT_TEMPLATE_KEY, templateString);\n logger.debug(`[trace] Set neatlogs.prompt_template in context: ${templateString}`);\n }\n if (userVariablesJson) {\n ctx = ctx.setValue(USER_PROMPT_VARIABLES_KEY, userVariablesJson);\n logger.debug(`[trace] Set neatlogs.user_prompt_variables in context: ${userVariablesJson}`);\n }\n if (userTemplateString) {\n ctx = ctx.setValue(USER_PROMPT_TEMPLATE_KEY, userTemplateString);\n logger.debug(`[trace] Set neatlogs.user_prompt_template in context: ${userTemplateString}`);\n }\n if (version) {\n ctx = ctx.setValue(PROMPT_VERSION_KEY, version);\n logger.debug(`[trace] Set neatlogs.prompt_version in context: ${version}`);\n }\n\n // ---------------------------------------------------------------------------\n // Collect extra attributes (non-standard option keys)\n // ---------------------------------------------------------------------------\n\n const extraAttributes: Record<string, any> = { ...(explicitAttributes ?? {}) };\n for (const [key, value] of Object.entries(extraOptions)) {\n if (!KNOWN_OPTION_KEYS.has(key)) {\n extraAttributes[key] = value;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Create span and execute callback\n // ---------------------------------------------------------------------------\n\n const tracer = otelTrace.getTracer('neatlogs.trace');\n\n const spanCallback = async (span: Span): Promise<T> => {\n _setSpanAttributes(span, kind, extraAttributes);\n\n if (input !== undefined && input !== null) {\n span.setAttribute('input.value', safeJsonDumps(serializeObj(input)));\n }\n\n if (mask) {\n const maskId = registerMask(mask);\n span.setAttribute('neatlogs.mask_id', maskId);\n }\n\n try {\n const result: T = await fn(span);\n\n _finalizePromptCapture(span, isPromptTemplateObj, isUserPromptTemplateObj);\n\n if (result !== undefined && result !== null) {\n const spanAttrs = (span as any).attributes ?? (span as any)._attributes;\n const hasOutput = spanAttrs && (\n 'output.value' in spanAttrs || 'neatlogs.output.value' in spanAttrs\n );\n if (!hasOutput) {\n span.setAttribute('output.value', safeJsonDumps(serializeObj(result)));\n }\n }\n\n return result;\n } catch (error) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n if (isPromptTemplateObj) {\n PromptContext.clear();\n }\n if (isUserPromptTemplateObj) {\n UserPromptContext.clear();\n }\n span.end();\n }\n };\n\n if (shouldCreateRootTrace) {\n logger.debug(`[trace] Creating NEW root trace '${name}' (sessionId=${sessionId})`);\n return tracer.startActiveSpan(name, {}, ROOT_CONTEXT, spanCallback);\n } else {\n logger.debug(`[trace] Creating child span '${name}'`);\n return tracer.startActiveSpan(name, {}, ctx, spanCallback);\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { PromptMessage } from '../types.js';\n\n// ---------------------------------------------------------------------------\n// Async-local context for system prompts\n// ---------------------------------------------------------------------------\n\ninterface PromptContextData {\n template: string;\n variables: Record<string, any>;\n}\n\nconst _promptStorage = new AsyncLocalStorage<PromptContextData>();\n\n/**\n * Manages system prompt metadata in async-local context for automatic tracing.\n */\nexport class PromptContext {\n /**\n * Store system prompt template and variables in context.\n */\n static set(template: string, variables: Record<string, any>): void {\n // enterWith mutates the current async context in-place\n _promptStorage.enterWith({ template, variables });\n }\n\n /**\n * Retrieve system prompt template from context.\n */\n static getTemplate(): string | undefined {\n return _promptStorage.getStore()?.template;\n }\n\n /**\n * Retrieve system prompt variables from context.\n */\n static getVariables(): Record<string, any> | undefined {\n return _promptStorage.getStore()?.variables;\n }\n\n /**\n * Clear system prompt context.\n */\n static clear(): void {\n _promptStorage.enterWith(undefined as unknown as PromptContextData);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Async-local context for user prompts\n// ---------------------------------------------------------------------------\n\nconst _userPromptStorage = new AsyncLocalStorage<PromptContextData>();\n\n/**\n * Manages user/human prompt metadata in async-local context for automatic tracing.\n */\nexport class UserPromptContext {\n /**\n * Store user prompt template and variables in context.\n */\n static set(template: string, variables: Record<string, any>): void {\n _userPromptStorage.enterWith({ template, variables });\n }\n\n /**\n * Retrieve user prompt template from context.\n */\n static getTemplate(): string | undefined {\n return _userPromptStorage.getStore()?.template;\n }\n\n /**\n * Retrieve user prompt variables from context.\n */\n static getVariables(): Record<string, any> | undefined {\n return _userPromptStorage.getStore()?.variables;\n }\n\n /**\n * Clear user prompt context.\n */\n static clear(): void {\n _userPromptStorage.enterWith(undefined as unknown as PromptContextData);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Shared context setter type for the base template class\n// ---------------------------------------------------------------------------\n\ninterface ContextSetter {\n set(template: string, variables: Record<string, any>): void;\n}\n\n// ---------------------------------------------------------------------------\n// BasePromptTemplate — shared logic for system and user prompts\n// ---------------------------------------------------------------------------\n\nconst VARIABLE_PATTERN = /\\{\\{(\\w+)\\}\\}/g;\n\n/**\n * Base class for prompt templates with `{{variable}}` placeholders.\n *\n * Extracts variables, compiles templates, and renders strings.\n * Subclasses only need to specify the context class and display name.\n */\nabstract class BasePromptTemplate {\n protected readonly _template: string | PromptMessage[];\n protected readonly _variables: string[];\n\n /**\n * @param template - Either a string with `{{variable}}` placeholders or\n * an array of `PromptMessage` objects whose `content` fields contain placeholders.\n */\n constructor(template: string | PromptMessage[]) {\n this._template = template;\n this._variables = this._extractVariables();\n }\n\n /** List of unique variable names found in this template. */\n get variables(): string[] {\n return this._variables;\n }\n\n /** The raw template (string or message array). */\n get template(): string | PromptMessage[] {\n return this._template;\n }\n\n /** The context class to store template/variables for automatic tracing. */\n protected abstract get _contextSetter(): ContextSetter;\n\n /** Display name for toString(). */\n protected abstract get _displayName(): string;\n\n /**\n * Compile the prompt template with the given variables.\n *\n * @param variables - Key/value pairs to substitute for `{{key}}` placeholders.\n * @returns The rendered string or rendered message array.\n * @throws {Error} If any required variables are missing.\n */\n compile(variables?: Record<string, any>): string | PromptMessage[] {\n const vars = variables ?? {};\n\n const missing = this._variables.filter((v) => !(v in vars));\n if (missing.length > 0) {\n throw new Error(\n `Missing required variables: ${missing.join(', ')}. Template requires: ${this._variables.join(', ')}`,\n );\n }\n\n this._contextSetter.set(\n typeof this._template === 'string'\n ? this._template\n : this._template.map((msg) => `${msg.role}: ${msg.content}`).join('\\n'),\n vars,\n );\n\n if (typeof this._template === 'string') {\n return this._renderString(this._template, vars);\n }\n\n return this._template.map((msg) => ({\n role: msg.role,\n content: this._renderString(msg.content, vars),\n }));\n }\n\n /**\n * Replace `{{key}}` placeholders in a string with the corresponding values.\n */\n _renderString(text: string, variables: Record<string, any>): string {\n let result = text;\n for (const [key, value] of Object.entries(variables)) {\n result = result.replaceAll(`{{${key}}}`, String(value));\n }\n return result;\n }\n\n toString(): string {\n if (typeof this._template === 'string') {\n return this._template.length > 50\n ? `${this._displayName}('${this._template.slice(0, 50)}...')`\n : `${this._displayName}('${this._template}')`;\n }\n return `${this._displayName}(${this._template.length} messages, variables=${JSON.stringify(this._variables)})`;\n }\n\n // ---- private ----\n\n private _extractVariables(): string[] {\n if (typeof this._template === 'string') {\n return [...new Set(Array.from(this._template.matchAll(VARIABLE_PATTERN), (m) => m[1]))];\n }\n\n const found: string[] = [];\n for (const msg of this._template) {\n if (msg.content) {\n for (const match of msg.content.matchAll(VARIABLE_PATTERN)) {\n found.push(match[1]);\n }\n }\n }\n return [...new Set(found)];\n }\n}\n\n// ---------------------------------------------------------------------------\n// PromptTemplate — system/AI instruction prompt\n// ---------------------------------------------------------------------------\n\n/**\n * Template for the system/AI instruction prompt with `{{variable}}` placeholders.\n */\nexport class PromptTemplate extends BasePromptTemplate {\n protected get _contextSetter(): ContextSetter {\n return PromptContext;\n }\n\n protected get _displayName(): string {\n return 'PromptTemplate';\n }\n}\n\n// ---------------------------------------------------------------------------\n// UserPromptTemplate — user/human turn prompt\n// ---------------------------------------------------------------------------\n\n/**\n * Template for the user/human turn prompt with `{{variable}}` placeholders.\n *\n * Identical to {@link PromptTemplate} but stores context in {@link UserPromptContext}.\n */\nexport class UserPromptTemplate extends BasePromptTemplate {\n protected get _contextSetter(): ContextSetter {\n return UserPromptContext;\n }\n\n protected get _displayName(): string {\n return 'UserPromptTemplate';\n }\n}\n","/**\n * Centralized logging configuration for Neatlogs SDK.\n * Provides structured logging with configurable levels.\n */\n\ntype LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE';\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n DEBUG: 0,\n INFO: 1,\n WARN: 2,\n ERROR: 3,\n NONE: 4,\n};\n\nlet _logLevel: LogLevel = 'INFO';\nlet _disabled = false;\n\nfunction _getConfiguredLevel(): LogLevel {\n const envLevel = process.env.NEATLOGS_LOG_LEVEL?.toUpperCase();\n if (envLevel && envLevel in LOG_LEVELS) {\n return envLevel as LogLevel;\n }\n return 'INFO';\n}\n\n// Initialize from env on first import\n_logLevel = _getConfiguredLevel();\n\nexport function getLogger() {\n return {\n debug(message: string, ...args: any[]) {\n if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.DEBUG) {\n console.debug(`[neatlogs] ${message}`, ...args);\n }\n },\n info(message: string, ...args: any[]) {\n if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.INFO) {\n console.info(`[neatlogs] ${message}`, ...args);\n }\n },\n warn(message: string, ...args: any[]) {\n if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.WARN) {\n console.warn(`[neatlogs] ${message}`, ...args);\n }\n },\n error(message: string, ...args: any[]) {\n if (!_disabled && LOG_LEVELS[_logLevel] <= LOG_LEVELS.ERROR) {\n console.error(`[neatlogs] ${message}`, ...args);\n }\n },\n };\n}\n\nexport function setLogLevel(level: LogLevel): void {\n _logLevel = level;\n}\n\nexport function enableDebugLogging(): void {\n _logLevel = 'DEBUG';\n}\n\nexport function disableLogging(): void {\n _disabled = true;\n}\n\nexport function enableLogging(): void {\n _disabled = false;\n}\n","/**\n * PII masking support for Neatlogs spans.\n *\n * Users supply a callable that receives the full span dict and returns\n * the (possibly modified) span dict. Return null to drop the span entirely.\n */\n\nimport type { MaskFunction } from '../types.js';\nimport { getLogger } from './logger.js';\n\nconst logger = getLogger();\n\n/** Module-level registry: key -> mask function */\nconst _MASK_REGISTRY = new Map<string, MaskFunction>();\n\nlet _nextId = 0;\n\n/**\n * Register a mask function and return its lookup key.\n */\nexport function registerMask(fn: MaskFunction): string {\n const key = String(++_nextId);\n _MASK_REGISTRY.set(key, fn);\n return key;\n}\n\n/**\n * Apply the effective mask function to span data.\n *\n * Per-span mask (stored in attributes[\"neatlogs.mask_id\"]) takes\n * precedence over the global mask. Returns the (possibly modified) dict.\n */\nexport function applyMask(\n spanData: Record<string, any>,\n globalMask: MaskFunction | null | undefined,\n): Record<string, any> | null {\n const maskId = spanData?.attributes?.['neatlogs.mask_id'];\n let maskFn: MaskFunction | undefined | null = null;\n\n if (maskId) {\n maskFn = _MASK_REGISTRY.get(String(maskId)) ?? null;\n }\n\n if (!maskFn) {\n maskFn = globalMask ?? null;\n }\n\n if (!maskFn) {\n return spanData;\n }\n\n try {\n const result = maskFn(spanData);\n // null means \"drop this span entirely\"; undefined means \"keep original\"\n if (result === null) return null;\n return result !== undefined ? result : spanData;\n } catch (exc) {\n logger.warn(\n `mask callable raised an exception for span '${spanData?.name}': ${exc} — original span data will be exported unchanged.`,\n );\n return spanData;\n }\n}\n\n/**\n * Clear all registered masks. Used for testing.\n * @internal\n */\nexport function _clearMaskRegistry(): void {\n _MASK_REGISTRY.clear();\n _nextId = 0;\n}\n","/**\n * Core span decoration utilities.\n * Provides the low-level wrapping logic used by span() and Span().\n */\n\nimport { trace, SpanStatusCode, type Span as OtelSpan } from '@opentelemetry/api';\nimport { getLogger } from '../core/logger.js';\nimport { registerMask } from '../core/mask.js';\nimport type { SpanOptions, MaskFunction } from '../types.js';\n\nconst logger = getLogger();\nconst TRACER_NAME = 'neatlogs';\n\n/** Safely serialize any value to JSON string. */\nexport function safeJsonDumps(value: any): string {\n try {\n return JSON.stringify(value, (_key, val) => {\n if (typeof val === 'bigint') return val.toString();\n if (val instanceof Error) return { message: val.message, name: val.name, stack: val.stack };\n if (typeof val === 'function') return `[Function: ${val.name || 'anonymous'}]`;\n return val;\n });\n } catch {\n return String(value);\n }\n}\n\n/** Serialize an object for span attributes. Handles toJSON(), plain objects, primitives. */\nexport function serializeObj(obj: any): any {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean') return obj;\n if (typeof obj.toJSON === 'function') return obj.toJSON();\n if (Array.isArray(obj)) return obj.map(serializeObj);\n if (typeof obj === 'object') {\n const result: Record<string, any> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = serializeObj(value);\n }\n return result;\n }\n return String(obj);\n}\n\n/** Check if content capture is enabled via env var. */\nexport function shouldCaptureContent(): boolean {\n const envVal = process.env.NEATLOGS_TRACE_CONTENT;\n if (envVal === undefined || envVal === '') return true;\n return envVal.toLowerCase() !== 'false' && envVal !== '0';\n}\n\n/** Set common span attributes from options. */\nexport function setCommonSpanAttrs(span: OtelSpan, opts: SpanOptions): void {\n if (opts.kind) {\n span.setAttribute('openinference.span.kind', opts.kind);\n }\n if (opts.internal) {\n span.setAttribute('neatlogs.internal', true);\n }\n if (opts.description) {\n span.setAttribute('neatlogs.description', opts.description);\n }\n if (opts.mask) {\n const maskId = registerMask(opts.mask);\n span.setAttribute('neatlogs.mask_id', maskId);\n }\n}\n\nexport interface DecorateSpanOptions extends SpanOptions {\n /** Override the span name (defaults to function name). */\n spanName?: string;\n /** Post-process callback after the function returns. */\n postprocessResult?: (span: OtelSpan, result: any, boundInputs: Record<string, any>) => void;\n}\n\n/**\n * Core wrapper factory that creates an instrumented version of a function.\n * This is the low-level building block used by span() and Span().\n */\nexport function decorateSpan<TArgs extends any[], TReturn>(\n opts: DecorateSpanOptions,\n fn: (...args: TArgs) => TReturn,\n): (...args: TArgs) => TReturn extends Promise<any> ? TReturn : Promise<Awaited<TReturn>> {\n const tracer = trace.getTracer(TRACER_NAME);\n const spanName = opts.spanName ?? opts.name ?? (fn.name || 'anonymous');\n const captureInput = opts.captureInput !== false;\n const captureOutput = opts.captureOutput !== false;\n const doCapture = shouldCaptureContent();\n\n const wrapped = (...args: TArgs): any => {\n return tracer.startActiveSpan(spanName, (span: OtelSpan) => {\n try {\n // Set common attributes\n setCommonSpanAttrs(span, opts);\n\n // Capture input\n if (captureInput && doCapture && args.length > 0) {\n try {\n const inputValue = args.length === 1 ? serializeObj(args[0]) : args.map(serializeObj);\n span.setAttribute('input.value', safeJsonDumps(inputValue));\n } catch (err) {\n logger.debug(`Failed to capture input: ${err}`);\n }\n }\n\n // Execute the function\n const result = fn(...args);\n\n // Handle async results\n if (result instanceof Promise) {\n return result\n .then((resolved: any) => {\n // Capture output\n if (captureOutput && doCapture) {\n try {\n span.setAttribute('output.value', safeJsonDumps(serializeObj(resolved)));\n } catch (err) {\n logger.debug(`Failed to capture output: ${err}`);\n }\n }\n\n // Post-process\n if (opts.postprocessResult) {\n try {\n const boundInputs = _extractBoundInputs(fn, args);\n opts.postprocessResult(span, resolved, boundInputs);\n } catch (err) {\n logger.debug(`Postprocess failed: ${err}`);\n }\n }\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return resolved;\n })\n .catch((error: any) => {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error?.message ?? String(error),\n });\n span.recordException(error instanceof Error ? error : new Error(String(error)));\n span.end();\n throw error;\n });\n }\n\n // Sync result\n if (captureOutput && doCapture) {\n try {\n span.setAttribute('output.value', safeJsonDumps(serializeObj(result)));\n } catch (err) {\n logger.debug(`Failed to capture output: ${err}`);\n }\n }\n\n if (opts.postprocessResult) {\n try {\n const boundInputs = _extractBoundInputs(fn, args);\n opts.postprocessResult(span, result, boundInputs);\n } catch (err) {\n logger.debug(`Postprocess failed: ${err}`);\n }\n }\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return result;\n } catch (error: any) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error?.message ?? String(error),\n });\n span.recordException(error instanceof Error ? error : new Error(String(error)));\n span.end();\n throw error;\n }\n });\n };\n\n // Preserve function name for debugging\n Object.defineProperty(wrapped, 'name', { value: spanName, configurable: true });\n\n return wrapped as any;\n}\n\n/** Extract named arguments from function call (best-effort). */\nfunction _extractBoundInputs(fn: Function, args: any[]): Record<string, any> {\n const result: Record<string, any> = {};\n // Parse function parameter names from toString()\n const fnStr = fn.toString();\n const match = fnStr.match(/\\(([^)]*)\\)/);\n if (match) {\n const paramNames = match[1]\n .split(',')\n .map((p) => p.trim().replace(/\\s*[:=].*$/, '').replace(/^\\.\\.\\./, ''))\n .filter(Boolean);\n for (let i = 0; i < Math.min(paramNames.length, args.length); i++) {\n result[paramNames[i]] = args[i];\n }\n }\n return result;\n}\n"],"mappings":"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","names":["import_api","import_api","import_api","logger","logger","otelContext","otelTrace","otelContext"]}