neatlogs 1.0.4 → 1.0.6
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 +373 -0
- package/dist/anthropic.cjs.map +1 -0
- package/dist/anthropic.d.ts +27 -0
- package/dist/anthropic.mjs +347 -0
- package/dist/anthropic.mjs.map +1 -0
- package/dist/index.cjs +1999 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.mjs +1993 -7
- package/dist/index.mjs.map +1 -1
- package/dist/langchain.cjs +269 -0
- package/dist/langchain.cjs.map +1 -0
- package/dist/langchain.d.ts +16 -0
- package/dist/langchain.mjs +244 -0
- package/dist/langchain.mjs.map +1 -0
- package/dist/mastra-wrap.cjs +597 -0
- package/dist/mastra-wrap.cjs.map +1 -0
- package/dist/mastra-wrap.d.ts +38 -0
- package/dist/mastra-wrap.mjs +571 -0
- package/dist/mastra-wrap.mjs.map +1 -0
- package/dist/openai-agents.cjs +215 -0
- package/dist/openai-agents.cjs.map +1 -0
- package/dist/openai-agents.d.ts +13 -0
- package/dist/openai-agents.mjs +190 -0
- package/dist/openai-agents.mjs.map +1 -0
- package/dist/openai.cjs +342 -0
- package/dist/openai.cjs.map +1 -0
- package/dist/openai.d.ts +26 -0
- package/dist/openai.mjs +316 -0
- package/dist/openai.mjs.map +1 -0
- package/dist/pi-agent.cjs +237 -0
- package/dist/pi-agent.cjs.map +1 -0
- package/dist/pi-agent.d.ts +31 -0
- package/dist/pi-agent.mjs +216 -0
- package/dist/pi-agent.mjs.map +1 -0
- package/dist/strands.cjs +167 -0
- package/dist/strands.cjs.map +1 -0
- package/dist/strands.d.ts +28 -0
- package/dist/strands.mjs +142 -0
- package/dist/strands.mjs.map +1 -0
- package/package.json +75 -3
package/dist/index.cjs
CHANGED
|
@@ -50,16 +50,25 @@ __export(index_exports, {
|
|
|
50
50
|
getSessionConfig: () => getSessionConfig,
|
|
51
51
|
init: () => init,
|
|
52
52
|
isDebugEnabled: () => isDebugEnabled,
|
|
53
|
+
langchainHandler: () => langchainHandler,
|
|
53
54
|
listPrompts: () => listPrompts,
|
|
54
55
|
log: () => log,
|
|
56
|
+
openaiAgentsProcessor: () => openaiAgentsProcessor,
|
|
57
|
+
piAgentHooks: () => piAgentHooks,
|
|
55
58
|
registerCrewaiTask: () => registerCrewaiTask,
|
|
56
59
|
removeTag: () => removeTag,
|
|
57
60
|
saveAsVersion: () => saveAsVersion,
|
|
58
61
|
shutdown: () => shutdown,
|
|
59
62
|
span: () => span,
|
|
63
|
+
strandsHooks: () => strandsHooks,
|
|
60
64
|
trace: () => trace2,
|
|
65
|
+
traceToolAnthropic: () => traceTool2,
|
|
66
|
+
traceToolOpenAI: () => traceTool,
|
|
61
67
|
updatePrompt: () => updatePrompt,
|
|
62
|
-
wrapAISDK: () => wrapAISDK
|
|
68
|
+
wrapAISDK: () => wrapAISDK,
|
|
69
|
+
wrapAnthropic: () => wrapAnthropic,
|
|
70
|
+
wrapMastra: () => wrapMastra,
|
|
71
|
+
wrapOpenAI: () => wrapOpenAI
|
|
63
72
|
});
|
|
64
73
|
module.exports = __toCommonJS(index_exports);
|
|
65
74
|
|
|
@@ -302,7 +311,6 @@ var VECTOR_DB_SYSTEMS = /* @__PURE__ */ new Set([
|
|
|
302
311
|
"marqo",
|
|
303
312
|
"weaviate",
|
|
304
313
|
"lancedb",
|
|
305
|
-
"astra",
|
|
306
314
|
"pgvector",
|
|
307
315
|
"elasticsearch"
|
|
308
316
|
]);
|
|
@@ -328,8 +336,7 @@ var VECTOR_DB_NAMES = [
|
|
|
328
336
|
"qdrant",
|
|
329
337
|
"milvus",
|
|
330
338
|
"lancedb",
|
|
331
|
-
"marqo"
|
|
332
|
-
"astra"
|
|
339
|
+
"marqo"
|
|
333
340
|
];
|
|
334
341
|
|
|
335
342
|
// src/span-kinds/mapping.ts
|
|
@@ -3149,7 +3156,8 @@ var attribute_mapping_default = {
|
|
|
3149
3156
|
tool: {
|
|
3150
3157
|
name: {
|
|
3151
3158
|
sources: [
|
|
3152
|
-
"tool.name"
|
|
3159
|
+
"tool.name",
|
|
3160
|
+
"gen_ai.tool.name"
|
|
3153
3161
|
],
|
|
3154
3162
|
target: "neatlogs.tool.name"
|
|
3155
3163
|
},
|
|
@@ -3898,16 +3906,25 @@ var AttributeMapper = class {
|
|
|
3898
3906
|
}
|
|
3899
3907
|
}
|
|
3900
3908
|
}
|
|
3909
|
+
if (!spanKindValue && "neatlogs.span.kind" in attributes) {
|
|
3910
|
+
spanKindValue = attributes["neatlogs.span.kind"];
|
|
3911
|
+
}
|
|
3901
3912
|
if (spanKindValue && spanKindValue in valuesMap) {
|
|
3902
3913
|
return valuesMap[spanKindValue];
|
|
3903
3914
|
}
|
|
3915
|
+
if (spanKindValue && Object.values(valuesMap).includes(spanKindValue)) {
|
|
3916
|
+
return spanKindValue;
|
|
3917
|
+
}
|
|
3904
3918
|
const isLlmSpan = [
|
|
3905
3919
|
"llm.model_name",
|
|
3906
3920
|
"gen_ai.request.model",
|
|
3907
3921
|
"llm.token_count.prompt",
|
|
3908
3922
|
"llm.token_count.completion",
|
|
3909
3923
|
"gen_ai.usage.prompt_tokens",
|
|
3910
|
-
"gen_ai.usage.completion_tokens"
|
|
3924
|
+
"gen_ai.usage.completion_tokens",
|
|
3925
|
+
"neatlogs.llm.model_name",
|
|
3926
|
+
"neatlogs.llm.token_count.prompt",
|
|
3927
|
+
"neatlogs.llm.token_count.completion"
|
|
3911
3928
|
].some((key) => key in attributes);
|
|
3912
3929
|
if (isLlmSpan) {
|
|
3913
3930
|
return "llm";
|
|
@@ -5846,7 +5863,7 @@ async function removeTag(name, tag) {
|
|
|
5846
5863
|
}
|
|
5847
5864
|
|
|
5848
5865
|
// src/version.ts
|
|
5849
|
-
var __version__ = "1.0.
|
|
5866
|
+
var __version__ = "1.0.6";
|
|
5850
5867
|
|
|
5851
5868
|
// src/init.ts
|
|
5852
5869
|
var logger13 = getLogger();
|
|
@@ -6478,6 +6495,1971 @@ function recordSpanError(span2, err) {
|
|
|
6478
6495
|
}
|
|
6479
6496
|
}
|
|
6480
6497
|
|
|
6498
|
+
// src/openai.ts
|
|
6499
|
+
var import_api9 = require("@opentelemetry/api");
|
|
6500
|
+
var TRACER_NAME3 = "neatlogs.openai";
|
|
6501
|
+
function wrapOpenAI(client) {
|
|
6502
|
+
return wrapNamespace(client, []);
|
|
6503
|
+
}
|
|
6504
|
+
function traceTool(name, fn) {
|
|
6505
|
+
return async function tracedTool(args) {
|
|
6506
|
+
const tracer = import_api9.trace.getTracer(TRACER_NAME3);
|
|
6507
|
+
return tracer.startActiveSpan(
|
|
6508
|
+
`tool.${name}`,
|
|
6509
|
+
{
|
|
6510
|
+
attributes: {
|
|
6511
|
+
"neatlogs.span.kind": "TOOL",
|
|
6512
|
+
"neatlogs.tool.name": name,
|
|
6513
|
+
"input.value": safeStringify3(args)
|
|
6514
|
+
}
|
|
6515
|
+
},
|
|
6516
|
+
import_api9.context.active(),
|
|
6517
|
+
async (span2) => {
|
|
6518
|
+
try {
|
|
6519
|
+
const result = await fn(args);
|
|
6520
|
+
span2.setAttribute("output.value", safeStringify3(result));
|
|
6521
|
+
span2.setStatus({ code: import_api9.SpanStatusCode.OK });
|
|
6522
|
+
return result;
|
|
6523
|
+
} catch (err) {
|
|
6524
|
+
recordError(span2, err);
|
|
6525
|
+
throw err;
|
|
6526
|
+
} finally {
|
|
6527
|
+
span2.end();
|
|
6528
|
+
}
|
|
6529
|
+
}
|
|
6530
|
+
);
|
|
6531
|
+
};
|
|
6532
|
+
}
|
|
6533
|
+
function wrapNamespace(target, path4) {
|
|
6534
|
+
return new Proxy(target, {
|
|
6535
|
+
get(obj, prop, receiver) {
|
|
6536
|
+
const value = Reflect.get(obj, prop, receiver);
|
|
6537
|
+
if (typeof prop === "symbol" || String(prop).startsWith("_")) return value;
|
|
6538
|
+
const currentPath = [...path4, String(prop)];
|
|
6539
|
+
const pathStr = currentPath.join(".");
|
|
6540
|
+
if (pathStr === "chat.completions.create" && typeof value === "function") {
|
|
6541
|
+
return tracedChatCompletionsCreate(value.bind(obj));
|
|
6542
|
+
}
|
|
6543
|
+
if (pathStr === "responses.create" && typeof value === "function") {
|
|
6544
|
+
return tracedResponsesCreate(value.bind(obj));
|
|
6545
|
+
}
|
|
6546
|
+
if (value && typeof value === "object" && !Array.isArray(value) && isNamespace(currentPath)) {
|
|
6547
|
+
return wrapNamespace(value, currentPath);
|
|
6548
|
+
}
|
|
6549
|
+
return value;
|
|
6550
|
+
}
|
|
6551
|
+
});
|
|
6552
|
+
}
|
|
6553
|
+
function isNamespace(path4) {
|
|
6554
|
+
if (path4.length > 3) return false;
|
|
6555
|
+
const key = path4[path4.length - 1];
|
|
6556
|
+
return ["chat", "completions", "responses", "beta"].includes(key);
|
|
6557
|
+
}
|
|
6558
|
+
function tracedChatCompletionsCreate(original) {
|
|
6559
|
+
return function(opts, ...rest) {
|
|
6560
|
+
const tracer = import_api9.trace.getTracer(TRACER_NAME3);
|
|
6561
|
+
const model = opts?.model ?? "";
|
|
6562
|
+
const messages = opts?.messages ?? [];
|
|
6563
|
+
const isStream = opts?.stream === true;
|
|
6564
|
+
const span2 = tracer.startSpan("openai.chat.completions.create", {
|
|
6565
|
+
attributes: {
|
|
6566
|
+
"neatlogs.span.kind": "LLM",
|
|
6567
|
+
"neatlogs.llm.provider": "openai",
|
|
6568
|
+
"neatlogs.llm.system": "openai",
|
|
6569
|
+
"neatlogs.llm.model_name": model,
|
|
6570
|
+
"neatlogs.llm.is_streaming": isStream
|
|
6571
|
+
}
|
|
6572
|
+
}, import_api9.context.active());
|
|
6573
|
+
for (let i = 0; i < messages.length; i++) {
|
|
6574
|
+
const msg = messages[i];
|
|
6575
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${i}.role`, msg.role ?? "");
|
|
6576
|
+
if (typeof msg.content === "string") {
|
|
6577
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${i}.content`, msg.content);
|
|
6578
|
+
} else if (msg.content) {
|
|
6579
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${i}.content`, safeStringify3(msg.content));
|
|
6580
|
+
}
|
|
6581
|
+
if (msg.tool_call_id) {
|
|
6582
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${i}.tool_call_id`, msg.tool_call_id);
|
|
6583
|
+
}
|
|
6584
|
+
}
|
|
6585
|
+
if (opts?.tools) {
|
|
6586
|
+
for (let i = 0; i < opts.tools.length; i++) {
|
|
6587
|
+
const fn = opts.tools[i]?.function ?? {};
|
|
6588
|
+
span2.setAttribute(`neatlogs.llm.tools.${i}.name`, fn.name ?? "");
|
|
6589
|
+
if (fn.description) span2.setAttribute(`neatlogs.llm.tools.${i}.description`, fn.description);
|
|
6590
|
+
if (fn.parameters) span2.setAttribute(`neatlogs.llm.tools.${i}.input_schema`, safeStringify3(fn.parameters));
|
|
6591
|
+
}
|
|
6592
|
+
}
|
|
6593
|
+
setInvocationParams(span2, opts);
|
|
6594
|
+
if (isStream) {
|
|
6595
|
+
opts = { ...opts };
|
|
6596
|
+
const streamOpts = opts.stream_options ?? {};
|
|
6597
|
+
if (!streamOpts.include_usage) {
|
|
6598
|
+
opts.stream_options = { ...streamOpts, include_usage: true };
|
|
6599
|
+
}
|
|
6600
|
+
}
|
|
6601
|
+
const ctx = import_api9.trace.setSpan(import_api9.context.active(), span2);
|
|
6602
|
+
const promise = import_api9.context.with(ctx, () => original(opts, ...rest));
|
|
6603
|
+
return promise.then(
|
|
6604
|
+
(response) => {
|
|
6605
|
+
if (isStream) {
|
|
6606
|
+
return wrapAsyncIterableStream(response, span2);
|
|
6607
|
+
}
|
|
6608
|
+
finalizeChatResponse(span2, response);
|
|
6609
|
+
return response;
|
|
6610
|
+
},
|
|
6611
|
+
(err) => {
|
|
6612
|
+
recordError(span2, err);
|
|
6613
|
+
throw err;
|
|
6614
|
+
}
|
|
6615
|
+
);
|
|
6616
|
+
};
|
|
6617
|
+
}
|
|
6618
|
+
function tracedResponsesCreate(original) {
|
|
6619
|
+
return function(opts, ...rest) {
|
|
6620
|
+
const tracer = import_api9.trace.getTracer(TRACER_NAME3);
|
|
6621
|
+
const model = opts?.model ?? "";
|
|
6622
|
+
const span2 = tracer.startSpan("openai.responses.create", {
|
|
6623
|
+
attributes: {
|
|
6624
|
+
"neatlogs.span.kind": "LLM",
|
|
6625
|
+
"neatlogs.llm.provider": "openai",
|
|
6626
|
+
"neatlogs.llm.system": "openai",
|
|
6627
|
+
"neatlogs.llm.model_name": model,
|
|
6628
|
+
"input.value": safeStringify3(opts?.input ?? "")
|
|
6629
|
+
}
|
|
6630
|
+
}, import_api9.context.active());
|
|
6631
|
+
const ctx = import_api9.trace.setSpan(import_api9.context.active(), span2);
|
|
6632
|
+
const promise = import_api9.context.with(ctx, () => original(opts, ...rest));
|
|
6633
|
+
return promise.then(
|
|
6634
|
+
(response) => {
|
|
6635
|
+
if (response?.output_text) {
|
|
6636
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
6637
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", response.output_text);
|
|
6638
|
+
}
|
|
6639
|
+
if (response?.model) span2.setAttribute("neatlogs.llm.model_name", response.model);
|
|
6640
|
+
if (response?.usage) {
|
|
6641
|
+
if (response.usage.input_tokens != null) span2.setAttribute("neatlogs.llm.token_count.prompt", response.usage.input_tokens);
|
|
6642
|
+
if (response.usage.output_tokens != null) span2.setAttribute("neatlogs.llm.token_count.completion", response.usage.output_tokens);
|
|
6643
|
+
}
|
|
6644
|
+
span2.setStatus({ code: import_api9.SpanStatusCode.OK });
|
|
6645
|
+
span2.end();
|
|
6646
|
+
return response;
|
|
6647
|
+
},
|
|
6648
|
+
(err) => {
|
|
6649
|
+
recordError(span2, err);
|
|
6650
|
+
throw err;
|
|
6651
|
+
}
|
|
6652
|
+
);
|
|
6653
|
+
};
|
|
6654
|
+
}
|
|
6655
|
+
function wrapAsyncIterableStream(stream, span2) {
|
|
6656
|
+
const chunks = [];
|
|
6657
|
+
const originalAsyncIterator = stream[Symbol.asyncIterator]?.bind(stream);
|
|
6658
|
+
if (!originalAsyncIterator) {
|
|
6659
|
+
span2.setStatus({ code: import_api9.SpanStatusCode.OK });
|
|
6660
|
+
span2.end();
|
|
6661
|
+
return stream;
|
|
6662
|
+
}
|
|
6663
|
+
const wrapped = Object.create(Object.getPrototypeOf(stream));
|
|
6664
|
+
Object.assign(wrapped, stream);
|
|
6665
|
+
wrapped[Symbol.asyncIterator] = function() {
|
|
6666
|
+
const iterator = originalAsyncIterator();
|
|
6667
|
+
return {
|
|
6668
|
+
async next() {
|
|
6669
|
+
try {
|
|
6670
|
+
const result = await iterator.next();
|
|
6671
|
+
if (result.done) {
|
|
6672
|
+
finalizeStreamChunks(span2, chunks);
|
|
6673
|
+
return result;
|
|
6674
|
+
}
|
|
6675
|
+
chunks.push(result.value);
|
|
6676
|
+
return result;
|
|
6677
|
+
} catch (err) {
|
|
6678
|
+
recordError(span2, err);
|
|
6679
|
+
throw err;
|
|
6680
|
+
}
|
|
6681
|
+
},
|
|
6682
|
+
async return(value) {
|
|
6683
|
+
finalizeStreamChunks(span2, chunks);
|
|
6684
|
+
return iterator.return?.(value) ?? { done: true, value: void 0 };
|
|
6685
|
+
},
|
|
6686
|
+
async throw(err) {
|
|
6687
|
+
recordError(span2, err);
|
|
6688
|
+
return iterator.throw?.(err) ?? { done: true, value: void 0 };
|
|
6689
|
+
}
|
|
6690
|
+
};
|
|
6691
|
+
};
|
|
6692
|
+
return wrapped;
|
|
6693
|
+
}
|
|
6694
|
+
function finalizeStreamChunks(span2, chunks) {
|
|
6695
|
+
const textParts = [];
|
|
6696
|
+
const toolCallsAcc = {};
|
|
6697
|
+
let finishReason = "";
|
|
6698
|
+
let model = "";
|
|
6699
|
+
let usage = null;
|
|
6700
|
+
for (const chunk of chunks) {
|
|
6701
|
+
if (!chunk?.choices?.length) {
|
|
6702
|
+
if (chunk?.usage) usage = chunk.usage;
|
|
6703
|
+
continue;
|
|
6704
|
+
}
|
|
6705
|
+
const choice = chunk.choices[0];
|
|
6706
|
+
const delta = choice?.delta;
|
|
6707
|
+
if (delta?.content) textParts.push(delta.content);
|
|
6708
|
+
if (delta?.tool_calls) {
|
|
6709
|
+
for (const tc of delta.tool_calls) {
|
|
6710
|
+
const idx = tc.index ?? 0;
|
|
6711
|
+
if (!toolCallsAcc[idx]) toolCallsAcc[idx] = { id: "", name: "", arguments: "" };
|
|
6712
|
+
if (tc.id) toolCallsAcc[idx].id = tc.id;
|
|
6713
|
+
if (tc.function?.name) toolCallsAcc[idx].name = tc.function.name;
|
|
6714
|
+
if (tc.function?.arguments) toolCallsAcc[idx].arguments += tc.function.arguments;
|
|
6715
|
+
}
|
|
6716
|
+
}
|
|
6717
|
+
if (choice?.finish_reason) finishReason = choice.finish_reason;
|
|
6718
|
+
if (chunk?.model) model = chunk.model;
|
|
6719
|
+
}
|
|
6720
|
+
const fullText = textParts.join("");
|
|
6721
|
+
if (fullText) {
|
|
6722
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
6723
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", fullText);
|
|
6724
|
+
}
|
|
6725
|
+
let j = 0;
|
|
6726
|
+
for (const tc of Object.values(toolCallsAcc)) {
|
|
6727
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, tc.id);
|
|
6728
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.name);
|
|
6729
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, tc.arguments);
|
|
6730
|
+
j++;
|
|
6731
|
+
}
|
|
6732
|
+
if (model) span2.setAttribute("neatlogs.llm.model_name", model);
|
|
6733
|
+
if (finishReason) span2.setAttribute("neatlogs.llm.finish_reason", finishReason);
|
|
6734
|
+
if (usage) {
|
|
6735
|
+
if (usage.prompt_tokens != null) span2.setAttribute("neatlogs.llm.token_count.prompt", usage.prompt_tokens);
|
|
6736
|
+
if (usage.completion_tokens != null) span2.setAttribute("neatlogs.llm.token_count.completion", usage.completion_tokens);
|
|
6737
|
+
if (usage.total_tokens != null) span2.setAttribute("neatlogs.llm.token_count.total", usage.total_tokens);
|
|
6738
|
+
if (usage.prompt_tokens_details?.cached_tokens != null) {
|
|
6739
|
+
span2.setAttribute("neatlogs.llm.token_count.cache_read", usage.prompt_tokens_details.cached_tokens);
|
|
6740
|
+
}
|
|
6741
|
+
if (usage.completion_tokens_details?.reasoning_tokens != null) {
|
|
6742
|
+
span2.setAttribute("neatlogs.llm.token_count.reasoning", usage.completion_tokens_details.reasoning_tokens);
|
|
6743
|
+
}
|
|
6744
|
+
}
|
|
6745
|
+
span2.setStatus({ code: import_api9.SpanStatusCode.OK });
|
|
6746
|
+
span2.end();
|
|
6747
|
+
}
|
|
6748
|
+
function finalizeChatResponse(span2, response) {
|
|
6749
|
+
const choices = response?.choices ?? [];
|
|
6750
|
+
for (let i = 0; i < choices.length; i++) {
|
|
6751
|
+
const message = choices[i]?.message;
|
|
6752
|
+
if (!message) continue;
|
|
6753
|
+
span2.setAttribute(`neatlogs.llm.output_messages.${i}.role`, "assistant");
|
|
6754
|
+
if (message.content) {
|
|
6755
|
+
span2.setAttribute(`neatlogs.llm.output_messages.${i}.content`, message.content);
|
|
6756
|
+
}
|
|
6757
|
+
if (message.tool_calls) {
|
|
6758
|
+
for (let j = 0; j < message.tool_calls.length; j++) {
|
|
6759
|
+
const tc = message.tool_calls[j];
|
|
6760
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, tc.id ?? "");
|
|
6761
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.function?.name ?? "");
|
|
6762
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, tc.function?.arguments ?? "");
|
|
6763
|
+
}
|
|
6764
|
+
}
|
|
6765
|
+
if (choices[i].finish_reason) {
|
|
6766
|
+
span2.setAttribute("neatlogs.llm.finish_reason", choices[i].finish_reason);
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
const usage = response?.usage;
|
|
6770
|
+
if (usage) {
|
|
6771
|
+
if (usage.prompt_tokens != null) span2.setAttribute("neatlogs.llm.token_count.prompt", usage.prompt_tokens);
|
|
6772
|
+
if (usage.completion_tokens != null) span2.setAttribute("neatlogs.llm.token_count.completion", usage.completion_tokens);
|
|
6773
|
+
if (usage.total_tokens != null) span2.setAttribute("neatlogs.llm.token_count.total", usage.total_tokens);
|
|
6774
|
+
if (usage.prompt_tokens_details?.cached_tokens != null) {
|
|
6775
|
+
span2.setAttribute("neatlogs.llm.token_count.cache_read", usage.prompt_tokens_details.cached_tokens);
|
|
6776
|
+
}
|
|
6777
|
+
if (usage.completion_tokens_details?.reasoning_tokens != null) {
|
|
6778
|
+
span2.setAttribute("neatlogs.llm.token_count.reasoning", usage.completion_tokens_details.reasoning_tokens);
|
|
6779
|
+
}
|
|
6780
|
+
}
|
|
6781
|
+
if (response?.model) span2.setAttribute("neatlogs.llm.model_name", response.model);
|
|
6782
|
+
span2.setStatus({ code: import_api9.SpanStatusCode.OK });
|
|
6783
|
+
span2.end();
|
|
6784
|
+
}
|
|
6785
|
+
function setInvocationParams(span2, opts) {
|
|
6786
|
+
if (opts?.temperature != null) span2.setAttribute("neatlogs.llm.temperature", opts.temperature);
|
|
6787
|
+
if (opts?.top_p != null) span2.setAttribute("neatlogs.llm.top_p", opts.top_p);
|
|
6788
|
+
if (opts?.max_tokens != null) span2.setAttribute("neatlogs.llm.max_tokens", opts.max_tokens);
|
|
6789
|
+
if (opts?.frequency_penalty != null) span2.setAttribute("neatlogs.llm.frequency_penalty", opts.frequency_penalty);
|
|
6790
|
+
if (opts?.presence_penalty != null) span2.setAttribute("neatlogs.llm.presence_penalty", opts.presence_penalty);
|
|
6791
|
+
if (opts?.stop) span2.setAttribute("neatlogs.llm.stop_sequences", safeStringify3(opts.stop));
|
|
6792
|
+
}
|
|
6793
|
+
function safeStringify3(value) {
|
|
6794
|
+
try {
|
|
6795
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
6796
|
+
} catch {
|
|
6797
|
+
return "";
|
|
6798
|
+
}
|
|
6799
|
+
}
|
|
6800
|
+
function recordError(span2, err) {
|
|
6801
|
+
if (err instanceof Error) {
|
|
6802
|
+
span2.setStatus({ code: import_api9.SpanStatusCode.ERROR, message: err.message });
|
|
6803
|
+
span2.recordException(err);
|
|
6804
|
+
} else {
|
|
6805
|
+
span2.setStatus({ code: import_api9.SpanStatusCode.ERROR, message: String(err) });
|
|
6806
|
+
}
|
|
6807
|
+
span2.end();
|
|
6808
|
+
}
|
|
6809
|
+
|
|
6810
|
+
// src/anthropic.ts
|
|
6811
|
+
var import_api10 = require("@opentelemetry/api");
|
|
6812
|
+
var TRACER_NAME4 = "neatlogs.anthropic";
|
|
6813
|
+
function wrapAnthropic(client) {
|
|
6814
|
+
return wrapNamespace2(client, []);
|
|
6815
|
+
}
|
|
6816
|
+
function traceTool2(name, fn) {
|
|
6817
|
+
return async function tracedTool(input) {
|
|
6818
|
+
const tracer = import_api10.trace.getTracer(TRACER_NAME4);
|
|
6819
|
+
return tracer.startActiveSpan(
|
|
6820
|
+
`tool.${name}`,
|
|
6821
|
+
{
|
|
6822
|
+
attributes: {
|
|
6823
|
+
"neatlogs.span.kind": "TOOL",
|
|
6824
|
+
"neatlogs.tool.name": name,
|
|
6825
|
+
"input.value": safeStringify4(input)
|
|
6826
|
+
}
|
|
6827
|
+
},
|
|
6828
|
+
import_api10.context.active(),
|
|
6829
|
+
async (span2) => {
|
|
6830
|
+
try {
|
|
6831
|
+
const result = await fn(input);
|
|
6832
|
+
span2.setAttribute("output.value", safeStringify4(result));
|
|
6833
|
+
span2.setStatus({ code: import_api10.SpanStatusCode.OK });
|
|
6834
|
+
return result;
|
|
6835
|
+
} catch (err) {
|
|
6836
|
+
recordError2(span2, err);
|
|
6837
|
+
throw err;
|
|
6838
|
+
} finally {
|
|
6839
|
+
span2.end();
|
|
6840
|
+
}
|
|
6841
|
+
}
|
|
6842
|
+
);
|
|
6843
|
+
};
|
|
6844
|
+
}
|
|
6845
|
+
function wrapNamespace2(target, path4) {
|
|
6846
|
+
return new Proxy(target, {
|
|
6847
|
+
get(obj, prop, receiver) {
|
|
6848
|
+
const value = Reflect.get(obj, prop, receiver);
|
|
6849
|
+
if (typeof prop === "symbol" || String(prop).startsWith("_")) return value;
|
|
6850
|
+
const currentPath = [...path4, String(prop)];
|
|
6851
|
+
const pathStr = currentPath.join(".");
|
|
6852
|
+
if (pathStr === "messages.create" && typeof value === "function") {
|
|
6853
|
+
return tracedMessagesCreate(value.bind(obj));
|
|
6854
|
+
}
|
|
6855
|
+
if (pathStr === "messages.stream" && typeof value === "function") {
|
|
6856
|
+
return tracedMessagesStream(value.bind(obj));
|
|
6857
|
+
}
|
|
6858
|
+
if (value && typeof value === "object" && !Array.isArray(value) && isNamespace2(currentPath)) {
|
|
6859
|
+
return wrapNamespace2(value, currentPath);
|
|
6860
|
+
}
|
|
6861
|
+
return value;
|
|
6862
|
+
}
|
|
6863
|
+
});
|
|
6864
|
+
}
|
|
6865
|
+
function isNamespace2(path4) {
|
|
6866
|
+
if (path4.length > 3) return false;
|
|
6867
|
+
const key = path4[path4.length - 1];
|
|
6868
|
+
return ["messages", "beta"].includes(key);
|
|
6869
|
+
}
|
|
6870
|
+
function tracedMessagesCreate(original) {
|
|
6871
|
+
return function(opts, ...rest) {
|
|
6872
|
+
const tracer = import_api10.trace.getTracer(TRACER_NAME4);
|
|
6873
|
+
const model = opts?.model ?? "";
|
|
6874
|
+
const messages = opts?.messages ?? [];
|
|
6875
|
+
const isStream = opts?.stream === true;
|
|
6876
|
+
const span2 = tracer.startSpan("anthropic.messages.create", {
|
|
6877
|
+
attributes: {
|
|
6878
|
+
"neatlogs.span.kind": "LLM",
|
|
6879
|
+
"neatlogs.llm.provider": "anthropic",
|
|
6880
|
+
"neatlogs.llm.system": "anthropic",
|
|
6881
|
+
"neatlogs.llm.model_name": model,
|
|
6882
|
+
"neatlogs.llm.is_streaming": isStream
|
|
6883
|
+
}
|
|
6884
|
+
}, import_api10.context.active());
|
|
6885
|
+
setInputMessages(span2, opts?.system, messages);
|
|
6886
|
+
setTools(span2, opts?.tools);
|
|
6887
|
+
setInvocationParams2(span2, opts);
|
|
6888
|
+
const ctx = import_api10.trace.setSpan(import_api10.context.active(), span2);
|
|
6889
|
+
const promise = import_api10.context.with(ctx, () => original(opts, ...rest));
|
|
6890
|
+
return promise.then(
|
|
6891
|
+
(response) => {
|
|
6892
|
+
if (isStream) {
|
|
6893
|
+
return wrapStreamIterable(response, span2);
|
|
6894
|
+
}
|
|
6895
|
+
finalizeMessageResponse(span2, response);
|
|
6896
|
+
return response;
|
|
6897
|
+
},
|
|
6898
|
+
(err) => {
|
|
6899
|
+
recordError2(span2, err);
|
|
6900
|
+
throw err;
|
|
6901
|
+
}
|
|
6902
|
+
);
|
|
6903
|
+
};
|
|
6904
|
+
}
|
|
6905
|
+
function tracedMessagesStream(original) {
|
|
6906
|
+
return function(opts, ...rest) {
|
|
6907
|
+
const tracer = import_api10.trace.getTracer(TRACER_NAME4);
|
|
6908
|
+
const model = opts?.model ?? "";
|
|
6909
|
+
const messages = opts?.messages ?? [];
|
|
6910
|
+
const span2 = tracer.startSpan("anthropic.messages.stream", {
|
|
6911
|
+
attributes: {
|
|
6912
|
+
"neatlogs.span.kind": "LLM",
|
|
6913
|
+
"neatlogs.llm.provider": "anthropic",
|
|
6914
|
+
"neatlogs.llm.system": "anthropic",
|
|
6915
|
+
"neatlogs.llm.model_name": model,
|
|
6916
|
+
"neatlogs.llm.is_streaming": true
|
|
6917
|
+
}
|
|
6918
|
+
}, import_api10.context.active());
|
|
6919
|
+
setInputMessages(span2, opts?.system, messages);
|
|
6920
|
+
setTools(span2, opts?.tools);
|
|
6921
|
+
setInvocationParams2(span2, opts);
|
|
6922
|
+
const ctx = import_api10.trace.setSpan(import_api10.context.active(), span2);
|
|
6923
|
+
const messageStream = import_api10.context.with(ctx, () => original(opts, ...rest));
|
|
6924
|
+
return wrapMessageStream(messageStream, span2);
|
|
6925
|
+
};
|
|
6926
|
+
}
|
|
6927
|
+
function wrapStreamIterable(stream, span2) {
|
|
6928
|
+
const events = [];
|
|
6929
|
+
const originalAsyncIterator = stream[Symbol.asyncIterator]?.bind(stream);
|
|
6930
|
+
if (!originalAsyncIterator) {
|
|
6931
|
+
span2.setStatus({ code: import_api10.SpanStatusCode.OK });
|
|
6932
|
+
span2.end();
|
|
6933
|
+
return stream;
|
|
6934
|
+
}
|
|
6935
|
+
const wrapped = Object.create(Object.getPrototypeOf(stream));
|
|
6936
|
+
Object.assign(wrapped, stream);
|
|
6937
|
+
wrapped[Symbol.asyncIterator] = function() {
|
|
6938
|
+
const iterator = originalAsyncIterator();
|
|
6939
|
+
return {
|
|
6940
|
+
async next() {
|
|
6941
|
+
try {
|
|
6942
|
+
const result = await iterator.next();
|
|
6943
|
+
if (result.done) {
|
|
6944
|
+
finalizeStreamEvents(span2, events);
|
|
6945
|
+
return result;
|
|
6946
|
+
}
|
|
6947
|
+
events.push(result.value);
|
|
6948
|
+
return result;
|
|
6949
|
+
} catch (err) {
|
|
6950
|
+
recordError2(span2, err);
|
|
6951
|
+
throw err;
|
|
6952
|
+
}
|
|
6953
|
+
},
|
|
6954
|
+
async return(value) {
|
|
6955
|
+
finalizeStreamEvents(span2, events);
|
|
6956
|
+
return iterator.return?.(value) ?? { done: true, value: void 0 };
|
|
6957
|
+
},
|
|
6958
|
+
async throw(err) {
|
|
6959
|
+
recordError2(span2, err);
|
|
6960
|
+
return iterator.throw?.(err) ?? { done: true, value: void 0 };
|
|
6961
|
+
}
|
|
6962
|
+
};
|
|
6963
|
+
};
|
|
6964
|
+
if (typeof stream.finalMessage === "function") {
|
|
6965
|
+
const origFinal = stream.finalMessage.bind(stream);
|
|
6966
|
+
wrapped.finalMessage = async function() {
|
|
6967
|
+
return origFinal();
|
|
6968
|
+
};
|
|
6969
|
+
}
|
|
6970
|
+
return wrapped;
|
|
6971
|
+
}
|
|
6972
|
+
function wrapMessageStream(messageStream, span2) {
|
|
6973
|
+
const origOn = messageStream.on?.bind(messageStream);
|
|
6974
|
+
if (origOn) {
|
|
6975
|
+
origOn("end", () => {
|
|
6976
|
+
const finalMsg = messageStream._finalMessage ?? messageStream.currentMessage;
|
|
6977
|
+
if (finalMsg) {
|
|
6978
|
+
finalizeMessageResponse(span2, finalMsg);
|
|
6979
|
+
} else {
|
|
6980
|
+
span2.setStatus({ code: import_api10.SpanStatusCode.OK });
|
|
6981
|
+
span2.end();
|
|
6982
|
+
}
|
|
6983
|
+
});
|
|
6984
|
+
origOn("error", (err) => {
|
|
6985
|
+
if (span2.isRecording()) recordError2(span2, err);
|
|
6986
|
+
});
|
|
6987
|
+
}
|
|
6988
|
+
if (typeof messageStream.finalMessage === "function") {
|
|
6989
|
+
const origFinal = messageStream.finalMessage.bind(messageStream);
|
|
6990
|
+
messageStream.finalMessage = async function() {
|
|
6991
|
+
const result = await origFinal();
|
|
6992
|
+
if (span2.isRecording()) {
|
|
6993
|
+
finalizeMessageResponse(span2, result);
|
|
6994
|
+
}
|
|
6995
|
+
return result;
|
|
6996
|
+
};
|
|
6997
|
+
}
|
|
6998
|
+
return messageStream;
|
|
6999
|
+
}
|
|
7000
|
+
function finalizeStreamEvents(span2, events) {
|
|
7001
|
+
const textParts = [];
|
|
7002
|
+
const thinkingParts = [];
|
|
7003
|
+
const toolCalls = [];
|
|
7004
|
+
let currentToolInput = "";
|
|
7005
|
+
let currentToolId = "";
|
|
7006
|
+
let currentToolName = "";
|
|
7007
|
+
let usage = null;
|
|
7008
|
+
let model = "";
|
|
7009
|
+
let stopReason = "";
|
|
7010
|
+
for (const event of events) {
|
|
7011
|
+
const type = event?.type ?? "";
|
|
7012
|
+
if (type === "content_block_delta") {
|
|
7013
|
+
const delta = event?.delta;
|
|
7014
|
+
if (delta?.type === "text_delta" && delta.text) textParts.push(delta.text);
|
|
7015
|
+
else if (delta?.type === "thinking_delta" && delta.thinking) thinkingParts.push(delta.thinking);
|
|
7016
|
+
else if (delta?.type === "input_json_delta" && delta.partial_json) currentToolInput += delta.partial_json;
|
|
7017
|
+
} else if (type === "content_block_start") {
|
|
7018
|
+
const block = event?.content_block;
|
|
7019
|
+
if (block?.type === "tool_use") {
|
|
7020
|
+
currentToolId = block.id ?? "";
|
|
7021
|
+
currentToolName = block.name ?? "";
|
|
7022
|
+
currentToolInput = "";
|
|
7023
|
+
}
|
|
7024
|
+
} else if (type === "content_block_stop") {
|
|
7025
|
+
if (currentToolName) {
|
|
7026
|
+
toolCalls.push({ id: currentToolId, name: currentToolName, input: currentToolInput });
|
|
7027
|
+
currentToolId = "";
|
|
7028
|
+
currentToolName = "";
|
|
7029
|
+
currentToolInput = "";
|
|
7030
|
+
}
|
|
7031
|
+
} else if (type === "message_start") {
|
|
7032
|
+
const msg = event?.message;
|
|
7033
|
+
if (msg?.model) model = msg.model;
|
|
7034
|
+
if (msg?.usage) usage = msg.usage;
|
|
7035
|
+
} else if (type === "message_delta") {
|
|
7036
|
+
const delta = event?.delta;
|
|
7037
|
+
if (delta?.stop_reason) stopReason = delta.stop_reason;
|
|
7038
|
+
if (event?.usage) usage = { ...usage ?? {}, ...event.usage };
|
|
7039
|
+
}
|
|
7040
|
+
}
|
|
7041
|
+
const fullText = textParts.join("");
|
|
7042
|
+
if (fullText) {
|
|
7043
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
7044
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", fullText);
|
|
7045
|
+
}
|
|
7046
|
+
const thinking = thinkingParts.join("");
|
|
7047
|
+
if (thinking) {
|
|
7048
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.thinking", thinking);
|
|
7049
|
+
}
|
|
7050
|
+
for (let j = 0; j < toolCalls.length; j++) {
|
|
7051
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, toolCalls[j].id);
|
|
7052
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, toolCalls[j].name);
|
|
7053
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, toolCalls[j].input);
|
|
7054
|
+
}
|
|
7055
|
+
if (model) span2.setAttribute("neatlogs.llm.model_name", model);
|
|
7056
|
+
if (stopReason) span2.setAttribute("neatlogs.llm.stop_reason", stopReason);
|
|
7057
|
+
setUsageAttrs(span2, usage);
|
|
7058
|
+
span2.setStatus({ code: import_api10.SpanStatusCode.OK });
|
|
7059
|
+
span2.end();
|
|
7060
|
+
}
|
|
7061
|
+
function finalizeMessageResponse(span2, response) {
|
|
7062
|
+
const content = response?.content ?? [];
|
|
7063
|
+
const textParts = [];
|
|
7064
|
+
const thinkingParts = [];
|
|
7065
|
+
const toolCalls = [];
|
|
7066
|
+
for (const block of content) {
|
|
7067
|
+
if (block.type === "text" && block.text) textParts.push(block.text);
|
|
7068
|
+
else if (block.type === "thinking" && block.thinking) thinkingParts.push(block.thinking);
|
|
7069
|
+
else if (block.type === "tool_use") {
|
|
7070
|
+
toolCalls.push({
|
|
7071
|
+
id: block.id ?? "",
|
|
7072
|
+
name: block.name ?? "",
|
|
7073
|
+
input: safeStringify4(block.input ?? {})
|
|
7074
|
+
});
|
|
7075
|
+
}
|
|
7076
|
+
}
|
|
7077
|
+
if (textParts.length) {
|
|
7078
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
7079
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", textParts.join(""));
|
|
7080
|
+
}
|
|
7081
|
+
if (thinkingParts.length) {
|
|
7082
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.thinking", thinkingParts.join(""));
|
|
7083
|
+
}
|
|
7084
|
+
for (let j = 0; j < toolCalls.length; j++) {
|
|
7085
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, toolCalls[j].id);
|
|
7086
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, toolCalls[j].name);
|
|
7087
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, toolCalls[j].input);
|
|
7088
|
+
}
|
|
7089
|
+
setUsageAttrs(span2, response?.usage);
|
|
7090
|
+
if (response?.model) span2.setAttribute("neatlogs.llm.model_name", response.model);
|
|
7091
|
+
if (response?.stop_reason) span2.setAttribute("neatlogs.llm.stop_reason", response.stop_reason);
|
|
7092
|
+
span2.setStatus({ code: import_api10.SpanStatusCode.OK });
|
|
7093
|
+
span2.end();
|
|
7094
|
+
}
|
|
7095
|
+
function setInputMessages(span2, system, messages) {
|
|
7096
|
+
let idx = 0;
|
|
7097
|
+
if (system) {
|
|
7098
|
+
const content = typeof system === "string" ? system : safeStringify4(system);
|
|
7099
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, "system");
|
|
7100
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, content);
|
|
7101
|
+
idx++;
|
|
7102
|
+
}
|
|
7103
|
+
for (const msg of messages) {
|
|
7104
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, msg.role ?? "");
|
|
7105
|
+
if (typeof msg.content === "string") {
|
|
7106
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, msg.content);
|
|
7107
|
+
} else if (msg.content) {
|
|
7108
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, safeStringify4(msg.content));
|
|
7109
|
+
}
|
|
7110
|
+
idx++;
|
|
7111
|
+
}
|
|
7112
|
+
}
|
|
7113
|
+
function setTools(span2, tools) {
|
|
7114
|
+
if (!tools) return;
|
|
7115
|
+
for (let i = 0; i < tools.length; i++) {
|
|
7116
|
+
const tool = tools[i];
|
|
7117
|
+
span2.setAttribute(`neatlogs.llm.tools.${i}.name`, tool.name ?? "");
|
|
7118
|
+
if (tool.description) span2.setAttribute(`neatlogs.llm.tools.${i}.description`, tool.description);
|
|
7119
|
+
if (tool.input_schema) span2.setAttribute(`neatlogs.llm.tools.${i}.input_schema`, safeStringify4(tool.input_schema));
|
|
7120
|
+
}
|
|
7121
|
+
}
|
|
7122
|
+
function setInvocationParams2(span2, opts) {
|
|
7123
|
+
if (opts?.temperature != null) span2.setAttribute("neatlogs.llm.temperature", opts.temperature);
|
|
7124
|
+
if (opts?.top_p != null) span2.setAttribute("neatlogs.llm.top_p", opts.top_p);
|
|
7125
|
+
if (opts?.top_k != null) span2.setAttribute("neatlogs.llm.top_k", opts.top_k);
|
|
7126
|
+
if (opts?.max_tokens != null) span2.setAttribute("neatlogs.llm.max_tokens", opts.max_tokens);
|
|
7127
|
+
if (opts?.stop_sequences) span2.setAttribute("neatlogs.llm.stop_sequences", safeStringify4(opts.stop_sequences));
|
|
7128
|
+
}
|
|
7129
|
+
function setUsageAttrs(span2, usage) {
|
|
7130
|
+
if (!usage) return;
|
|
7131
|
+
if (usage.input_tokens != null) span2.setAttribute("neatlogs.llm.token_count.prompt", usage.input_tokens);
|
|
7132
|
+
if (usage.output_tokens != null) span2.setAttribute("neatlogs.llm.token_count.completion", usage.output_tokens);
|
|
7133
|
+
if (usage.cache_read_input_tokens != null) span2.setAttribute("neatlogs.llm.token_count.cache_read", usage.cache_read_input_tokens);
|
|
7134
|
+
if (usage.cache_creation_input_tokens != null) span2.setAttribute("neatlogs.llm.token_count.cache_write", usage.cache_creation_input_tokens);
|
|
7135
|
+
}
|
|
7136
|
+
function safeStringify4(value) {
|
|
7137
|
+
try {
|
|
7138
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
7139
|
+
} catch {
|
|
7140
|
+
return "";
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
7143
|
+
function recordError2(span2, err) {
|
|
7144
|
+
if (err instanceof Error) {
|
|
7145
|
+
span2.setStatus({ code: import_api10.SpanStatusCode.ERROR, message: err.message });
|
|
7146
|
+
span2.recordException(err);
|
|
7147
|
+
} else {
|
|
7148
|
+
span2.setStatus({ code: import_api10.SpanStatusCode.ERROR, message: String(err) });
|
|
7149
|
+
}
|
|
7150
|
+
span2.end();
|
|
7151
|
+
}
|
|
7152
|
+
|
|
7153
|
+
// src/langchain.ts
|
|
7154
|
+
var import_api11 = require("@opentelemetry/api");
|
|
7155
|
+
var TRACER_NAME5 = "neatlogs.langchain";
|
|
7156
|
+
function langchainHandler(opts) {
|
|
7157
|
+
return new NeatlogsCallbackHandler(opts);
|
|
7158
|
+
}
|
|
7159
|
+
var NeatlogsCallbackHandler = class {
|
|
7160
|
+
name = "neatlogs";
|
|
7161
|
+
_spans = /* @__PURE__ */ new Map();
|
|
7162
|
+
_workflowName;
|
|
7163
|
+
constructor(opts) {
|
|
7164
|
+
this._workflowName = opts?.workflowName;
|
|
7165
|
+
}
|
|
7166
|
+
// --- Chain/Graph callbacks ---
|
|
7167
|
+
async handleChainStart(serialized, inputs, runId, parentRunId, tags, metadata) {
|
|
7168
|
+
const tracer = import_api11.trace.getTracer(TRACER_NAME5);
|
|
7169
|
+
const name = serialized?.name ?? serialized?.id?.at(-1) ?? "chain";
|
|
7170
|
+
const parentSpan = parentRunId ? this._spans.get(parentRunId) : void 0;
|
|
7171
|
+
const parentCtx = parentSpan ? import_api11.trace.setSpan(import_api11.context.active(), parentSpan) : import_api11.context.active();
|
|
7172
|
+
const attrs = {
|
|
7173
|
+
"neatlogs.span.kind": "CHAIN",
|
|
7174
|
+
"neatlogs.chain.name": name
|
|
7175
|
+
};
|
|
7176
|
+
if (this._workflowName) attrs["neatlogs.workflow.name"] = this._workflowName;
|
|
7177
|
+
if (inputs) attrs["input.value"] = safeStringify5(inputs).slice(0, 1e4);
|
|
7178
|
+
if (tags?.length) attrs["neatlogs.tags"] = tags.join(",");
|
|
7179
|
+
const span2 = tracer.startSpan(`langchain.chain.${name}`, { attributes: attrs }, parentCtx);
|
|
7180
|
+
this._spans.set(runId, span2);
|
|
7181
|
+
}
|
|
7182
|
+
async handleChainEnd(outputs, runId) {
|
|
7183
|
+
const span2 = this._spans.get(runId);
|
|
7184
|
+
if (!span2) return;
|
|
7185
|
+
if (outputs) span2.setAttribute("output.value", safeStringify5(outputs).slice(0, 1e4));
|
|
7186
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.OK });
|
|
7187
|
+
span2.end();
|
|
7188
|
+
this._spans.delete(runId);
|
|
7189
|
+
}
|
|
7190
|
+
async handleChainError(error, runId) {
|
|
7191
|
+
const span2 = this._spans.get(runId);
|
|
7192
|
+
if (!span2) return;
|
|
7193
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.ERROR, message: error.message });
|
|
7194
|
+
span2.recordException(error);
|
|
7195
|
+
span2.end();
|
|
7196
|
+
this._spans.delete(runId);
|
|
7197
|
+
}
|
|
7198
|
+
// --- LLM callbacks ---
|
|
7199
|
+
async handleLLMStart(serialized, prompts, runId, parentRunId, extraParams) {
|
|
7200
|
+
const tracer = import_api11.trace.getTracer(TRACER_NAME5);
|
|
7201
|
+
const model = serialized?.kwargs?.model_name ?? serialized?.kwargs?.model ?? serialized?.name ?? "";
|
|
7202
|
+
const parentSpan = parentRunId ? this._spans.get(parentRunId) : void 0;
|
|
7203
|
+
const parentCtx = parentSpan ? import_api11.trace.setSpan(import_api11.context.active(), parentSpan) : import_api11.context.active();
|
|
7204
|
+
const attrs = {
|
|
7205
|
+
"neatlogs.span.kind": "LLM",
|
|
7206
|
+
"neatlogs.llm.provider": detectProvider(model),
|
|
7207
|
+
"neatlogs.llm.model_name": model
|
|
7208
|
+
};
|
|
7209
|
+
for (let i = 0; i < prompts.length; i++) {
|
|
7210
|
+
attrs[`neatlogs.llm.input_messages.${i}.role`] = "user";
|
|
7211
|
+
attrs[`neatlogs.llm.input_messages.${i}.content`] = prompts[i].slice(0, 1e4);
|
|
7212
|
+
}
|
|
7213
|
+
if (extraParams?.invocation_params) {
|
|
7214
|
+
const p = extraParams.invocation_params;
|
|
7215
|
+
if (p.temperature != null) attrs["neatlogs.llm.temperature"] = p.temperature;
|
|
7216
|
+
if (p.max_tokens != null) attrs["neatlogs.llm.max_tokens"] = p.max_tokens;
|
|
7217
|
+
if (p.model_name) attrs["neatlogs.llm.model_name"] = p.model_name;
|
|
7218
|
+
}
|
|
7219
|
+
const span2 = tracer.startSpan("langchain.llm", { attributes: attrs }, parentCtx);
|
|
7220
|
+
this._spans.set(runId, span2);
|
|
7221
|
+
}
|
|
7222
|
+
async handleChatModelStart(serialized, messages, runId, parentRunId, extraParams) {
|
|
7223
|
+
const tracer = import_api11.trace.getTracer(TRACER_NAME5);
|
|
7224
|
+
const model = serialized?.kwargs?.model_name ?? serialized?.kwargs?.model ?? serialized?.name ?? "";
|
|
7225
|
+
const parentSpan = parentRunId ? this._spans.get(parentRunId) : void 0;
|
|
7226
|
+
const parentCtx = parentSpan ? import_api11.trace.setSpan(import_api11.context.active(), parentSpan) : import_api11.context.active();
|
|
7227
|
+
const attrs = {
|
|
7228
|
+
"neatlogs.span.kind": "LLM",
|
|
7229
|
+
"neatlogs.llm.provider": detectProvider(model),
|
|
7230
|
+
"neatlogs.llm.model_name": model
|
|
7231
|
+
};
|
|
7232
|
+
const flatMessages = messages.flat();
|
|
7233
|
+
for (let i = 0; i < flatMessages.length; i++) {
|
|
7234
|
+
const msg = flatMessages[i];
|
|
7235
|
+
const role = msg?.role ?? msg?._getType?.() ?? msg?.constructor?.name ?? "unknown";
|
|
7236
|
+
const content = typeof msg?.content === "string" ? msg.content : safeStringify5(msg?.content);
|
|
7237
|
+
attrs[`neatlogs.llm.input_messages.${i}.role`] = mapRole(role);
|
|
7238
|
+
attrs[`neatlogs.llm.input_messages.${i}.content`] = content.slice(0, 1e4);
|
|
7239
|
+
}
|
|
7240
|
+
if (extraParams?.invocation_params) {
|
|
7241
|
+
const p = extraParams.invocation_params;
|
|
7242
|
+
if (p.temperature != null) attrs["neatlogs.llm.temperature"] = p.temperature;
|
|
7243
|
+
if (p.max_tokens != null) attrs["neatlogs.llm.max_tokens"] = p.max_tokens;
|
|
7244
|
+
if (p.model_name) attrs["neatlogs.llm.model_name"] = p.model_name;
|
|
7245
|
+
}
|
|
7246
|
+
const span2 = tracer.startSpan("langchain.chat_model", { attributes: attrs }, parentCtx);
|
|
7247
|
+
this._spans.set(runId, span2);
|
|
7248
|
+
}
|
|
7249
|
+
async handleLLMEnd(output, runId) {
|
|
7250
|
+
const span2 = this._spans.get(runId);
|
|
7251
|
+
if (!span2) return;
|
|
7252
|
+
const generations = output?.generations ?? [];
|
|
7253
|
+
for (let i = 0; i < generations.length; i++) {
|
|
7254
|
+
const gen = generations[i];
|
|
7255
|
+
if (!Array.isArray(gen)) continue;
|
|
7256
|
+
for (let j = 0; j < gen.length; j++) {
|
|
7257
|
+
const msg = gen[j]?.message ?? gen[j];
|
|
7258
|
+
const content = msg?.content ?? msg?.text ?? "";
|
|
7259
|
+
span2.setAttribute(`neatlogs.llm.output_messages.${i}.role`, "assistant");
|
|
7260
|
+
span2.setAttribute(`neatlogs.llm.output_messages.${i}.content`, String(content).slice(0, 1e4));
|
|
7261
|
+
const toolCalls = msg?.tool_calls ?? msg?.additional_kwargs?.tool_calls;
|
|
7262
|
+
if (toolCalls && Array.isArray(toolCalls)) {
|
|
7263
|
+
for (let k = 0; k < toolCalls.length; k++) {
|
|
7264
|
+
const tc = toolCalls[k];
|
|
7265
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${k}.id`, tc.id ?? "");
|
|
7266
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${k}.name`, tc.name ?? tc.function?.name ?? "");
|
|
7267
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${k}.arguments`, tc.args ? safeStringify5(tc.args) : tc.function?.arguments ?? "");
|
|
7268
|
+
}
|
|
7269
|
+
}
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
const usage = output?.llmOutput?.tokenUsage ?? output?.llmOutput?.usage;
|
|
7273
|
+
if (usage) {
|
|
7274
|
+
if (usage.promptTokens != null || usage.prompt_tokens != null) {
|
|
7275
|
+
span2.setAttribute("neatlogs.llm.token_count.prompt", usage.promptTokens ?? usage.prompt_tokens);
|
|
7276
|
+
}
|
|
7277
|
+
if (usage.completionTokens != null || usage.completion_tokens != null) {
|
|
7278
|
+
span2.setAttribute("neatlogs.llm.token_count.completion", usage.completionTokens ?? usage.completion_tokens);
|
|
7279
|
+
}
|
|
7280
|
+
if (usage.totalTokens != null || usage.total_tokens != null) {
|
|
7281
|
+
span2.setAttribute("neatlogs.llm.token_count.total", usage.totalTokens ?? usage.total_tokens);
|
|
7282
|
+
}
|
|
7283
|
+
}
|
|
7284
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.OK });
|
|
7285
|
+
span2.end();
|
|
7286
|
+
this._spans.delete(runId);
|
|
7287
|
+
}
|
|
7288
|
+
async handleLLMNewToken(_token, _idx, _runId) {
|
|
7289
|
+
}
|
|
7290
|
+
async handleLLMError(error, runId) {
|
|
7291
|
+
const span2 = this._spans.get(runId);
|
|
7292
|
+
if (!span2) return;
|
|
7293
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.ERROR, message: error.message });
|
|
7294
|
+
span2.recordException(error);
|
|
7295
|
+
span2.end();
|
|
7296
|
+
this._spans.delete(runId);
|
|
7297
|
+
}
|
|
7298
|
+
// --- Tool callbacks ---
|
|
7299
|
+
async handleToolStart(serialized, input, runId, parentRunId, _tags, _metadata, runName, toolCallId) {
|
|
7300
|
+
const tracer = import_api11.trace.getTracer(TRACER_NAME5);
|
|
7301
|
+
const name = serialized?.name || runName || (Array.isArray(serialized?.id) ? serialized.id[serialized.id.length - 1] : void 0) || "tool";
|
|
7302
|
+
const parentSpan = parentRunId ? this._spans.get(parentRunId) : void 0;
|
|
7303
|
+
const parentCtx = parentSpan ? import_api11.trace.setSpan(import_api11.context.active(), parentSpan) : import_api11.context.active();
|
|
7304
|
+
const attrs = {
|
|
7305
|
+
"neatlogs.span.kind": "TOOL",
|
|
7306
|
+
"neatlogs.tool.name": name,
|
|
7307
|
+
"input.value": String(input).slice(0, 1e4)
|
|
7308
|
+
};
|
|
7309
|
+
if (toolCallId) attrs["neatlogs.tool_call.id"] = toolCallId;
|
|
7310
|
+
const span2 = tracer.startSpan(`langchain.tool.${name}`, { attributes: attrs }, parentCtx);
|
|
7311
|
+
this._spans.set(runId, span2);
|
|
7312
|
+
}
|
|
7313
|
+
async handleToolEnd(output, runId) {
|
|
7314
|
+
const span2 = this._spans.get(runId);
|
|
7315
|
+
if (!span2) return;
|
|
7316
|
+
span2.setAttribute("output.value", String(output).slice(0, 1e4));
|
|
7317
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.OK });
|
|
7318
|
+
span2.end();
|
|
7319
|
+
this._spans.delete(runId);
|
|
7320
|
+
}
|
|
7321
|
+
async handleToolError(error, runId) {
|
|
7322
|
+
const span2 = this._spans.get(runId);
|
|
7323
|
+
if (!span2) return;
|
|
7324
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.ERROR, message: error.message });
|
|
7325
|
+
span2.recordException(error);
|
|
7326
|
+
span2.end();
|
|
7327
|
+
this._spans.delete(runId);
|
|
7328
|
+
}
|
|
7329
|
+
// --- Retriever callbacks ---
|
|
7330
|
+
async handleRetrieverStart(serialized, query, runId, parentRunId) {
|
|
7331
|
+
const tracer = import_api11.trace.getTracer(TRACER_NAME5);
|
|
7332
|
+
const name = serialized?.name ?? "retriever";
|
|
7333
|
+
const parentSpan = parentRunId ? this._spans.get(parentRunId) : void 0;
|
|
7334
|
+
const parentCtx = parentSpan ? import_api11.trace.setSpan(import_api11.context.active(), parentSpan) : import_api11.context.active();
|
|
7335
|
+
const attrs = {
|
|
7336
|
+
"neatlogs.span.kind": "RETRIEVER",
|
|
7337
|
+
"neatlogs.retriever.name": name,
|
|
7338
|
+
"input.value": query.slice(0, 1e4)
|
|
7339
|
+
};
|
|
7340
|
+
const span2 = tracer.startSpan(`langchain.retriever.${name}`, { attributes: attrs }, parentCtx);
|
|
7341
|
+
this._spans.set(runId, span2);
|
|
7342
|
+
}
|
|
7343
|
+
async handleRetrieverEnd(documents, runId) {
|
|
7344
|
+
const span2 = this._spans.get(runId);
|
|
7345
|
+
if (!span2) return;
|
|
7346
|
+
if (documents?.length) {
|
|
7347
|
+
span2.setAttribute("neatlogs.retriever.document_count", documents.length);
|
|
7348
|
+
for (let i = 0; i < Math.min(documents.length, 10); i++) {
|
|
7349
|
+
const doc = documents[i];
|
|
7350
|
+
if (doc?.pageContent) {
|
|
7351
|
+
span2.setAttribute(`neatlogs.retriever.documents.${i}.content`, doc.pageContent.slice(0, 2e3));
|
|
7352
|
+
}
|
|
7353
|
+
}
|
|
7354
|
+
}
|
|
7355
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.OK });
|
|
7356
|
+
span2.end();
|
|
7357
|
+
this._spans.delete(runId);
|
|
7358
|
+
}
|
|
7359
|
+
async handleRetrieverError(error, runId) {
|
|
7360
|
+
const span2 = this._spans.get(runId);
|
|
7361
|
+
if (!span2) return;
|
|
7362
|
+
span2.setStatus({ code: import_api11.SpanStatusCode.ERROR, message: error.message });
|
|
7363
|
+
span2.recordException(error);
|
|
7364
|
+
span2.end();
|
|
7365
|
+
this._spans.delete(runId);
|
|
7366
|
+
}
|
|
7367
|
+
};
|
|
7368
|
+
function detectProvider(model) {
|
|
7369
|
+
const m = model.toLowerCase();
|
|
7370
|
+
if (m.includes("gpt") || m.includes("o1") || m.includes("o3") || m.includes("o4")) return "openai";
|
|
7371
|
+
if (m.includes("claude")) return "anthropic";
|
|
7372
|
+
if (m.includes("gemini")) return "google";
|
|
7373
|
+
if (m.includes("command")) return "cohere";
|
|
7374
|
+
if (m.includes("llama") || m.includes("mixtral")) return "meta";
|
|
7375
|
+
return "unknown";
|
|
7376
|
+
}
|
|
7377
|
+
function mapRole(role) {
|
|
7378
|
+
const r = role.toLowerCase();
|
|
7379
|
+
if (r === "human" || r === "humanmessage") return "user";
|
|
7380
|
+
if (r === "ai" || r === "aimessage") return "assistant";
|
|
7381
|
+
if (r === "system" || r === "systemmessage") return "system";
|
|
7382
|
+
if (r === "function" || r === "functionmessage") return "function";
|
|
7383
|
+
if (r === "tool" || r === "toolmessage") return "tool";
|
|
7384
|
+
return role;
|
|
7385
|
+
}
|
|
7386
|
+
function safeStringify5(value) {
|
|
7387
|
+
try {
|
|
7388
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
7389
|
+
} catch {
|
|
7390
|
+
return "";
|
|
7391
|
+
}
|
|
7392
|
+
}
|
|
7393
|
+
|
|
7394
|
+
// src/strands.ts
|
|
7395
|
+
var PATCH_FLAG = "_neatlogs_patched";
|
|
7396
|
+
function strandsHooks(agent) {
|
|
7397
|
+
installEventHookFromAgent(agent);
|
|
7398
|
+
if (agent && typeof agent === "object") {
|
|
7399
|
+
try {
|
|
7400
|
+
Object.defineProperty(agent, PATCH_FLAG, {
|
|
7401
|
+
value: true,
|
|
7402
|
+
enumerable: false,
|
|
7403
|
+
configurable: true
|
|
7404
|
+
});
|
|
7405
|
+
} catch {
|
|
7406
|
+
agent[PATCH_FLAG] = true;
|
|
7407
|
+
}
|
|
7408
|
+
}
|
|
7409
|
+
return agent;
|
|
7410
|
+
}
|
|
7411
|
+
function installEventHookFromAgent(agent) {
|
|
7412
|
+
const tracer = agent?._tracer;
|
|
7413
|
+
const proto = tracer ? Object.getPrototypeOf(tracer) : void 0;
|
|
7414
|
+
if (!proto || typeof proto._addEvent !== "function") return;
|
|
7415
|
+
if (proto._addEvent[PATCH_FLAG]) return;
|
|
7416
|
+
const orig = proto._addEvent;
|
|
7417
|
+
function patchedAddEvent(span2, eventName, eventAttributes) {
|
|
7418
|
+
const result = orig.call(this, span2, eventName, eventAttributes);
|
|
7419
|
+
try {
|
|
7420
|
+
enrichSpanFromEvent(span2, eventName, eventAttributes || {});
|
|
7421
|
+
} catch {
|
|
7422
|
+
}
|
|
7423
|
+
return result;
|
|
7424
|
+
}
|
|
7425
|
+
patchedAddEvent[PATCH_FLAG] = true;
|
|
7426
|
+
proto._addEvent = patchedAddEvent;
|
|
7427
|
+
}
|
|
7428
|
+
function enrichSpanFromEvent(span2, eventName, attrs) {
|
|
7429
|
+
if (!span2 || typeof span2.setAttribute !== "function") return;
|
|
7430
|
+
if (typeof span2.isRecording === "function" && !span2.isRecording()) return;
|
|
7431
|
+
const isTool = readSpanOp(span2) === "execute_tool";
|
|
7432
|
+
if (eventName.startsWith("gen_ai.") && eventName.endsWith(".message")) {
|
|
7433
|
+
const role = eventName.slice("gen_ai.".length, -".message".length);
|
|
7434
|
+
const content = flattenStrandsContent(attrs.content);
|
|
7435
|
+
if (content) {
|
|
7436
|
+
if (isTool) {
|
|
7437
|
+
span2.setAttribute("input.value", content);
|
|
7438
|
+
span2.setAttribute("neatlogs.tool.input", content);
|
|
7439
|
+
} else {
|
|
7440
|
+
appendInputMessage(span2, role, content);
|
|
7441
|
+
}
|
|
7442
|
+
}
|
|
7443
|
+
return;
|
|
7444
|
+
}
|
|
7445
|
+
if (eventName === "gen_ai.choice") {
|
|
7446
|
+
const out = flattenStrandsContent(attrs.message);
|
|
7447
|
+
if (out) setOutput(span2, isTool, out);
|
|
7448
|
+
return;
|
|
7449
|
+
}
|
|
7450
|
+
if (eventName === "gen_ai.client.inference.operation.details") {
|
|
7451
|
+
const out = flattenStrandsContent(attrs["gen_ai.output.messages"]);
|
|
7452
|
+
if (out) setOutput(span2, isTool, out);
|
|
7453
|
+
}
|
|
7454
|
+
}
|
|
7455
|
+
function setOutput(span2, isTool, out) {
|
|
7456
|
+
span2.setAttribute("output.value", out);
|
|
7457
|
+
if (isTool) {
|
|
7458
|
+
span2.setAttribute("neatlogs.tool.output", out);
|
|
7459
|
+
} else {
|
|
7460
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
7461
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", out);
|
|
7462
|
+
span2.setAttribute("neatlogs.llm.output", safeStringify6({ role: "assistant", content: out }));
|
|
7463
|
+
}
|
|
7464
|
+
}
|
|
7465
|
+
function appendInputMessage(span2, role, content) {
|
|
7466
|
+
const idx = span2.__neatlogs_in_idx ?? 0;
|
|
7467
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, role);
|
|
7468
|
+
span2.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, content);
|
|
7469
|
+
span2.__neatlogs_in_idx = idx + 1;
|
|
7470
|
+
const existing = span2.__neatlogs_in_msgs ?? [];
|
|
7471
|
+
existing.push({ role, content });
|
|
7472
|
+
span2.__neatlogs_in_msgs = existing;
|
|
7473
|
+
const blob = safeStringify6({ messages: existing });
|
|
7474
|
+
span2.setAttribute("input.value", blob);
|
|
7475
|
+
span2.setAttribute("neatlogs.llm.input", blob);
|
|
7476
|
+
}
|
|
7477
|
+
function readSpanOp(span2) {
|
|
7478
|
+
try {
|
|
7479
|
+
const a = span2.attributes;
|
|
7480
|
+
if (!a) return "";
|
|
7481
|
+
const v = typeof a.get === "function" ? a.get("gen_ai.operation.name") : a["gen_ai.operation.name"];
|
|
7482
|
+
return typeof v === "string" ? v.toLowerCase() : "";
|
|
7483
|
+
} catch {
|
|
7484
|
+
return "";
|
|
7485
|
+
}
|
|
7486
|
+
}
|
|
7487
|
+
function flattenStrandsContent(content) {
|
|
7488
|
+
if (content == null) return "";
|
|
7489
|
+
let val = content;
|
|
7490
|
+
if (typeof val === "string") {
|
|
7491
|
+
const s = val.trim();
|
|
7492
|
+
if (!(s.startsWith("[") || s.startsWith("{"))) return val;
|
|
7493
|
+
try {
|
|
7494
|
+
val = JSON.parse(s);
|
|
7495
|
+
} catch {
|
|
7496
|
+
return val;
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
7499
|
+
return flattenBlocks(val);
|
|
7500
|
+
}
|
|
7501
|
+
function flattenBlocks(val) {
|
|
7502
|
+
const items = Array.isArray(val) ? val : [val];
|
|
7503
|
+
const out = [];
|
|
7504
|
+
for (const item of items) {
|
|
7505
|
+
if (typeof item === "string") {
|
|
7506
|
+
out.push(item);
|
|
7507
|
+
continue;
|
|
7508
|
+
}
|
|
7509
|
+
if (!item || typeof item !== "object") {
|
|
7510
|
+
if (item != null) out.push(String(item));
|
|
7511
|
+
continue;
|
|
7512
|
+
}
|
|
7513
|
+
const o = item;
|
|
7514
|
+
if (typeof o.text === "string") out.push(o.text);
|
|
7515
|
+
else if (typeof o.content === "string") out.push(o.content);
|
|
7516
|
+
else if (o.toolUse) out.push(`${o.toolUse.name ?? "tool"}(${safeStringify6(o.toolUse.input ?? {})})`);
|
|
7517
|
+
else if (o.toolResult) out.push(flattenBlocks(o.toolResult.content ?? o.toolResult));
|
|
7518
|
+
else if (Array.isArray(o.parts)) out.push(flattenBlocks(o.parts));
|
|
7519
|
+
else if (Array.isArray(o.content)) out.push(flattenBlocks(o.content));
|
|
7520
|
+
else out.push(safeStringify6(o));
|
|
7521
|
+
}
|
|
7522
|
+
return out.filter(Boolean).join("\n");
|
|
7523
|
+
}
|
|
7524
|
+
function safeStringify6(value) {
|
|
7525
|
+
if (typeof value === "string") return value;
|
|
7526
|
+
try {
|
|
7527
|
+
return JSON.stringify(value) ?? "";
|
|
7528
|
+
} catch {
|
|
7529
|
+
return "";
|
|
7530
|
+
}
|
|
7531
|
+
}
|
|
7532
|
+
|
|
7533
|
+
// src/openai-agents.ts
|
|
7534
|
+
var import_api12 = require("@opentelemetry/api");
|
|
7535
|
+
var TRACER_NAME6 = "neatlogs.openai_agents";
|
|
7536
|
+
function openaiAgentsProcessor() {
|
|
7537
|
+
return new NeatlogsTraceProcessor();
|
|
7538
|
+
}
|
|
7539
|
+
var NeatlogsTraceProcessor = class {
|
|
7540
|
+
_spans = /* @__PURE__ */ new Map();
|
|
7541
|
+
_startTimes = /* @__PURE__ */ new Map();
|
|
7542
|
+
// The @openai/agents SDK passes a Trace object: { traceId, name, groupId, metadata }.
|
|
7543
|
+
onTraceStart(traceData) {
|
|
7544
|
+
const tracer = import_api12.trace.getTracer(TRACER_NAME6);
|
|
7545
|
+
const attrs = { "neatlogs.span.kind": "WORKFLOW" };
|
|
7546
|
+
const workflowName = traceData?.name ?? traceData?.workflow_name;
|
|
7547
|
+
if (workflowName) attrs["neatlogs.workflow.name"] = workflowName;
|
|
7548
|
+
const traceId = traceData?.traceId ?? traceData?.trace_id;
|
|
7549
|
+
if (traceId) attrs["neatlogs.agent.trace_id"] = String(traceId);
|
|
7550
|
+
const span2 = tracer.startSpan("openai_agents.trace", { attributes: attrs }, import_api12.context.active());
|
|
7551
|
+
const key = String(traceId ?? `trace_${Date.now()}`);
|
|
7552
|
+
this._spans.set(key, span2);
|
|
7553
|
+
this._startTimes.set(key, Date.now());
|
|
7554
|
+
}
|
|
7555
|
+
onTraceEnd(traceData) {
|
|
7556
|
+
const key = String(traceData?.traceId ?? traceData?.trace_id ?? "");
|
|
7557
|
+
const span2 = this._spans.get(key);
|
|
7558
|
+
if (!span2) return;
|
|
7559
|
+
const startTime = this._startTimes.get(key);
|
|
7560
|
+
if (startTime) {
|
|
7561
|
+
span2.setAttribute("neatlogs.metrics.duration_ms", Date.now() - startTime);
|
|
7562
|
+
}
|
|
7563
|
+
span2.setStatus({ code: import_api12.SpanStatusCode.OK });
|
|
7564
|
+
span2.end();
|
|
7565
|
+
this._spans.delete(key);
|
|
7566
|
+
this._startTimes.delete(key);
|
|
7567
|
+
}
|
|
7568
|
+
// The SDK passes a Span object: { type, spanId, traceId, parentId?, spanData: {...} }.
|
|
7569
|
+
// The meaningful payload (type, name, input, output, usage, ...) lives in `spanData`.
|
|
7570
|
+
onSpanStart(span2) {
|
|
7571
|
+
const tracer = import_api12.trace.getTracer(TRACER_NAME6);
|
|
7572
|
+
const data = span2?.spanData ?? span2 ?? {};
|
|
7573
|
+
const spanType = data?.type ?? data?.span_type ?? span2?.type ?? "";
|
|
7574
|
+
const spanId = String(span2?.spanId ?? span2?.span_id ?? data?.span_id ?? `span_${Date.now()}`);
|
|
7575
|
+
const parentKey = String(span2?.parentId ?? span2?.traceId ?? span2?.trace_id ?? "");
|
|
7576
|
+
const parentSpan = this._spans.get(parentKey);
|
|
7577
|
+
const parentCtx = parentSpan ? import_api12.trace.setSpan(import_api12.context.active(), parentSpan) : import_api12.context.active();
|
|
7578
|
+
let otelSpan;
|
|
7579
|
+
if (spanType === "agent" || spanType === "agent_run") {
|
|
7580
|
+
const agentName = data?.name ?? data?.agent_name ?? "agent";
|
|
7581
|
+
const attrs = {
|
|
7582
|
+
"neatlogs.span.kind": "AGENT",
|
|
7583
|
+
"neatlogs.agent.name": agentName
|
|
7584
|
+
};
|
|
7585
|
+
if (Array.isArray(data?.tools) && data.tools.length) {
|
|
7586
|
+
attrs["neatlogs.agent.available_tools"] = data.tools.join(",");
|
|
7587
|
+
}
|
|
7588
|
+
otelSpan = tracer.startSpan(`openai_agents.agent.${agentName}`, { attributes: attrs }, parentCtx);
|
|
7589
|
+
} else if (spanType === "response" || spanType === "generation" || spanType === "llm") {
|
|
7590
|
+
const attrs = {
|
|
7591
|
+
"neatlogs.span.kind": "LLM",
|
|
7592
|
+
"neatlogs.llm.provider": "openai"
|
|
7593
|
+
};
|
|
7594
|
+
const model = data?.model;
|
|
7595
|
+
if (model) attrs["neatlogs.llm.model_name"] = model;
|
|
7596
|
+
const inputMsgs = data?.input ?? data?.messages;
|
|
7597
|
+
if (inputMsgs && Array.isArray(inputMsgs)) {
|
|
7598
|
+
for (let i = 0; i < inputMsgs.length; i++) {
|
|
7599
|
+
const msg = inputMsgs[i];
|
|
7600
|
+
const role = typeof msg === "object" ? msg.role ?? "" : "";
|
|
7601
|
+
const content = typeof msg === "object" ? msg.content ?? "" : String(msg);
|
|
7602
|
+
if (role) attrs[`neatlogs.llm.input_messages.${i}.role`] = role;
|
|
7603
|
+
if (content) attrs[`neatlogs.llm.input_messages.${i}.content`] = (typeof content === "string" ? content : safeStringify7(content)).slice(0, 1e4);
|
|
7604
|
+
}
|
|
7605
|
+
}
|
|
7606
|
+
otelSpan = tracer.startSpan("openai_agents.generation", { attributes: attrs }, parentCtx);
|
|
7607
|
+
} else if (spanType === "function" || spanType === "tool" || spanType === "tool_call") {
|
|
7608
|
+
const toolName = data?.name ?? data?.function_name ?? "tool";
|
|
7609
|
+
const attrs = {
|
|
7610
|
+
"neatlogs.span.kind": "TOOL",
|
|
7611
|
+
"neatlogs.tool.name": toolName
|
|
7612
|
+
};
|
|
7613
|
+
const toolInput = data?.input ?? data?.arguments;
|
|
7614
|
+
if (toolInput !== void 0) {
|
|
7615
|
+
attrs["input.value"] = (typeof toolInput === "string" ? toolInput : safeStringify7(toolInput)).slice(0, 1e4);
|
|
7616
|
+
}
|
|
7617
|
+
otelSpan = tracer.startSpan(`openai_agents.tool.${toolName}`, { attributes: attrs }, parentCtx);
|
|
7618
|
+
} else if (spanType === "handoff") {
|
|
7619
|
+
const attrs = { "neatlogs.span.kind": "AGENT" };
|
|
7620
|
+
if (data?.from_agent) attrs["neatlogs.agent.handoff_from"] = String(data.from_agent);
|
|
7621
|
+
if (data?.to_agent) attrs["neatlogs.agent.name"] = String(data.to_agent);
|
|
7622
|
+
otelSpan = tracer.startSpan("openai_agents.handoff", { attributes: attrs }, parentCtx);
|
|
7623
|
+
} else {
|
|
7624
|
+
const attrs = { "neatlogs.span.kind": "CHAIN" };
|
|
7625
|
+
otelSpan = tracer.startSpan(`openai_agents.${spanType || "span"}`, { attributes: attrs }, parentCtx);
|
|
7626
|
+
}
|
|
7627
|
+
this._spans.set(spanId, otelSpan);
|
|
7628
|
+
this._startTimes.set(spanId, Date.now());
|
|
7629
|
+
}
|
|
7630
|
+
onSpanEnd(span2) {
|
|
7631
|
+
const data = span2?.spanData ?? span2 ?? {};
|
|
7632
|
+
const spanId = String(span2?.spanId ?? span2?.span_id ?? data?.span_id ?? "");
|
|
7633
|
+
const otelSpan = this._spans.get(spanId);
|
|
7634
|
+
if (!otelSpan) return;
|
|
7635
|
+
const spanType = data?.type ?? data?.span_type ?? span2?.type ?? "";
|
|
7636
|
+
const startTime = this._startTimes.get(spanId);
|
|
7637
|
+
if (spanType === "response" || spanType === "generation" || spanType === "llm") {
|
|
7638
|
+
const resp = data?._response ?? data?.response ?? {};
|
|
7639
|
+
const model = data?.model ?? resp?.model;
|
|
7640
|
+
if (model) otelSpan.setAttribute("neatlogs.llm.model_name", model);
|
|
7641
|
+
const outputItems = data?.output ?? resp?.output;
|
|
7642
|
+
if (Array.isArray(outputItems)) {
|
|
7643
|
+
const text = outputItems.filter((o) => o?.type === "message" || o?.role === "assistant").flatMap((o) => Array.isArray(o.content) ? o.content : [o.content]).map((c) => typeof c === "string" ? c : c?.text ?? "").join("");
|
|
7644
|
+
if (text) {
|
|
7645
|
+
otelSpan.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
7646
|
+
otelSpan.setAttribute("neatlogs.llm.output_messages.0.content", text.slice(0, 1e4));
|
|
7647
|
+
}
|
|
7648
|
+
const toolCalls = outputItems.filter((o) => o?.type === "function_call");
|
|
7649
|
+
for (let i = 0; i < toolCalls.length; i++) {
|
|
7650
|
+
const tc = toolCalls[i];
|
|
7651
|
+
otelSpan.setAttribute(`neatlogs.llm.tool_calls.${i}.name`, tc.name ?? "");
|
|
7652
|
+
otelSpan.setAttribute(`neatlogs.llm.tool_calls.${i}.arguments`, typeof tc.arguments === "string" ? tc.arguments : safeStringify7(tc.arguments ?? {}));
|
|
7653
|
+
if (tc.callId ?? tc.id) otelSpan.setAttribute(`neatlogs.llm.tool_calls.${i}.id`, tc.callId ?? tc.id);
|
|
7654
|
+
}
|
|
7655
|
+
} else if (outputItems?.content) {
|
|
7656
|
+
otelSpan.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
7657
|
+
const c = outputItems.content;
|
|
7658
|
+
otelSpan.setAttribute("neatlogs.llm.output_messages.0.content", (typeof c === "string" ? c : safeStringify7(c)).slice(0, 1e4));
|
|
7659
|
+
}
|
|
7660
|
+
const usage = data?.usage ?? resp?.usage;
|
|
7661
|
+
if (usage) {
|
|
7662
|
+
const inputTokens = usage.input_tokens ?? usage.prompt_tokens ?? usage.inputTokens;
|
|
7663
|
+
const outputTokens = usage.output_tokens ?? usage.completion_tokens ?? usage.outputTokens;
|
|
7664
|
+
const totalTokens = usage.total_tokens ?? usage.totalTokens;
|
|
7665
|
+
if (inputTokens != null) otelSpan.setAttribute("neatlogs.llm.token_count.prompt", inputTokens);
|
|
7666
|
+
if (outputTokens != null) otelSpan.setAttribute("neatlogs.llm.token_count.completion", outputTokens);
|
|
7667
|
+
if (totalTokens != null) otelSpan.setAttribute("neatlogs.llm.token_count.total", totalTokens);
|
|
7668
|
+
else if (inputTokens != null && outputTokens != null) {
|
|
7669
|
+
otelSpan.setAttribute("neatlogs.llm.token_count.total", inputTokens + outputTokens);
|
|
7670
|
+
}
|
|
7671
|
+
}
|
|
7672
|
+
} else if (spanType === "function" || spanType === "tool" || spanType === "tool_call") {
|
|
7673
|
+
const output = data?.output ?? data?.result;
|
|
7674
|
+
if (output != null) {
|
|
7675
|
+
otelSpan.setAttribute("output.value", (typeof output === "string" ? output : safeStringify7(output)).slice(0, 1e4));
|
|
7676
|
+
}
|
|
7677
|
+
} else if (spanType === "agent" || spanType === "agent_run") {
|
|
7678
|
+
const output = data?.output;
|
|
7679
|
+
if (output != null) {
|
|
7680
|
+
otelSpan.setAttribute("output.value", (typeof output === "string" ? output : safeStringify7(output)).slice(0, 1e4));
|
|
7681
|
+
}
|
|
7682
|
+
}
|
|
7683
|
+
const error = data?.error ?? span2?.error;
|
|
7684
|
+
if (error) {
|
|
7685
|
+
if (error instanceof Error) {
|
|
7686
|
+
otelSpan.setStatus({ code: import_api12.SpanStatusCode.ERROR, message: error.message });
|
|
7687
|
+
otelSpan.recordException(error);
|
|
7688
|
+
} else {
|
|
7689
|
+
otelSpan.setStatus({ code: import_api12.SpanStatusCode.ERROR, message: String(error) });
|
|
7690
|
+
}
|
|
7691
|
+
} else {
|
|
7692
|
+
otelSpan.setStatus({ code: import_api12.SpanStatusCode.OK });
|
|
7693
|
+
}
|
|
7694
|
+
if (startTime) {
|
|
7695
|
+
otelSpan.setAttribute("neatlogs.llm.metrics.duration_ms", Date.now() - startTime);
|
|
7696
|
+
}
|
|
7697
|
+
otelSpan.end();
|
|
7698
|
+
this._spans.delete(spanId);
|
|
7699
|
+
this._startTimes.delete(spanId);
|
|
7700
|
+
}
|
|
7701
|
+
shutdown() {
|
|
7702
|
+
for (const [, span2] of this._spans) {
|
|
7703
|
+
span2.setStatus({ code: import_api12.SpanStatusCode.ERROR, message: "Processor shutdown before span completed" });
|
|
7704
|
+
span2.end();
|
|
7705
|
+
}
|
|
7706
|
+
this._spans.clear();
|
|
7707
|
+
this._startTimes.clear();
|
|
7708
|
+
}
|
|
7709
|
+
forceFlush() {
|
|
7710
|
+
}
|
|
7711
|
+
};
|
|
7712
|
+
function safeStringify7(value) {
|
|
7713
|
+
try {
|
|
7714
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
7715
|
+
} catch {
|
|
7716
|
+
return "";
|
|
7717
|
+
}
|
|
7718
|
+
}
|
|
7719
|
+
|
|
7720
|
+
// src/mastra-wrap.ts
|
|
7721
|
+
var import_api13 = require("@opentelemetry/api");
|
|
7722
|
+
var TRACER_NAME7 = "neatlogs.mastra";
|
|
7723
|
+
var PATCH_FLAG2 = "_neatlogs_patched";
|
|
7724
|
+
function wrapMastra(entity) {
|
|
7725
|
+
if (!entity || entity[PATCH_FLAG2]) return entity;
|
|
7726
|
+
const e = entity;
|
|
7727
|
+
const className = entity.constructor?.name ?? "";
|
|
7728
|
+
if (isRootMastra(e)) {
|
|
7729
|
+
const proxied = wrapRootMastra(e);
|
|
7730
|
+
markPatched(proxied);
|
|
7731
|
+
return proxied;
|
|
7732
|
+
}
|
|
7733
|
+
if (isAgent(e, className)) {
|
|
7734
|
+
patchAgent(e);
|
|
7735
|
+
} else if (isWorkflow(e, className)) {
|
|
7736
|
+
patchWorkflow(e);
|
|
7737
|
+
} else if (isVector(e, className)) {
|
|
7738
|
+
patchVector(e);
|
|
7739
|
+
} else if (isMemory(e, className)) {
|
|
7740
|
+
patchMemory(e);
|
|
7741
|
+
} else if (isDocument(e, className)) {
|
|
7742
|
+
patchDocument(e);
|
|
7743
|
+
}
|
|
7744
|
+
markPatched(e);
|
|
7745
|
+
return entity;
|
|
7746
|
+
}
|
|
7747
|
+
function isRootMastra(e) {
|
|
7748
|
+
return typeof e.getAgent === "function" && typeof e.getWorkflow === "function";
|
|
7749
|
+
}
|
|
7750
|
+
function isAgent(e, className) {
|
|
7751
|
+
return className === "Agent" || typeof e.generate === "function" || typeof e.stream === "function";
|
|
7752
|
+
}
|
|
7753
|
+
function isWorkflow(e, className) {
|
|
7754
|
+
return className === "Workflow" || typeof e.createRun === "function";
|
|
7755
|
+
}
|
|
7756
|
+
function isVector(e, className) {
|
|
7757
|
+
return /Vector/.test(className) || typeof e.query === "function" && typeof e.upsert === "function";
|
|
7758
|
+
}
|
|
7759
|
+
function isMemory(e, className) {
|
|
7760
|
+
return /Memory/.test(className) || typeof e.recall === "function" && typeof e.saveMessages === "function";
|
|
7761
|
+
}
|
|
7762
|
+
function isDocument(e, className) {
|
|
7763
|
+
return className === "MDocument" || typeof e.chunk === "function" && typeof e.getDocs === "function";
|
|
7764
|
+
}
|
|
7765
|
+
function patchAgent(agent) {
|
|
7766
|
+
patchAgentMethod(agent, "generate", false);
|
|
7767
|
+
patchAgentMethod(agent, "stream", true);
|
|
7768
|
+
}
|
|
7769
|
+
function patchAgentMethod(agent, method, streaming) {
|
|
7770
|
+
if (typeof agent[method] !== "function") return;
|
|
7771
|
+
const orig = agent[method].bind(agent);
|
|
7772
|
+
agent[method] = async function tracedAgentMethod(input, opts) {
|
|
7773
|
+
const agentName = agent.name ?? agent.id ?? "mastra_agent";
|
|
7774
|
+
const model = extractModelId(agent.model);
|
|
7775
|
+
installAgentLlmHook(agent);
|
|
7776
|
+
installAgentToolHooks(agent);
|
|
7777
|
+
const attrs = {
|
|
7778
|
+
"neatlogs.span.kind": "AGENT",
|
|
7779
|
+
"neatlogs.agent.name": agentName,
|
|
7780
|
+
"input.value": toInputValue(input)
|
|
7781
|
+
};
|
|
7782
|
+
if (model) attrs["neatlogs.llm.model_name"] = model;
|
|
7783
|
+
if (agent.instructions && typeof agent.instructions === "string") {
|
|
7784
|
+
attrs["neatlogs.llm.system_prompt"] = agent.instructions.slice(0, 5e3);
|
|
7785
|
+
}
|
|
7786
|
+
if (streaming) attrs["neatlogs.llm.is_streaming"] = true;
|
|
7787
|
+
if (streaming) {
|
|
7788
|
+
const tracer = import_api13.trace.getTracer(TRACER_NAME7);
|
|
7789
|
+
const span2 = tracer.startSpan(`mastra.agent.${agentName}`, { attributes: attrs }, import_api13.context.active());
|
|
7790
|
+
const ctx = import_api13.trace.setSpan(import_api13.context.active(), span2);
|
|
7791
|
+
try {
|
|
7792
|
+
const result = await import_api13.context.with(ctx, () => orig(input, opts));
|
|
7793
|
+
return wrapStreamingOutput(result, span2, ctx);
|
|
7794
|
+
} catch (err) {
|
|
7795
|
+
recordError3(span2, err);
|
|
7796
|
+
span2.end();
|
|
7797
|
+
throw err;
|
|
7798
|
+
}
|
|
7799
|
+
}
|
|
7800
|
+
return withActiveSpan(`mastra.agent.${agentName}`, attrs, async (span2) => {
|
|
7801
|
+
const result = await orig(input, opts);
|
|
7802
|
+
finalizeAgentResult(span2, result);
|
|
7803
|
+
return result;
|
|
7804
|
+
});
|
|
7805
|
+
};
|
|
7806
|
+
}
|
|
7807
|
+
function installAgentLlmHook(agent) {
|
|
7808
|
+
if (agent.__neatlogs_llm_hook || typeof agent.getLLM !== "function") return;
|
|
7809
|
+
agent.__neatlogs_llm_hook = true;
|
|
7810
|
+
const origGetLLM = agent.getLLM.bind(agent);
|
|
7811
|
+
agent.getLLM = function patchedGetLLM(...args) {
|
|
7812
|
+
const out = origGetLLM(...args);
|
|
7813
|
+
return Promise.resolve(out).then((llm) => {
|
|
7814
|
+
try {
|
|
7815
|
+
const model = typeof llm?.getModel === "function" ? llm.getModel() : llm;
|
|
7816
|
+
patchModelInPlace(model);
|
|
7817
|
+
} catch {
|
|
7818
|
+
}
|
|
7819
|
+
return llm;
|
|
7820
|
+
});
|
|
7821
|
+
};
|
|
7822
|
+
}
|
|
7823
|
+
function patchModelInPlace(model) {
|
|
7824
|
+
if (!model || model.__neatlogs_model_patched) return;
|
|
7825
|
+
model.__neatlogs_model_patched = true;
|
|
7826
|
+
const modelId = model.modelId ?? model.modelName ?? "";
|
|
7827
|
+
const provider = model.provider ?? "";
|
|
7828
|
+
for (const fn of ["doGenerate", "doStream"]) {
|
|
7829
|
+
if (typeof model[fn] !== "function") continue;
|
|
7830
|
+
const orig = model[fn].bind(model);
|
|
7831
|
+
const isStream = fn === "doStream";
|
|
7832
|
+
model[fn] = function tracedModelCall(callOpts) {
|
|
7833
|
+
const attrs = { "neatlogs.span.kind": "LLM" };
|
|
7834
|
+
if (modelId) attrs["neatlogs.llm.model_name"] = modelId;
|
|
7835
|
+
if (provider) attrs["neatlogs.llm.provider"] = provider;
|
|
7836
|
+
if (isStream) attrs["neatlogs.llm.is_streaming"] = true;
|
|
7837
|
+
const promptInput = callOpts?.prompt ?? callOpts?.messages;
|
|
7838
|
+
if (promptInput !== void 0) attrs["input.value"] = safeStringify8(promptInput).slice(0, 1e4);
|
|
7839
|
+
captureInvocationParams(attrs, callOpts);
|
|
7840
|
+
return withActiveSpan(`mastra.llm.${modelId || "model"}.${fn}`, attrs, async (span2) => {
|
|
7841
|
+
const result = await orig(callOpts);
|
|
7842
|
+
if (!isStream) finalizeModelResult(span2, result);
|
|
7843
|
+
else if (result?.usage) recordUsage(span2, result.usage);
|
|
7844
|
+
return result;
|
|
7845
|
+
});
|
|
7846
|
+
};
|
|
7847
|
+
}
|
|
7848
|
+
}
|
|
7849
|
+
function installAgentToolHooks(agent) {
|
|
7850
|
+
if (agent.__neatlogs_tool_hook) return;
|
|
7851
|
+
let tools;
|
|
7852
|
+
try {
|
|
7853
|
+
tools = typeof agent.listTools === "function" ? agent.listTools() : void 0;
|
|
7854
|
+
} catch {
|
|
7855
|
+
tools = void 0;
|
|
7856
|
+
}
|
|
7857
|
+
if (!tools || typeof tools !== "object") return;
|
|
7858
|
+
agent.__neatlogs_tool_hook = true;
|
|
7859
|
+
for (const [key, tool] of Object.entries(tools)) {
|
|
7860
|
+
patchToolExecute(tool, key);
|
|
7861
|
+
}
|
|
7862
|
+
}
|
|
7863
|
+
function patchToolExecute(tool, key) {
|
|
7864
|
+
if (!tool || typeof tool.execute !== "function" || tool.__neatlogs_tool_patched) return;
|
|
7865
|
+
tool.__neatlogs_tool_patched = true;
|
|
7866
|
+
const toolName = tool.id ?? key;
|
|
7867
|
+
const orig = tool.execute.bind(tool);
|
|
7868
|
+
tool.execute = function tracedToolExecute(params, options) {
|
|
7869
|
+
const attrs = {
|
|
7870
|
+
"neatlogs.span.kind": "TOOL",
|
|
7871
|
+
"neatlogs.tool.name": toolName,
|
|
7872
|
+
"input.value": safeStringify8(params).slice(0, 1e4)
|
|
7873
|
+
};
|
|
7874
|
+
if (tool.description) attrs["neatlogs.tool.description"] = String(tool.description).slice(0, 2e3);
|
|
7875
|
+
return withActiveSpan(`mastra.tool.${toolName}`, attrs, async (span2) => {
|
|
7876
|
+
const result = await orig(params, options);
|
|
7877
|
+
span2.setAttribute("output.value", safeStringify8(result).slice(0, 1e4));
|
|
7878
|
+
return result;
|
|
7879
|
+
});
|
|
7880
|
+
};
|
|
7881
|
+
}
|
|
7882
|
+
function patchWorkflow(workflow) {
|
|
7883
|
+
if (typeof workflow.createRun !== "function") return;
|
|
7884
|
+
const origCreateRun = workflow.createRun.bind(workflow);
|
|
7885
|
+
const workflowName = workflow.name ?? workflow.id ?? "mastra_workflow";
|
|
7886
|
+
workflow.createRun = async function tracedCreateRun(...args) {
|
|
7887
|
+
const run = await origCreateRun(...args);
|
|
7888
|
+
if (!run) return run;
|
|
7889
|
+
patchRunMethod(run, "start", workflowName);
|
|
7890
|
+
patchRunMethod(run, "resume", workflowName);
|
|
7891
|
+
return run;
|
|
7892
|
+
};
|
|
7893
|
+
}
|
|
7894
|
+
function patchRunMethod(run, method, workflowName) {
|
|
7895
|
+
if (typeof run[method] !== "function") return;
|
|
7896
|
+
const orig = run[method].bind(run);
|
|
7897
|
+
run[method] = async function tracedRunMethod(startOpts) {
|
|
7898
|
+
const attrs = {
|
|
7899
|
+
"neatlogs.span.kind": "WORKFLOW",
|
|
7900
|
+
"neatlogs.workflow.name": workflowName
|
|
7901
|
+
};
|
|
7902
|
+
if (startOpts?.inputData !== void 0) {
|
|
7903
|
+
attrs["input.value"] = safeStringify8(startOpts.inputData).slice(0, 1e4);
|
|
7904
|
+
}
|
|
7905
|
+
return withActiveSpan(`mastra.workflow.${workflowName}`, attrs, async (span2) => {
|
|
7906
|
+
const result = await orig(startOpts);
|
|
7907
|
+
if (result?.status) span2.setAttribute("neatlogs.metadata", safeStringify8({ status: result.status }));
|
|
7908
|
+
if (result?.result !== void 0) {
|
|
7909
|
+
span2.setAttribute("output.value", safeStringify8(result.result).slice(0, 1e4));
|
|
7910
|
+
}
|
|
7911
|
+
return result;
|
|
7912
|
+
});
|
|
7913
|
+
};
|
|
7914
|
+
}
|
|
7915
|
+
var VECTOR_READ_OPS = ["query"];
|
|
7916
|
+
var VECTOR_WRITE_OPS = ["upsert", "updateVector", "deleteVector", "createIndex", "deleteIndex"];
|
|
7917
|
+
function patchVector(vector) {
|
|
7918
|
+
for (const op of VECTOR_READ_OPS) patchVectorOp(vector, op, "RETRIEVER");
|
|
7919
|
+
for (const op of VECTOR_WRITE_OPS) patchVectorOp(vector, op, "VECTOR_STORE");
|
|
7920
|
+
}
|
|
7921
|
+
function patchVectorOp(vector, op, kind) {
|
|
7922
|
+
if (typeof vector[op] !== "function") return;
|
|
7923
|
+
const orig = vector[op].bind(vector);
|
|
7924
|
+
const dbName = vector.constructor?.name ?? "vector";
|
|
7925
|
+
vector[op] = async function tracedVectorOp(params) {
|
|
7926
|
+
const attrs = {
|
|
7927
|
+
"neatlogs.span.kind": kind,
|
|
7928
|
+
"neatlogs.db.system": dbName,
|
|
7929
|
+
"neatlogs.db.operation": op,
|
|
7930
|
+
"input.value": safeStringify8(params).slice(0, 1e4)
|
|
7931
|
+
};
|
|
7932
|
+
const indexName = params?.indexName;
|
|
7933
|
+
if (indexName) attrs["neatlogs.vectordb.index_name"] = String(indexName);
|
|
7934
|
+
if (kind === "RETRIEVER" && params?.topK != null) attrs["neatlogs.retriever.top_k"] = params.topK;
|
|
7935
|
+
return withActiveSpan(`mastra.vector.${op}`, attrs, async (span2) => {
|
|
7936
|
+
const result = await orig(params);
|
|
7937
|
+
span2.setAttribute("output.value", safeStringify8(result).slice(0, 1e4));
|
|
7938
|
+
return result;
|
|
7939
|
+
});
|
|
7940
|
+
};
|
|
7941
|
+
}
|
|
7942
|
+
var MEMORY_OPS = ["recall", "saveMessages", "updateWorkingMemory", "deleteMessages"];
|
|
7943
|
+
function patchMemory(memory) {
|
|
7944
|
+
for (const op of MEMORY_OPS) {
|
|
7945
|
+
if (typeof memory[op] !== "function") continue;
|
|
7946
|
+
const orig = memory[op].bind(memory);
|
|
7947
|
+
memory[op] = async function tracedMemoryOp(...args) {
|
|
7948
|
+
const attrs = {
|
|
7949
|
+
"neatlogs.span.kind": "CHAIN",
|
|
7950
|
+
"neatlogs.db.operation": op,
|
|
7951
|
+
"input.value": safeStringify8(args?.[0]).slice(0, 1e4)
|
|
7952
|
+
};
|
|
7953
|
+
return withActiveSpan(`mastra.memory.${op}`, attrs, async (span2) => {
|
|
7954
|
+
const result = await orig(...args);
|
|
7955
|
+
span2.setAttribute("output.value", safeStringify8(result).slice(0, 8e3));
|
|
7956
|
+
return result;
|
|
7957
|
+
});
|
|
7958
|
+
};
|
|
7959
|
+
}
|
|
7960
|
+
}
|
|
7961
|
+
function patchDocument(doc) {
|
|
7962
|
+
if (typeof doc.chunk !== "function") return;
|
|
7963
|
+
const orig = doc.chunk.bind(doc);
|
|
7964
|
+
doc.chunk = async function tracedChunk(...args) {
|
|
7965
|
+
const attrs = {
|
|
7966
|
+
"neatlogs.span.kind": "CHAIN",
|
|
7967
|
+
"neatlogs.db.operation": "chunk"
|
|
7968
|
+
};
|
|
7969
|
+
return withActiveSpan("mastra.document.chunk", attrs, async (span2) => {
|
|
7970
|
+
const result = await orig(...args);
|
|
7971
|
+
if (Array.isArray(result)) span2.setAttribute("neatlogs.db.documents_count", result.length);
|
|
7972
|
+
return result;
|
|
7973
|
+
});
|
|
7974
|
+
};
|
|
7975
|
+
}
|
|
7976
|
+
function wrapRootMastra(mastra) {
|
|
7977
|
+
const AGENT_GETTERS = /* @__PURE__ */ new Set(["getAgent", "getAgentById"]);
|
|
7978
|
+
const WORKFLOW_GETTERS = /* @__PURE__ */ new Set(["getWorkflow", "getWorkflowById"]);
|
|
7979
|
+
return new Proxy(mastra, {
|
|
7980
|
+
get(target, prop, receiver) {
|
|
7981
|
+
const value = Reflect.get(target, prop, receiver);
|
|
7982
|
+
if (typeof value !== "function") return value;
|
|
7983
|
+
const name = String(prop);
|
|
7984
|
+
if (AGENT_GETTERS.has(name) || WORKFLOW_GETTERS.has(name)) {
|
|
7985
|
+
return (...args) => {
|
|
7986
|
+
const entity = value.apply(target, args);
|
|
7987
|
+
return entity && typeof entity === "object" ? wrapMastra(entity) : entity;
|
|
7988
|
+
};
|
|
7989
|
+
}
|
|
7990
|
+
return value.bind(target);
|
|
7991
|
+
}
|
|
7992
|
+
});
|
|
7993
|
+
}
|
|
7994
|
+
function wrapStreamingOutput(output, span2, ctx) {
|
|
7995
|
+
if (!output) {
|
|
7996
|
+
span2.setStatus({ code: import_api13.SpanStatusCode.OK });
|
|
7997
|
+
span2.end();
|
|
7998
|
+
return output;
|
|
7999
|
+
}
|
|
8000
|
+
let ended = false;
|
|
8001
|
+
const endOnce = (err) => {
|
|
8002
|
+
if (ended) return;
|
|
8003
|
+
ended = true;
|
|
8004
|
+
if (err) recordError3(span2, err);
|
|
8005
|
+
else span2.setStatus({ code: import_api13.SpanStatusCode.OK });
|
|
8006
|
+
span2.end();
|
|
8007
|
+
};
|
|
8008
|
+
if (output.text && typeof output.text.then === "function") {
|
|
8009
|
+
const finalize = async () => {
|
|
8010
|
+
try {
|
|
8011
|
+
const [text, usage, finishReason] = await Promise.all([
|
|
8012
|
+
Promise.resolve(output.text).catch(() => void 0),
|
|
8013
|
+
Promise.resolve(output.usage).catch(() => void 0),
|
|
8014
|
+
Promise.resolve(output.finishReason).catch(() => void 0)
|
|
8015
|
+
]);
|
|
8016
|
+
if (typeof text === "string" && text) {
|
|
8017
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
8018
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", text.slice(0, 1e4));
|
|
8019
|
+
}
|
|
8020
|
+
if (usage) recordUsage(span2, usage);
|
|
8021
|
+
if (finishReason) span2.setAttribute("neatlogs.llm.stop_reason", normalizeFinishReason(finishReason));
|
|
8022
|
+
endOnce();
|
|
8023
|
+
} catch (err) {
|
|
8024
|
+
endOnce(err);
|
|
8025
|
+
}
|
|
8026
|
+
};
|
|
8027
|
+
void finalize();
|
|
8028
|
+
return rebindStreamContext(output, ctx);
|
|
8029
|
+
}
|
|
8030
|
+
if (output[Symbol.asyncIterator]) {
|
|
8031
|
+
const origIterator = output[Symbol.asyncIterator].bind(output);
|
|
8032
|
+
const textParts = [];
|
|
8033
|
+
const wrapped = Object.create(Object.getPrototypeOf(output));
|
|
8034
|
+
Object.assign(wrapped, output);
|
|
8035
|
+
wrapped[Symbol.asyncIterator] = function() {
|
|
8036
|
+
const iterator = origIterator();
|
|
8037
|
+
const finish = () => {
|
|
8038
|
+
if (textParts.length) {
|
|
8039
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
8040
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", textParts.join("").slice(0, 1e4));
|
|
8041
|
+
}
|
|
8042
|
+
endOnce();
|
|
8043
|
+
};
|
|
8044
|
+
return {
|
|
8045
|
+
async next() {
|
|
8046
|
+
try {
|
|
8047
|
+
const r = await iterator.next();
|
|
8048
|
+
if (r.done) {
|
|
8049
|
+
finish();
|
|
8050
|
+
return r;
|
|
8051
|
+
}
|
|
8052
|
+
const chunk = r.value;
|
|
8053
|
+
if (typeof chunk === "string") textParts.push(chunk);
|
|
8054
|
+
else if (chunk?.text) textParts.push(chunk.text);
|
|
8055
|
+
else if (chunk?.delta) textParts.push(chunk.delta);
|
|
8056
|
+
return r;
|
|
8057
|
+
} catch (err) {
|
|
8058
|
+
endOnce(err);
|
|
8059
|
+
throw err;
|
|
8060
|
+
}
|
|
8061
|
+
},
|
|
8062
|
+
async return(value) {
|
|
8063
|
+
finish();
|
|
8064
|
+
return iterator.return?.(value) ?? { done: true, value: void 0 };
|
|
8065
|
+
},
|
|
8066
|
+
async throw(err) {
|
|
8067
|
+
endOnce(err);
|
|
8068
|
+
return iterator.throw?.(err) ?? { done: true, value: void 0 };
|
|
8069
|
+
}
|
|
8070
|
+
};
|
|
8071
|
+
};
|
|
8072
|
+
return wrapped;
|
|
8073
|
+
}
|
|
8074
|
+
if (typeof output.then === "function") {
|
|
8075
|
+
return output.then((resolved) => {
|
|
8076
|
+
finalizeAgentResult(span2, resolved);
|
|
8077
|
+
endOnce();
|
|
8078
|
+
return resolved;
|
|
8079
|
+
}).catch((err) => {
|
|
8080
|
+
endOnce(err);
|
|
8081
|
+
throw err;
|
|
8082
|
+
});
|
|
8083
|
+
}
|
|
8084
|
+
endOnce();
|
|
8085
|
+
return output;
|
|
8086
|
+
}
|
|
8087
|
+
function rebindStreamContext(output, ctx) {
|
|
8088
|
+
const STREAM_PROPS = /* @__PURE__ */ new Set(["textStream", "fullStream", "objectStream", "elementStream"]);
|
|
8089
|
+
return new Proxy(output, {
|
|
8090
|
+
get(target, prop, receiver) {
|
|
8091
|
+
const value = Reflect.get(target, prop, receiver);
|
|
8092
|
+
if (typeof prop === "string" && STREAM_PROPS.has(prop) && value && value[Symbol.asyncIterator]) {
|
|
8093
|
+
const origIterator = value[Symbol.asyncIterator].bind(value);
|
|
8094
|
+
return {
|
|
8095
|
+
[Symbol.asyncIterator]() {
|
|
8096
|
+
return import_api13.context.with(ctx, () => origIterator());
|
|
8097
|
+
}
|
|
8098
|
+
};
|
|
8099
|
+
}
|
|
8100
|
+
if (typeof value === "function") return value.bind(target);
|
|
8101
|
+
return value;
|
|
8102
|
+
}
|
|
8103
|
+
});
|
|
8104
|
+
}
|
|
8105
|
+
function finalizeAgentResult(span2, result) {
|
|
8106
|
+
if (!result) return;
|
|
8107
|
+
if (result.text) {
|
|
8108
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
8109
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", String(result.text).slice(0, 1e4));
|
|
8110
|
+
}
|
|
8111
|
+
if (Array.isArray(result.toolCalls)) {
|
|
8112
|
+
for (let i = 0; i < result.toolCalls.length; i++) {
|
|
8113
|
+
const tc = result.toolCalls[i];
|
|
8114
|
+
const p = tc.payload ?? tc;
|
|
8115
|
+
setToolCall(span2, i, p.toolName ?? p.name, p.args ?? p.arguments, p.toolCallId ?? p.id);
|
|
8116
|
+
}
|
|
8117
|
+
}
|
|
8118
|
+
if (result.usage) recordUsage(span2, result.usage);
|
|
8119
|
+
if (result.finishReason) span2.setAttribute("neatlogs.llm.stop_reason", normalizeFinishReason(result.finishReason));
|
|
8120
|
+
if (result.model) span2.setAttribute("neatlogs.llm.model_name", result.model);
|
|
8121
|
+
}
|
|
8122
|
+
function finalizeModelResult(span2, result) {
|
|
8123
|
+
if (!result) return;
|
|
8124
|
+
if (typeof result.text === "string" && result.text) {
|
|
8125
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
8126
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", result.text.slice(0, 1e4));
|
|
8127
|
+
} else if (Array.isArray(result.content)) {
|
|
8128
|
+
const text = result.content.filter((p) => p?.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
|
|
8129
|
+
if (text) {
|
|
8130
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
8131
|
+
span2.setAttribute("neatlogs.llm.output_messages.0.content", text.slice(0, 1e4));
|
|
8132
|
+
}
|
|
8133
|
+
const toolCalls = result.content.filter((p) => p?.type === "tool-call");
|
|
8134
|
+
for (let i = 0; i < toolCalls.length; i++) {
|
|
8135
|
+
const tc = toolCalls[i];
|
|
8136
|
+
setToolCall(span2, i, tc.toolName, tc.input ?? tc.args, tc.toolCallId);
|
|
8137
|
+
}
|
|
8138
|
+
span2.setAttribute("output.value", safeStringify8(result.content).slice(0, 1e4));
|
|
8139
|
+
}
|
|
8140
|
+
if (result.usage) recordUsage(span2, result.usage);
|
|
8141
|
+
span2.setAttribute("neatlogs.llm.stop_reason", normalizeFinishReason(result.finishReason));
|
|
8142
|
+
}
|
|
8143
|
+
function normalizeFinishReason(fr) {
|
|
8144
|
+
if (fr == null) return "";
|
|
8145
|
+
if (typeof fr === "string") return fr;
|
|
8146
|
+
return String(fr.unified ?? fr.reason ?? fr.type ?? safeStringify8(fr));
|
|
8147
|
+
}
|
|
8148
|
+
function tokenValue(v) {
|
|
8149
|
+
if (v == null) return void 0;
|
|
8150
|
+
if (typeof v === "number") return v;
|
|
8151
|
+
if (typeof v === "object" && typeof v.total === "number") return v.total;
|
|
8152
|
+
const n = Number(v);
|
|
8153
|
+
return Number.isFinite(n) ? n : void 0;
|
|
8154
|
+
}
|
|
8155
|
+
function captureInvocationParams(attrs, callOpts) {
|
|
8156
|
+
if (!callOpts) return;
|
|
8157
|
+
const map = [
|
|
8158
|
+
["temperature", "neatlogs.llm.temperature"],
|
|
8159
|
+
["maxOutputTokens", "neatlogs.llm.max_tokens"],
|
|
8160
|
+
["maxTokens", "neatlogs.llm.max_tokens"],
|
|
8161
|
+
["topP", "neatlogs.llm.top_p"],
|
|
8162
|
+
["topK", "neatlogs.llm.top_k"],
|
|
8163
|
+
["frequencyPenalty", "neatlogs.llm.frequency_penalty"],
|
|
8164
|
+
["presencePenalty", "neatlogs.llm.presence_penalty"]
|
|
8165
|
+
];
|
|
8166
|
+
const invocation = {};
|
|
8167
|
+
for (const [src, target] of map) {
|
|
8168
|
+
const v = callOpts[src];
|
|
8169
|
+
if (v != null) {
|
|
8170
|
+
attrs[target] = v;
|
|
8171
|
+
invocation[src] = v;
|
|
8172
|
+
}
|
|
8173
|
+
}
|
|
8174
|
+
if (Array.isArray(callOpts.stopSequences) && callOpts.stopSequences.length) {
|
|
8175
|
+
attrs["neatlogs.llm.stop_sequences"] = safeStringify8(callOpts.stopSequences);
|
|
8176
|
+
invocation.stopSequences = callOpts.stopSequences;
|
|
8177
|
+
}
|
|
8178
|
+
if (Array.isArray(callOpts.tools)) {
|
|
8179
|
+
for (let i = 0; i < callOpts.tools.length; i++) {
|
|
8180
|
+
attrs[`neatlogs.llm.tools.${i}`] = safeStringify8(callOpts.tools[i]).slice(0, 4e3);
|
|
8181
|
+
}
|
|
8182
|
+
invocation.toolChoice = callOpts.toolChoice;
|
|
8183
|
+
}
|
|
8184
|
+
if (Object.keys(invocation).length) {
|
|
8185
|
+
attrs["neatlogs.llm.invocation_parameters"] = safeStringify8(invocation).slice(0, 4e3);
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
8188
|
+
function setToolCall(span2, i, name, args, id) {
|
|
8189
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${i}.name`, name ?? "");
|
|
8190
|
+
span2.setAttribute(`neatlogs.llm.tool_calls.${i}.arguments`, safeStringify8(args ?? {}));
|
|
8191
|
+
if (id) span2.setAttribute(`neatlogs.llm.tool_calls.${i}.id`, id);
|
|
8192
|
+
}
|
|
8193
|
+
function recordUsage(span2, usage) {
|
|
8194
|
+
if (!usage) return;
|
|
8195
|
+
const prompt = tokenValue(usage.promptTokens ?? usage.inputTokens ?? usage.input_tokens);
|
|
8196
|
+
const completion = tokenValue(usage.completionTokens ?? usage.outputTokens ?? usage.output_tokens);
|
|
8197
|
+
const total = tokenValue(usage.totalTokens);
|
|
8198
|
+
if (prompt != null) span2.setAttribute("neatlogs.llm.token_count.prompt", prompt);
|
|
8199
|
+
if (completion != null) span2.setAttribute("neatlogs.llm.token_count.completion", completion);
|
|
8200
|
+
if (total != null) span2.setAttribute("neatlogs.llm.token_count.total", total);
|
|
8201
|
+
else if (prompt != null && completion != null) {
|
|
8202
|
+
span2.setAttribute("neatlogs.llm.token_count.total", prompt + completion);
|
|
8203
|
+
}
|
|
8204
|
+
}
|
|
8205
|
+
function withActiveSpan(name, attrs, fn) {
|
|
8206
|
+
const tracer = import_api13.trace.getTracer(TRACER_NAME7);
|
|
8207
|
+
const span2 = tracer.startSpan(name, { attributes: attrs }, import_api13.context.active());
|
|
8208
|
+
const ctx = import_api13.trace.setSpan(import_api13.context.active(), span2);
|
|
8209
|
+
return import_api13.context.with(ctx, async () => {
|
|
8210
|
+
try {
|
|
8211
|
+
const result = await fn(span2);
|
|
8212
|
+
span2.setStatus({ code: import_api13.SpanStatusCode.OK });
|
|
8213
|
+
return result;
|
|
8214
|
+
} catch (err) {
|
|
8215
|
+
recordError3(span2, err);
|
|
8216
|
+
throw err;
|
|
8217
|
+
} finally {
|
|
8218
|
+
span2.end();
|
|
8219
|
+
}
|
|
8220
|
+
});
|
|
8221
|
+
}
|
|
8222
|
+
function markPatched(e) {
|
|
8223
|
+
try {
|
|
8224
|
+
Object.defineProperty(e, PATCH_FLAG2, { value: true, enumerable: false, configurable: true });
|
|
8225
|
+
} catch {
|
|
8226
|
+
e[PATCH_FLAG2] = true;
|
|
8227
|
+
}
|
|
8228
|
+
}
|
|
8229
|
+
function extractModelId(model) {
|
|
8230
|
+
if (!model) return "";
|
|
8231
|
+
if (typeof model === "string") return model;
|
|
8232
|
+
return model.modelId ?? model.name ?? "";
|
|
8233
|
+
}
|
|
8234
|
+
function toInputValue(input) {
|
|
8235
|
+
return (typeof input === "string" ? input : safeStringify8(input)).slice(0, 1e4);
|
|
8236
|
+
}
|
|
8237
|
+
function safeStringify8(value) {
|
|
8238
|
+
if (typeof value === "string") return value;
|
|
8239
|
+
try {
|
|
8240
|
+
return JSON.stringify(value) ?? "";
|
|
8241
|
+
} catch {
|
|
8242
|
+
return "";
|
|
8243
|
+
}
|
|
8244
|
+
}
|
|
8245
|
+
function recordError3(span2, err) {
|
|
8246
|
+
if (err instanceof Error) {
|
|
8247
|
+
span2.setStatus({ code: import_api13.SpanStatusCode.ERROR, message: err.message });
|
|
8248
|
+
span2.recordException(err);
|
|
8249
|
+
} else {
|
|
8250
|
+
span2.setStatus({ code: import_api13.SpanStatusCode.ERROR, message: String(err) });
|
|
8251
|
+
}
|
|
8252
|
+
}
|
|
8253
|
+
|
|
8254
|
+
// src/pi-agent.ts
|
|
8255
|
+
var import_api14 = require("@opentelemetry/api");
|
|
8256
|
+
var TRACER_NAME8 = "neatlogs.pi-agent";
|
|
8257
|
+
var PATCH_FLAG3 = "_neatlogs_patched";
|
|
8258
|
+
function piAgentHooks(agent) {
|
|
8259
|
+
if (!agent || agent[PATCH_FLAG3]) return agent;
|
|
8260
|
+
const a = agent;
|
|
8261
|
+
if (typeof a.subscribe !== "function") return agent;
|
|
8262
|
+
const state = { toolSpans: /* @__PURE__ */ new Map(), inputMessages: [] };
|
|
8263
|
+
const tracer = import_api14.trace.getTracer(TRACER_NAME8);
|
|
8264
|
+
a.subscribe((event) => {
|
|
8265
|
+
try {
|
|
8266
|
+
handleEvent(tracer, state, event);
|
|
8267
|
+
} catch {
|
|
8268
|
+
}
|
|
8269
|
+
});
|
|
8270
|
+
markPatched2(a);
|
|
8271
|
+
return agent;
|
|
8272
|
+
}
|
|
8273
|
+
function handleEvent(tracer, state, event) {
|
|
8274
|
+
switch (event.type) {
|
|
8275
|
+
case "agent_start": {
|
|
8276
|
+
const span2 = tracer.startSpan(
|
|
8277
|
+
"pi_agent.run",
|
|
8278
|
+
{ attributes: { "neatlogs.span.kind": "AGENT" } },
|
|
8279
|
+
import_api14.context.active()
|
|
8280
|
+
);
|
|
8281
|
+
state.agentSpan = span2;
|
|
8282
|
+
state.agentCtx = import_api14.trace.setSpan(import_api14.context.active(), span2);
|
|
8283
|
+
state.inputMessages = [];
|
|
8284
|
+
break;
|
|
8285
|
+
}
|
|
8286
|
+
case "message_end": {
|
|
8287
|
+
const msg = event.message;
|
|
8288
|
+
if (!msg) return;
|
|
8289
|
+
if (msg.role === "assistant") {
|
|
8290
|
+
emitLlmSpan(tracer, state, msg);
|
|
8291
|
+
const { text } = splitAssistantContent(msg.content);
|
|
8292
|
+
if (text) state.inputMessages.push({ role: "assistant", content: text });
|
|
8293
|
+
} else {
|
|
8294
|
+
const role = msg.role === "toolResult" ? "tool" : String(msg.role || "user");
|
|
8295
|
+
const content = messageText(msg);
|
|
8296
|
+
if (content) state.inputMessages.push({ role, content });
|
|
8297
|
+
}
|
|
8298
|
+
break;
|
|
8299
|
+
}
|
|
8300
|
+
case "tool_execution_start": {
|
|
8301
|
+
const parent = state.agentCtx ?? import_api14.context.active();
|
|
8302
|
+
const span2 = tracer.startSpan(
|
|
8303
|
+
`pi_agent.tool.${event.toolName ?? "tool"}`,
|
|
8304
|
+
{
|
|
8305
|
+
attributes: {
|
|
8306
|
+
"neatlogs.span.kind": "TOOL",
|
|
8307
|
+
...event.toolName ? { "neatlogs.tool.name": String(event.toolName) } : {},
|
|
8308
|
+
...event.args !== void 0 ? { "input.value": safeStringify9(event.args).slice(0, 1e4) } : {}
|
|
8309
|
+
}
|
|
8310
|
+
},
|
|
8311
|
+
parent
|
|
8312
|
+
);
|
|
8313
|
+
if (event.toolCallId) state.toolSpans.set(event.toolCallId, span2);
|
|
8314
|
+
break;
|
|
8315
|
+
}
|
|
8316
|
+
case "tool_execution_end": {
|
|
8317
|
+
const span2 = event.toolCallId ? state.toolSpans.get(event.toolCallId) : void 0;
|
|
8318
|
+
if (!span2) return;
|
|
8319
|
+
if (event.result !== void 0) {
|
|
8320
|
+
span2.setAttribute("output.value", safeStringify9(event.result).slice(0, 1e4));
|
|
8321
|
+
}
|
|
8322
|
+
if (event.isError) {
|
|
8323
|
+
span2.setStatus({ code: import_api14.SpanStatusCode.ERROR });
|
|
8324
|
+
span2.setAttribute("neatlogs.tool.is_error", true);
|
|
8325
|
+
} else {
|
|
8326
|
+
span2.setStatus({ code: import_api14.SpanStatusCode.OK });
|
|
8327
|
+
}
|
|
8328
|
+
span2.end();
|
|
8329
|
+
if (event.toolCallId) state.toolSpans.delete(event.toolCallId);
|
|
8330
|
+
break;
|
|
8331
|
+
}
|
|
8332
|
+
case "agent_end": {
|
|
8333
|
+
for (const ts of state.toolSpans.values()) {
|
|
8334
|
+
try {
|
|
8335
|
+
ts.end();
|
|
8336
|
+
} catch {
|
|
8337
|
+
}
|
|
8338
|
+
}
|
|
8339
|
+
state.toolSpans.clear();
|
|
8340
|
+
if (state.agentSpan) {
|
|
8341
|
+
const firstUser = state.inputMessages.find((m) => m.role === "user");
|
|
8342
|
+
if (firstUser) state.agentSpan.setAttribute("input.value", firstUser.content.slice(0, 1e4));
|
|
8343
|
+
const finalText = lastAssistantText(event.messages);
|
|
8344
|
+
if (finalText) state.agentSpan.setAttribute("output.value", finalText.slice(0, 1e4));
|
|
8345
|
+
state.agentSpan.setStatus({ code: import_api14.SpanStatusCode.OK });
|
|
8346
|
+
state.agentSpan.end();
|
|
8347
|
+
state.agentSpan = void 0;
|
|
8348
|
+
state.agentCtx = void 0;
|
|
8349
|
+
}
|
|
8350
|
+
break;
|
|
8351
|
+
}
|
|
8352
|
+
default:
|
|
8353
|
+
break;
|
|
8354
|
+
}
|
|
8355
|
+
}
|
|
8356
|
+
function emitLlmSpan(tracer, state, msg) {
|
|
8357
|
+
const attrs = { "neatlogs.span.kind": "LLM" };
|
|
8358
|
+
if (msg.model) attrs["neatlogs.llm.model_name"] = String(msg.model);
|
|
8359
|
+
if (msg.provider) attrs["neatlogs.llm.provider"] = String(msg.provider);
|
|
8360
|
+
if (msg.stopReason) attrs["neatlogs.llm.stop_reason"] = String(msg.stopReason);
|
|
8361
|
+
const inMsgs = state.inputMessages;
|
|
8362
|
+
if (inMsgs.length) {
|
|
8363
|
+
inMsgs.forEach((m, i) => {
|
|
8364
|
+
attrs[`neatlogs.llm.input_messages.${i}.role`] = m.role;
|
|
8365
|
+
attrs[`neatlogs.llm.input_messages.${i}.content`] = m.content.slice(0, 1e4);
|
|
8366
|
+
});
|
|
8367
|
+
attrs["neatlogs.llm.input"] = safeStringify9({ messages: inMsgs }).slice(0, 2e4);
|
|
8368
|
+
attrs["input.value"] = safeStringify9({ messages: inMsgs }).slice(0, 1e4);
|
|
8369
|
+
}
|
|
8370
|
+
const { text, toolCalls } = splitAssistantContent(msg.content);
|
|
8371
|
+
const outText = text || toolCalls.map((tc) => `${tc.name}(${safeStringify9(tc.arguments)})`).join("\n");
|
|
8372
|
+
if (outText || toolCalls.length) {
|
|
8373
|
+
attrs["neatlogs.llm.output_messages.0.role"] = "assistant";
|
|
8374
|
+
attrs["neatlogs.llm.output_messages.0.content"] = (outText || "").slice(0, 1e4);
|
|
8375
|
+
const outBlob = { role: "assistant", content: outText || "" };
|
|
8376
|
+
if (toolCalls.length) {
|
|
8377
|
+
outBlob.tool_calls = toolCalls.map((tc) => ({ name: tc.name, arguments: tc.arguments }));
|
|
8378
|
+
toolCalls.forEach((tc, j) => {
|
|
8379
|
+
if (tc.name) attrs[`neatlogs.llm.tool_calls.${j}.name`] = tc.name;
|
|
8380
|
+
if (tc.arguments !== void 0)
|
|
8381
|
+
attrs[`neatlogs.llm.tool_calls.${j}.arguments`] = safeStringify9(tc.arguments);
|
|
8382
|
+
if (tc.id) attrs[`neatlogs.llm.tool_calls.${j}.id`] = String(tc.id);
|
|
8383
|
+
});
|
|
8384
|
+
}
|
|
8385
|
+
attrs["neatlogs.llm.output"] = safeStringify9(outBlob).slice(0, 2e4);
|
|
8386
|
+
attrs["output.value"] = (outText || "").slice(0, 1e4);
|
|
8387
|
+
}
|
|
8388
|
+
const usage = msg.usage;
|
|
8389
|
+
if (usage) {
|
|
8390
|
+
if (usage.input != null) attrs["neatlogs.llm.token_count.prompt"] = usage.input;
|
|
8391
|
+
if (usage.output != null) attrs["neatlogs.llm.token_count.completion"] = usage.output;
|
|
8392
|
+
const total = usage.totalTokens ?? (usage.input ?? 0) + (usage.output ?? 0);
|
|
8393
|
+
if (total) attrs["neatlogs.llm.token_count.total"] = total;
|
|
8394
|
+
if (usage.cacheRead) attrs["neatlogs.llm.token_count.cache_read"] = usage.cacheRead;
|
|
8395
|
+
if (usage.cacheWrite) attrs["neatlogs.llm.token_count.cache_write"] = usage.cacheWrite;
|
|
8396
|
+
}
|
|
8397
|
+
const parent = state.agentCtx ?? import_api14.context.active();
|
|
8398
|
+
const span2 = tracer.startSpan(
|
|
8399
|
+
`pi_agent.llm.${msg.model || "model"}`,
|
|
8400
|
+
{ attributes: attrs },
|
|
8401
|
+
parent
|
|
8402
|
+
);
|
|
8403
|
+
span2.setStatus({ code: import_api14.SpanStatusCode.OK });
|
|
8404
|
+
span2.end();
|
|
8405
|
+
}
|
|
8406
|
+
function splitAssistantContent(content) {
|
|
8407
|
+
const texts = [];
|
|
8408
|
+
const toolCalls = [];
|
|
8409
|
+
if (Array.isArray(content)) {
|
|
8410
|
+
for (const block of content) {
|
|
8411
|
+
if (!block || typeof block !== "object") continue;
|
|
8412
|
+
if (block.type === "text" && typeof block.text === "string") texts.push(block.text);
|
|
8413
|
+
else if (block.type === "toolCall")
|
|
8414
|
+
toolCalls.push(block);
|
|
8415
|
+
}
|
|
8416
|
+
} else if (typeof content === "string") {
|
|
8417
|
+
texts.push(content);
|
|
8418
|
+
}
|
|
8419
|
+
return { text: texts.join(""), toolCalls };
|
|
8420
|
+
}
|
|
8421
|
+
function messageText(msg) {
|
|
8422
|
+
if (!msg) return "";
|
|
8423
|
+
const c = msg.content;
|
|
8424
|
+
if (typeof c === "string") return c;
|
|
8425
|
+
if (!Array.isArray(c)) return "";
|
|
8426
|
+
const parts = [];
|
|
8427
|
+
for (const block of c) {
|
|
8428
|
+
if (typeof block === "string") parts.push(block);
|
|
8429
|
+
else if (block && typeof block === "object") {
|
|
8430
|
+
if (typeof block.text === "string") parts.push(block.text);
|
|
8431
|
+
else if (block.type === "toolCall") parts.push(`${block.name ?? "tool"}(${safeStringify9(block.arguments)})`);
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
return parts.join("");
|
|
8435
|
+
}
|
|
8436
|
+
function lastAssistantText(messages) {
|
|
8437
|
+
if (!Array.isArray(messages)) return "";
|
|
8438
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8439
|
+
const m = messages[i];
|
|
8440
|
+
if (m && m.role === "assistant") {
|
|
8441
|
+
const { text } = splitAssistantContent(m.content);
|
|
8442
|
+
if (text) return text;
|
|
8443
|
+
}
|
|
8444
|
+
}
|
|
8445
|
+
return "";
|
|
8446
|
+
}
|
|
8447
|
+
function markPatched2(e) {
|
|
8448
|
+
try {
|
|
8449
|
+
Object.defineProperty(e, PATCH_FLAG3, { value: true, enumerable: false, configurable: true });
|
|
8450
|
+
} catch {
|
|
8451
|
+
e[PATCH_FLAG3] = true;
|
|
8452
|
+
}
|
|
8453
|
+
}
|
|
8454
|
+
function safeStringify9(value) {
|
|
8455
|
+
if (typeof value === "string") return value;
|
|
8456
|
+
try {
|
|
8457
|
+
return JSON.stringify(value) ?? "";
|
|
8458
|
+
} catch {
|
|
8459
|
+
return "";
|
|
8460
|
+
}
|
|
8461
|
+
}
|
|
8462
|
+
|
|
6481
8463
|
// src/core/llm-binder.ts
|
|
6482
8464
|
var logger15 = getLogger();
|
|
6483
8465
|
function bindTemplates(llm, systemTpl, userTpl, compiledVars) {
|
|
@@ -6549,15 +8531,24 @@ function bindTemplates(llm, systemTpl, userTpl, compiledVars) {
|
|
|
6549
8531
|
getSessionConfig,
|
|
6550
8532
|
init,
|
|
6551
8533
|
isDebugEnabled,
|
|
8534
|
+
langchainHandler,
|
|
6552
8535
|
listPrompts,
|
|
6553
8536
|
log,
|
|
8537
|
+
openaiAgentsProcessor,
|
|
8538
|
+
piAgentHooks,
|
|
6554
8539
|
registerCrewaiTask,
|
|
6555
8540
|
removeTag,
|
|
6556
8541
|
saveAsVersion,
|
|
6557
8542
|
shutdown,
|
|
6558
8543
|
span,
|
|
8544
|
+
strandsHooks,
|
|
6559
8545
|
trace,
|
|
8546
|
+
traceToolAnthropic,
|
|
8547
|
+
traceToolOpenAI,
|
|
6560
8548
|
updatePrompt,
|
|
6561
|
-
wrapAISDK
|
|
8549
|
+
wrapAISDK,
|
|
8550
|
+
wrapAnthropic,
|
|
8551
|
+
wrapMastra,
|
|
8552
|
+
wrapOpenAI
|
|
6562
8553
|
});
|
|
6563
8554
|
//# sourceMappingURL=index.cjs.map
|