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/anthropic.cjs +163 -17
- package/dist/anthropic.cjs.map +1 -1
- package/dist/anthropic.mjs +173 -18
- package/dist/anthropic.mjs.map +1 -1
- package/dist/azure-openai.cjs +163 -17
- package/dist/azure-openai.cjs.map +1 -1
- package/dist/azure-openai.mjs +173 -18
- package/dist/azure-openai.mjs.map +1 -1
- package/dist/bedrock.cjs +167 -21
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.mjs +177 -22
- package/dist/bedrock.mjs.map +1 -1
- package/dist/index.cjs +860 -310
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +778 -225
- package/dist/index.mjs.map +1 -1
- package/dist/langchain.cjs +163 -23
- package/dist/langchain.cjs.map +1 -1
- package/dist/langchain.mjs +173 -24
- package/dist/langchain.mjs.map +1 -1
- package/dist/openai.cjs +163 -17
- package/dist/openai.cjs.map +1 -1
- package/dist/openai.mjs +173 -18
- package/dist/openai.mjs.map +1 -1
- package/dist/opencode-plugin.cjs +530 -5727
- package/dist/opencode-plugin.cjs.map +1 -1
- package/dist/opencode-plugin.d.ts +17 -16
- package/dist/opencode-plugin.mjs +530 -5740
- package/dist/opencode-plugin.mjs.map +1 -1
- package/dist/openrouter-agent.cjs +157 -11
- package/dist/openrouter-agent.cjs.map +1 -1
- package/dist/openrouter-agent.mjs +167 -12
- package/dist/openrouter-agent.mjs.map +1 -1
- package/dist/vertex-ai.cjs +171 -25
- package/dist/vertex-ai.cjs.map +1 -1
- package/dist/vertex-ai.mjs +181 -26
- package/dist/vertex-ai.mjs.map +1 -1
- package/package.json +3 -2
package/dist/azure-openai.cjs
CHANGED
|
@@ -24,7 +24,153 @@ __export(azure_openai_exports, {
|
|
|
24
24
|
wrapAzureOpenAI: () => wrapAzureOpenAI
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(azure_openai_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/azure-openai.ts
|
|
28
174
|
var TRACER_NAME = "neatlogs.azure_openai";
|
|
29
175
|
var PROVIDER = "azure";
|
|
30
176
|
var SYSTEM = "azure";
|
|
@@ -33,7 +179,7 @@ function wrapAzureOpenAI(client) {
|
|
|
33
179
|
}
|
|
34
180
|
function traceTool(name, fn) {
|
|
35
181
|
return async function tracedTool(args) {
|
|
36
|
-
const tracer =
|
|
182
|
+
const tracer = getProviderTracer(TRACER_NAME);
|
|
37
183
|
return tracer.startActiveSpan(
|
|
38
184
|
`tool.${name}`,
|
|
39
185
|
{
|
|
@@ -43,12 +189,12 @@ function traceTool(name, fn) {
|
|
|
43
189
|
"input.value": safeStringify(args)
|
|
44
190
|
}
|
|
45
191
|
},
|
|
46
|
-
|
|
192
|
+
import_api4.context.active(),
|
|
47
193
|
async (span) => {
|
|
48
194
|
try {
|
|
49
195
|
const result = await fn(args);
|
|
50
196
|
span.setAttribute("output.value", safeStringify(result));
|
|
51
|
-
span.setStatus({ code:
|
|
197
|
+
span.setStatus({ code: import_api4.SpanStatusCode.OK });
|
|
52
198
|
return result;
|
|
53
199
|
} catch (err) {
|
|
54
200
|
recordError(span, err);
|
|
@@ -87,7 +233,7 @@ function isNamespace(path) {
|
|
|
87
233
|
}
|
|
88
234
|
function tracedChatCompletionsCreate(original) {
|
|
89
235
|
return function(opts, ...rest) {
|
|
90
|
-
const tracer =
|
|
236
|
+
const tracer = getProviderTracer(TRACER_NAME);
|
|
91
237
|
const model = opts?.model ?? "";
|
|
92
238
|
const messages = opts?.messages ?? [];
|
|
93
239
|
const isStream = opts?.stream === true;
|
|
@@ -99,7 +245,7 @@ function tracedChatCompletionsCreate(original) {
|
|
|
99
245
|
"neatlogs.llm.model_name": model,
|
|
100
246
|
"neatlogs.llm.is_streaming": isStream
|
|
101
247
|
}
|
|
102
|
-
},
|
|
248
|
+
}, import_api4.context.active());
|
|
103
249
|
for (let i = 0; i < messages.length; i++) {
|
|
104
250
|
const msg = messages[i];
|
|
105
251
|
span.setAttribute(`neatlogs.llm.input_messages.${i}.role`, msg.role ?? "");
|
|
@@ -128,8 +274,8 @@ function tracedChatCompletionsCreate(original) {
|
|
|
128
274
|
opts.stream_options = { ...streamOpts, include_usage: true };
|
|
129
275
|
}
|
|
130
276
|
}
|
|
131
|
-
const ctx =
|
|
132
|
-
const promise =
|
|
277
|
+
const ctx = import_api4.trace.setSpan(import_api4.context.active(), span);
|
|
278
|
+
const promise = import_api4.context.with(ctx, () => original(opts, ...rest));
|
|
133
279
|
return promise.then(
|
|
134
280
|
(response) => {
|
|
135
281
|
if (isStream) {
|
|
@@ -147,7 +293,7 @@ function tracedChatCompletionsCreate(original) {
|
|
|
147
293
|
}
|
|
148
294
|
function tracedResponsesCreate(original) {
|
|
149
295
|
return function(opts, ...rest) {
|
|
150
|
-
const tracer =
|
|
296
|
+
const tracer = getProviderTracer(TRACER_NAME);
|
|
151
297
|
const model = opts?.model ?? "";
|
|
152
298
|
const span = tracer.startSpan("azure_openai.responses.create", {
|
|
153
299
|
attributes: {
|
|
@@ -157,9 +303,9 @@ function tracedResponsesCreate(original) {
|
|
|
157
303
|
"neatlogs.llm.model_name": model,
|
|
158
304
|
"input.value": safeStringify(opts?.input ?? "")
|
|
159
305
|
}
|
|
160
|
-
},
|
|
161
|
-
const ctx =
|
|
162
|
-
const promise =
|
|
306
|
+
}, import_api4.context.active());
|
|
307
|
+
const ctx = import_api4.trace.setSpan(import_api4.context.active(), span);
|
|
308
|
+
const promise = import_api4.context.with(ctx, () => original(opts, ...rest));
|
|
163
309
|
return promise.then(
|
|
164
310
|
(response) => {
|
|
165
311
|
if (response?.output_text) {
|
|
@@ -171,7 +317,7 @@ function tracedResponsesCreate(original) {
|
|
|
171
317
|
if (response.usage.input_tokens != null) span.setAttribute("neatlogs.llm.token_count.prompt", response.usage.input_tokens);
|
|
172
318
|
if (response.usage.output_tokens != null) span.setAttribute("neatlogs.llm.token_count.completion", response.usage.output_tokens);
|
|
173
319
|
}
|
|
174
|
-
span.setStatus({ code:
|
|
320
|
+
span.setStatus({ code: import_api4.SpanStatusCode.OK });
|
|
175
321
|
span.end();
|
|
176
322
|
return response;
|
|
177
323
|
},
|
|
@@ -186,7 +332,7 @@ function wrapAsyncIterableStream(stream, span) {
|
|
|
186
332
|
const chunks = [];
|
|
187
333
|
const originalAsyncIterator = stream?.[Symbol.asyncIterator]?.bind(stream);
|
|
188
334
|
if (!originalAsyncIterator) {
|
|
189
|
-
span.setStatus({ code:
|
|
335
|
+
span.setStatus({ code: import_api4.SpanStatusCode.OK });
|
|
190
336
|
span.end();
|
|
191
337
|
return stream;
|
|
192
338
|
}
|
|
@@ -272,7 +418,7 @@ function finalizeStreamChunks(span, chunks) {
|
|
|
272
418
|
span.setAttribute("neatlogs.llm.token_count.reasoning", usage.completion_tokens_details.reasoning_tokens);
|
|
273
419
|
}
|
|
274
420
|
}
|
|
275
|
-
span.setStatus({ code:
|
|
421
|
+
span.setStatus({ code: import_api4.SpanStatusCode.OK });
|
|
276
422
|
span.end();
|
|
277
423
|
}
|
|
278
424
|
function finalizeChatResponse(span, response) {
|
|
@@ -309,7 +455,7 @@ function finalizeChatResponse(span, response) {
|
|
|
309
455
|
}
|
|
310
456
|
}
|
|
311
457
|
if (response?.model) span.setAttribute("neatlogs.llm.model_name", response.model);
|
|
312
|
-
span.setStatus({ code:
|
|
458
|
+
span.setStatus({ code: import_api4.SpanStatusCode.OK });
|
|
313
459
|
span.end();
|
|
314
460
|
}
|
|
315
461
|
function setInvocationParams(span, opts) {
|
|
@@ -329,10 +475,10 @@ function safeStringify(value) {
|
|
|
329
475
|
}
|
|
330
476
|
function recordError(span, err) {
|
|
331
477
|
if (err instanceof Error) {
|
|
332
|
-
span.setStatus({ code:
|
|
478
|
+
span.setStatus({ code: import_api4.SpanStatusCode.ERROR, message: err.message });
|
|
333
479
|
span.recordException(err);
|
|
334
480
|
} else {
|
|
335
|
-
span.setStatus({ code:
|
|
481
|
+
span.setStatus({ code: import_api4.SpanStatusCode.ERROR, message: String(err) });
|
|
336
482
|
}
|
|
337
483
|
span.end();
|
|
338
484
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/azure-openai.ts"],"sourcesContent":["/**\n * Neatlogs Azure OpenAI wrapper — ES6 Proxy-based.\n *\n * Azure OpenAI is accessed through the `openai` SDK's `AzureOpenAI` client,\n * which exposes the same `chat.completions.create()` shape as `OpenAI`. This\n * wrapper traces those calls with provider `azure` so Azure traffic is\n * distinguished from direct OpenAI traffic.\n *\n * Usage:\n * import { wrapAzureOpenAI } from 'neatlogs/azure-openai';\n * import { AzureOpenAI } from 'openai';\n * const client = wrapAzureOpenAI(new AzureOpenAI({ endpoint, apiKey, apiVersion }));\n * await client.chat.completions.create({ model: 'gpt-4o', messages: [...] });\n *\n * Intercepts:\n * - client.chat.completions.create() — non-streaming and streaming\n * - client.responses.create() — Responses API\n */\n\nimport { trace, context as otelContext, SpanStatusCode, type Span } from '@opentelemetry/api';\n\nconst TRACER_NAME = 'neatlogs.azure_openai';\nconst PROVIDER = 'azure';\nconst SYSTEM = 'azure';\n\nexport function wrapAzureOpenAI<T extends object>(client: T): T {\n return wrapNamespace(client, []) as T;\n}\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\nfunction wrapNamespace(target: any, path: string[]): any {\n return new Proxy(target, {\n get(obj, prop, receiver) {\n const value = Reflect.get(obj, prop, receiver);\n if (typeof prop === 'symbol' || String(prop).startsWith('_')) return value;\n\n const currentPath = [...path, String(prop)];\n const pathStr = currentPath.join('.');\n\n if (pathStr === 'chat.completions.create' && typeof value === 'function') {\n return tracedChatCompletionsCreate(value.bind(obj));\n }\n if (pathStr === 'responses.create' && typeof value === 'function') {\n return tracedResponsesCreate(value.bind(obj));\n }\n\n if (value && typeof value === 'object' && !Array.isArray(value) && isNamespace(currentPath)) {\n return wrapNamespace(value, currentPath);\n }\n\n return value;\n },\n });\n}\n\nfunction isNamespace(path: string[]): boolean {\n if (path.length > 3) return false;\n const key = path[path.length - 1];\n return ['chat', 'completions', 'responses', 'beta'].includes(key);\n}\n\n// ---------------------------------------------------------------------------\n// chat.completions.create — non-streaming + streaming\n// ---------------------------------------------------------------------------\n\nfunction tracedChatCompletionsCreate(original: (...args: any[]) => any) {\n return function (opts: any, ...rest: any[]): any {\n const tracer = trace.getTracer(TRACER_NAME);\n const model = opts?.model ?? '';\n const messages: any[] = opts?.messages ?? [];\n const isStream = opts?.stream === true;\n\n const span = tracer.startSpan('azure_openai.chat.completions.create', {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': SYSTEM,\n 'neatlogs.llm.model_name': model,\n 'neatlogs.llm.is_streaming': isStream,\n },\n }, otelContext.active());\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n span.setAttribute(`neatlogs.llm.input_messages.${i}.role`, msg.role ?? '');\n if (typeof msg.content === 'string') {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.content`, msg.content);\n } else if (msg.content) {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.content`, safeStringify(msg.content));\n }\n if (msg.tool_call_id) {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.tool_call_id`, msg.tool_call_id);\n }\n }\n\n if (opts?.tools) {\n for (let i = 0; i < opts.tools.length; i++) {\n const fn = opts.tools[i]?.function ?? {};\n span.setAttribute(`neatlogs.llm.tools.${i}.name`, fn.name ?? '');\n if (fn.description) span.setAttribute(`neatlogs.llm.tools.${i}.description`, fn.description);\n if (fn.parameters) span.setAttribute(`neatlogs.llm.tools.${i}.input_schema`, safeStringify(fn.parameters));\n }\n }\n\n setInvocationParams(span, opts);\n\n if (isStream) {\n opts = { ...opts };\n const streamOpts = opts.stream_options ?? {};\n if (!streamOpts.include_usage) {\n opts.stream_options = { ...streamOpts, include_usage: true };\n }\n }\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => original(opts, ...rest));\n\n return promise.then(\n (response: any) => {\n if (isStream) {\n return wrapAsyncIterableStream(response, span);\n }\n finalizeChatResponse(span, response);\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n };\n}\n\n// ---------------------------------------------------------------------------\n// responses.create\n// ---------------------------------------------------------------------------\n\nfunction tracedResponsesCreate(original: (...args: any[]) => any) {\n return function (opts: any, ...rest: any[]): any {\n const tracer = trace.getTracer(TRACER_NAME);\n const model = opts?.model ?? '';\n\n const span = tracer.startSpan('azure_openai.responses.create', {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': SYSTEM,\n 'neatlogs.llm.model_name': model,\n 'input.value': safeStringify(opts?.input ?? ''),\n },\n }, otelContext.active());\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => original(opts, ...rest));\n\n return promise.then(\n (response: any) => {\n if (response?.output_text) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', response.output_text);\n }\n if (response?.model) span.setAttribute('neatlogs.llm.model_name', response.model);\n if (response?.usage) {\n if (response.usage.input_tokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', response.usage.input_tokens);\n if (response.usage.output_tokens != null) span.setAttribute('neatlogs.llm.token_count.completion', response.usage.output_tokens);\n }\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n };\n}\n\n// ---------------------------------------------------------------------------\n// Streaming support\n// ---------------------------------------------------------------------------\n\nfunction wrapAsyncIterableStream(stream: any, span: Span): any {\n const chunks: any[] = [];\n const originalAsyncIterator = stream?.[Symbol.asyncIterator]?.bind(stream);\n\n if (!originalAsyncIterator) {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return stream;\n }\n\n const wrapped = Object.create(Object.getPrototypeOf(stream));\n Object.assign(wrapped, stream);\n\n wrapped[Symbol.asyncIterator] = function () {\n const iterator = originalAsyncIterator();\n return {\n async next(): Promise<IteratorResult<any>> {\n try {\n const result = await iterator.next();\n if (result.done) {\n finalizeStreamChunks(span, chunks);\n return result;\n }\n chunks.push(result.value);\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n }\n },\n async return(value?: any): Promise<IteratorResult<any>> {\n finalizeStreamChunks(span, chunks);\n return iterator.return?.(value) ?? { done: true, value: undefined };\n },\n async throw(err?: any): Promise<IteratorResult<any>> {\n recordError(span, err);\n return iterator.throw?.(err) ?? { done: true, value: undefined };\n },\n };\n };\n\n return wrapped;\n}\n\nfunction finalizeStreamChunks(span: Span, chunks: any[]): void {\n const textParts: string[] = [];\n const toolCallsAcc: Record<number, { id: string; name: string; arguments: string }> = {};\n let finishReason = '';\n let model = '';\n let usage: any = null;\n\n for (const chunk of chunks) {\n if (!chunk?.choices?.length) {\n if (chunk?.usage) usage = chunk.usage;\n continue;\n }\n const choice = chunk.choices[0];\n const delta = choice?.delta;\n if (delta?.content) textParts.push(delta.content);\n if (delta?.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index ?? 0;\n if (!toolCallsAcc[idx]) toolCallsAcc[idx] = { id: '', name: '', arguments: '' };\n if (tc.id) toolCallsAcc[idx].id = tc.id;\n if (tc.function?.name) toolCallsAcc[idx].name = tc.function.name;\n if (tc.function?.arguments) toolCallsAcc[idx].arguments += tc.function.arguments;\n }\n }\n if (choice?.finish_reason) finishReason = choice.finish_reason;\n if (chunk?.model) model = chunk.model;\n }\n\n const fullText = textParts.join('');\n if (fullText) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', fullText);\n }\n\n let j = 0;\n for (const tc of Object.values(toolCallsAcc)) {\n 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\n if (model) span.setAttribute('neatlogs.llm.model_name', model);\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', finishReason);\n\n if (usage) {\n if (usage.prompt_tokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.prompt_tokens);\n if (usage.completion_tokens != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.completion_tokens);\n if (usage.total_tokens != null) span.setAttribute('neatlogs.llm.token_count.total', usage.total_tokens);\n if (usage.prompt_tokens_details?.cached_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.cache_read', usage.prompt_tokens_details.cached_tokens);\n }\n if (usage.completion_tokens_details?.reasoning_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.reasoning', usage.completion_tokens_details.reasoning_tokens);\n }\n }\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\n// ---------------------------------------------------------------------------\n// Non-streaming response finalization\n// ---------------------------------------------------------------------------\n\nfunction finalizeChatResponse(span: Span, response: any): void {\n const choices = response?.choices ?? [];\n for (let i = 0; i < choices.length; i++) {\n const message = choices[i]?.message;\n if (!message) continue;\n\n span.setAttribute(`neatlogs.llm.output_messages.${i}.role`, 'assistant');\n if (message.content) {\n span.setAttribute(`neatlogs.llm.output_messages.${i}.content`, message.content);\n }\n if (message.tool_calls) {\n for (let j = 0; j < message.tool_calls.length; j++) {\n const tc = message.tool_calls[j];\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, tc.id ?? '');\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.function?.name ?? '');\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, tc.function?.arguments ?? '');\n }\n }\n if (choices[i].finish_reason) {\n span.setAttribute('neatlogs.llm.finish_reason', choices[i].finish_reason);\n }\n }\n\n const usage = response?.usage;\n if (usage) {\n if (usage.prompt_tokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.prompt_tokens);\n if (usage.completion_tokens != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.completion_tokens);\n if (usage.total_tokens != null) span.setAttribute('neatlogs.llm.token_count.total', usage.total_tokens);\n if (usage.prompt_tokens_details?.cached_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.cache_read', usage.prompt_tokens_details.cached_tokens);\n }\n if (usage.completion_tokens_details?.reasoning_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.reasoning', usage.completion_tokens_details.reasoning_tokens);\n }\n }\n\n if (response?.model) span.setAttribute('neatlogs.llm.model_name', response.model);\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nfunction setInvocationParams(span: Span, opts: any): void {\n if (opts?.temperature != null) span.setAttribute('neatlogs.llm.temperature', opts.temperature);\n if (opts?.top_p != null) span.setAttribute('neatlogs.llm.top_p', opts.top_p);\n if (opts?.max_tokens != null) span.setAttribute('neatlogs.llm.max_tokens', opts.max_tokens);\n if (opts?.frequency_penalty != null) span.setAttribute('neatlogs.llm.frequency_penalty', opts.frequency_penalty);\n if (opts?.presence_penalty != null) span.setAttribute('neatlogs.llm.presence_penalty', opts.presence_penalty);\n if (opts?.stop) span.setAttribute('neatlogs.llm.stop_sequences', safeStringify(opts.stop));\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/azure-openai.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 Azure OpenAI wrapper — ES6 Proxy-based.\n *\n * Azure OpenAI is accessed through the `openai` SDK's `AzureOpenAI` client,\n * which exposes the same `chat.completions.create()` shape as `OpenAI`. This\n * wrapper traces those calls with provider `azure` so Azure traffic is\n * distinguished from direct OpenAI traffic.\n *\n * Usage:\n * import { wrapAzureOpenAI } from 'neatlogs/azure-openai';\n * import { AzureOpenAI } from 'openai';\n * const client = wrapAzureOpenAI(new AzureOpenAI({ endpoint, apiKey, apiVersion }));\n * await client.chat.completions.create({ model: 'gpt-4o', messages: [...] });\n *\n * Intercepts:\n * - client.chat.completions.create() — non-streaming and streaming\n * - client.responses.create() — Responses API\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.azure_openai';\nconst PROVIDER = 'azure';\nconst SYSTEM = 'azure';\n\nexport function wrapAzureOpenAI<T extends object>(client: T): T {\n return wrapNamespace(client, []) as T;\n}\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\nfunction wrapNamespace(target: any, path: string[]): any {\n return new Proxy(target, {\n get(obj, prop, receiver) {\n const value = Reflect.get(obj, prop, receiver);\n if (typeof prop === 'symbol' || String(prop).startsWith('_')) return value;\n\n const currentPath = [...path, String(prop)];\n const pathStr = currentPath.join('.');\n\n if (pathStr === 'chat.completions.create' && typeof value === 'function') {\n return tracedChatCompletionsCreate(value.bind(obj));\n }\n if (pathStr === 'responses.create' && typeof value === 'function') {\n return tracedResponsesCreate(value.bind(obj));\n }\n\n if (value && typeof value === 'object' && !Array.isArray(value) && isNamespace(currentPath)) {\n return wrapNamespace(value, currentPath);\n }\n\n return value;\n },\n });\n}\n\nfunction isNamespace(path: string[]): boolean {\n if (path.length > 3) return false;\n const key = path[path.length - 1];\n return ['chat', 'completions', 'responses', 'beta'].includes(key);\n}\n\n// ---------------------------------------------------------------------------\n// chat.completions.create — non-streaming + streaming\n// ---------------------------------------------------------------------------\n\nfunction tracedChatCompletionsCreate(original: (...args: any[]) => any) {\n return function (opts: any, ...rest: any[]): any {\n const tracer = getProviderTracer(TRACER_NAME);\n const model = opts?.model ?? '';\n const messages: any[] = opts?.messages ?? [];\n const isStream = opts?.stream === true;\n\n const span = tracer.startSpan('azure_openai.chat.completions.create', {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': SYSTEM,\n 'neatlogs.llm.model_name': model,\n 'neatlogs.llm.is_streaming': isStream,\n },\n }, otelContext.active());\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n span.setAttribute(`neatlogs.llm.input_messages.${i}.role`, msg.role ?? '');\n if (typeof msg.content === 'string') {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.content`, msg.content);\n } else if (msg.content) {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.content`, safeStringify(msg.content));\n }\n if (msg.tool_call_id) {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.tool_call_id`, msg.tool_call_id);\n }\n }\n\n if (opts?.tools) {\n for (let i = 0; i < opts.tools.length; i++) {\n const fn = opts.tools[i]?.function ?? {};\n span.setAttribute(`neatlogs.llm.tools.${i}.name`, fn.name ?? '');\n if (fn.description) span.setAttribute(`neatlogs.llm.tools.${i}.description`, fn.description);\n if (fn.parameters) span.setAttribute(`neatlogs.llm.tools.${i}.input_schema`, safeStringify(fn.parameters));\n }\n }\n\n setInvocationParams(span, opts);\n\n if (isStream) {\n opts = { ...opts };\n const streamOpts = opts.stream_options ?? {};\n if (!streamOpts.include_usage) {\n opts.stream_options = { ...streamOpts, include_usage: true };\n }\n }\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => original(opts, ...rest));\n\n return promise.then(\n (response: any) => {\n if (isStream) {\n return wrapAsyncIterableStream(response, span);\n }\n finalizeChatResponse(span, response);\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n };\n}\n\n// ---------------------------------------------------------------------------\n// responses.create\n// ---------------------------------------------------------------------------\n\nfunction tracedResponsesCreate(original: (...args: any[]) => any) {\n return function (opts: any, ...rest: any[]): any {\n const tracer = getProviderTracer(TRACER_NAME);\n const model = opts?.model ?? '';\n\n const span = tracer.startSpan('azure_openai.responses.create', {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': SYSTEM,\n 'neatlogs.llm.model_name': model,\n 'input.value': safeStringify(opts?.input ?? ''),\n },\n }, otelContext.active());\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const promise = otelContext.with(ctx, () => original(opts, ...rest));\n\n return promise.then(\n (response: any) => {\n if (response?.output_text) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', response.output_text);\n }\n if (response?.model) span.setAttribute('neatlogs.llm.model_name', response.model);\n if (response?.usage) {\n if (response.usage.input_tokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', response.usage.input_tokens);\n if (response.usage.output_tokens != null) span.setAttribute('neatlogs.llm.token_count.completion', response.usage.output_tokens);\n }\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n };\n}\n\n// ---------------------------------------------------------------------------\n// Streaming support\n// ---------------------------------------------------------------------------\n\nfunction wrapAsyncIterableStream(stream: any, span: Span): any {\n const chunks: any[] = [];\n const originalAsyncIterator = stream?.[Symbol.asyncIterator]?.bind(stream);\n\n if (!originalAsyncIterator) {\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return stream;\n }\n\n const wrapped = Object.create(Object.getPrototypeOf(stream));\n Object.assign(wrapped, stream);\n\n wrapped[Symbol.asyncIterator] = function () {\n const iterator = originalAsyncIterator();\n return {\n async next(): Promise<IteratorResult<any>> {\n try {\n const result = await iterator.next();\n if (result.done) {\n finalizeStreamChunks(span, chunks);\n return result;\n }\n chunks.push(result.value);\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n }\n },\n async return(value?: any): Promise<IteratorResult<any>> {\n finalizeStreamChunks(span, chunks);\n return iterator.return?.(value) ?? { done: true, value: undefined };\n },\n async throw(err?: any): Promise<IteratorResult<any>> {\n recordError(span, err);\n return iterator.throw?.(err) ?? { done: true, value: undefined };\n },\n };\n };\n\n return wrapped;\n}\n\nfunction finalizeStreamChunks(span: Span, chunks: any[]): void {\n const textParts: string[] = [];\n const toolCallsAcc: Record<number, { id: string; name: string; arguments: string }> = {};\n let finishReason = '';\n let model = '';\n let usage: any = null;\n\n for (const chunk of chunks) {\n if (!chunk?.choices?.length) {\n if (chunk?.usage) usage = chunk.usage;\n continue;\n }\n const choice = chunk.choices[0];\n const delta = choice?.delta;\n if (delta?.content) textParts.push(delta.content);\n if (delta?.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index ?? 0;\n if (!toolCallsAcc[idx]) toolCallsAcc[idx] = { id: '', name: '', arguments: '' };\n if (tc.id) toolCallsAcc[idx].id = tc.id;\n if (tc.function?.name) toolCallsAcc[idx].name = tc.function.name;\n if (tc.function?.arguments) toolCallsAcc[idx].arguments += tc.function.arguments;\n }\n }\n if (choice?.finish_reason) finishReason = choice.finish_reason;\n if (chunk?.model) model = chunk.model;\n }\n\n const fullText = textParts.join('');\n if (fullText) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', fullText);\n }\n\n let j = 0;\n for (const tc of Object.values(toolCallsAcc)) {\n 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\n if (model) span.setAttribute('neatlogs.llm.model_name', model);\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', finishReason);\n\n if (usage) {\n if (usage.prompt_tokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.prompt_tokens);\n if (usage.completion_tokens != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.completion_tokens);\n if (usage.total_tokens != null) span.setAttribute('neatlogs.llm.token_count.total', usage.total_tokens);\n if (usage.prompt_tokens_details?.cached_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.cache_read', usage.prompt_tokens_details.cached_tokens);\n }\n if (usage.completion_tokens_details?.reasoning_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.reasoning', usage.completion_tokens_details.reasoning_tokens);\n }\n }\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\n// ---------------------------------------------------------------------------\n// Non-streaming response finalization\n// ---------------------------------------------------------------------------\n\nfunction finalizeChatResponse(span: Span, response: any): void {\n const choices = response?.choices ?? [];\n for (let i = 0; i < choices.length; i++) {\n const message = choices[i]?.message;\n if (!message) continue;\n\n span.setAttribute(`neatlogs.llm.output_messages.${i}.role`, 'assistant');\n if (message.content) {\n span.setAttribute(`neatlogs.llm.output_messages.${i}.content`, message.content);\n }\n if (message.tool_calls) {\n for (let j = 0; j < message.tool_calls.length; j++) {\n const tc = message.tool_calls[j];\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, tc.id ?? '');\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.function?.name ?? '');\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, tc.function?.arguments ?? '');\n }\n }\n if (choices[i].finish_reason) {\n span.setAttribute('neatlogs.llm.finish_reason', choices[i].finish_reason);\n }\n }\n\n const usage = response?.usage;\n if (usage) {\n if (usage.prompt_tokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.prompt_tokens);\n if (usage.completion_tokens != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.completion_tokens);\n if (usage.total_tokens != null) span.setAttribute('neatlogs.llm.token_count.total', usage.total_tokens);\n if (usage.prompt_tokens_details?.cached_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.cache_read', usage.prompt_tokens_details.cached_tokens);\n }\n if (usage.completion_tokens_details?.reasoning_tokens != null) {\n span.setAttribute('neatlogs.llm.token_count.reasoning', usage.completion_tokens_details.reasoning_tokens);\n }\n }\n\n if (response?.model) span.setAttribute('neatlogs.llm.model_name', response.model);\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nfunction setInvocationParams(span: Span, opts: any): void {\n if (opts?.temperature != null) span.setAttribute('neatlogs.llm.temperature', opts.temperature);\n if (opts?.top_p != null) span.setAttribute('neatlogs.llm.top_p', opts.top_p);\n if (opts?.max_tokens != null) span.setAttribute('neatlogs.llm.max_tokens', opts.max_tokens);\n if (opts?.frequency_penalty != null) span.setAttribute('neatlogs.llm.frequency_penalty', opts.frequency_penalty);\n if (opts?.presence_penalty != null) span.setAttribute('neatlogs.llm.presence_penalty', opts.presence_penalty);\n if (opts?.stop) span.setAttribute('neatlogs.llm.stop_sequences', safeStringify(opts.stop));\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"]}
|