neatlogs 1.0.5 → 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/index.cjs CHANGED
@@ -54,6 +54,7 @@ __export(index_exports, {
54
54
  listPrompts: () => listPrompts,
55
55
  log: () => log,
56
56
  openaiAgentsProcessor: () => openaiAgentsProcessor,
57
+ piAgentHooks: () => piAgentHooks,
57
58
  registerCrewaiTask: () => registerCrewaiTask,
58
59
  removeTag: () => removeTag,
59
60
  saveAsVersion: () => saveAsVersion,
@@ -5862,7 +5863,7 @@ async function removeTag(name, tag) {
5862
5863
  }
5863
5864
 
5864
5865
  // src/version.ts
5865
- var __version__ = "1.0.0";
5866
+ var __version__ = "1.0.6";
5866
5867
 
5867
5868
  // src/init.ts
5868
5869
  var logger13 = getLogger();
@@ -7391,20 +7392,143 @@ function safeStringify5(value) {
7391
7392
  }
7392
7393
 
7393
7394
  // src/strands.ts
7395
+ var PATCH_FLAG = "_neatlogs_patched";
7394
7396
  function strandsHooks(agent) {
7397
+ installEventHookFromAgent(agent);
7395
7398
  if (agent && typeof agent === "object") {
7396
7399
  try {
7397
- Object.defineProperty(agent, "_neatlogs_patched", {
7400
+ Object.defineProperty(agent, PATCH_FLAG, {
7398
7401
  value: true,
7399
7402
  enumerable: false,
7400
7403
  configurable: true
7401
7404
  });
7402
7405
  } catch {
7403
- agent._neatlogs_patched = true;
7406
+ agent[PATCH_FLAG] = true;
7404
7407
  }
7405
7408
  }
7406
7409
  return agent;
7407
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
+ }
7408
7532
 
7409
7533
  // src/openai-agents.ts
7410
7534
  var import_api12 = require("@opentelemetry/api");
@@ -7476,7 +7600,7 @@ var NeatlogsTraceProcessor = class {
7476
7600
  const role = typeof msg === "object" ? msg.role ?? "" : "";
7477
7601
  const content = typeof msg === "object" ? msg.content ?? "" : String(msg);
7478
7602
  if (role) attrs[`neatlogs.llm.input_messages.${i}.role`] = role;
7479
- if (content) attrs[`neatlogs.llm.input_messages.${i}.content`] = (typeof content === "string" ? content : safeStringify6(content)).slice(0, 1e4);
7603
+ if (content) attrs[`neatlogs.llm.input_messages.${i}.content`] = (typeof content === "string" ? content : safeStringify7(content)).slice(0, 1e4);
7480
7604
  }
7481
7605
  }
7482
7606
  otelSpan = tracer.startSpan("openai_agents.generation", { attributes: attrs }, parentCtx);
@@ -7488,7 +7612,7 @@ var NeatlogsTraceProcessor = class {
7488
7612
  };
7489
7613
  const toolInput = data?.input ?? data?.arguments;
7490
7614
  if (toolInput !== void 0) {
7491
- attrs["input.value"] = (typeof toolInput === "string" ? toolInput : safeStringify6(toolInput)).slice(0, 1e4);
7615
+ attrs["input.value"] = (typeof toolInput === "string" ? toolInput : safeStringify7(toolInput)).slice(0, 1e4);
7492
7616
  }
7493
7617
  otelSpan = tracer.startSpan(`openai_agents.tool.${toolName}`, { attributes: attrs }, parentCtx);
7494
7618
  } else if (spanType === "handoff") {
@@ -7525,13 +7649,13 @@ var NeatlogsTraceProcessor = class {
7525
7649
  for (let i = 0; i < toolCalls.length; i++) {
7526
7650
  const tc = toolCalls[i];
7527
7651
  otelSpan.setAttribute(`neatlogs.llm.tool_calls.${i}.name`, tc.name ?? "");
7528
- otelSpan.setAttribute(`neatlogs.llm.tool_calls.${i}.arguments`, typeof tc.arguments === "string" ? tc.arguments : safeStringify6(tc.arguments ?? {}));
7652
+ otelSpan.setAttribute(`neatlogs.llm.tool_calls.${i}.arguments`, typeof tc.arguments === "string" ? tc.arguments : safeStringify7(tc.arguments ?? {}));
7529
7653
  if (tc.callId ?? tc.id) otelSpan.setAttribute(`neatlogs.llm.tool_calls.${i}.id`, tc.callId ?? tc.id);
7530
7654
  }
7531
7655
  } else if (outputItems?.content) {
7532
7656
  otelSpan.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
7533
7657
  const c = outputItems.content;
7534
- otelSpan.setAttribute("neatlogs.llm.output_messages.0.content", (typeof c === "string" ? c : safeStringify6(c)).slice(0, 1e4));
7658
+ otelSpan.setAttribute("neatlogs.llm.output_messages.0.content", (typeof c === "string" ? c : safeStringify7(c)).slice(0, 1e4));
7535
7659
  }
7536
7660
  const usage = data?.usage ?? resp?.usage;
7537
7661
  if (usage) {
@@ -7548,12 +7672,12 @@ var NeatlogsTraceProcessor = class {
7548
7672
  } else if (spanType === "function" || spanType === "tool" || spanType === "tool_call") {
7549
7673
  const output = data?.output ?? data?.result;
7550
7674
  if (output != null) {
7551
- otelSpan.setAttribute("output.value", (typeof output === "string" ? output : safeStringify6(output)).slice(0, 1e4));
7675
+ otelSpan.setAttribute("output.value", (typeof output === "string" ? output : safeStringify7(output)).slice(0, 1e4));
7552
7676
  }
7553
7677
  } else if (spanType === "agent" || spanType === "agent_run") {
7554
7678
  const output = data?.output;
7555
7679
  if (output != null) {
7556
- otelSpan.setAttribute("output.value", (typeof output === "string" ? output : safeStringify6(output)).slice(0, 1e4));
7680
+ otelSpan.setAttribute("output.value", (typeof output === "string" ? output : safeStringify7(output)).slice(0, 1e4));
7557
7681
  }
7558
7682
  }
7559
7683
  const error = data?.error ?? span2?.error;
@@ -7585,7 +7709,7 @@ var NeatlogsTraceProcessor = class {
7585
7709
  forceFlush() {
7586
7710
  }
7587
7711
  };
7588
- function safeStringify6(value) {
7712
+ function safeStringify7(value) {
7589
7713
  try {
7590
7714
  return typeof value === "string" ? value : JSON.stringify(value);
7591
7715
  } catch {
@@ -7596,9 +7720,9 @@ function safeStringify6(value) {
7596
7720
  // src/mastra-wrap.ts
7597
7721
  var import_api13 = require("@opentelemetry/api");
7598
7722
  var TRACER_NAME7 = "neatlogs.mastra";
7599
- var PATCH_FLAG = "_neatlogs_patched";
7723
+ var PATCH_FLAG2 = "_neatlogs_patched";
7600
7724
  function wrapMastra(entity) {
7601
- if (!entity || entity[PATCH_FLAG]) return entity;
7725
+ if (!entity || entity[PATCH_FLAG2]) return entity;
7602
7726
  const e = entity;
7603
7727
  const className = entity.constructor?.name ?? "";
7604
7728
  if (isRootMastra(e)) {
@@ -7711,7 +7835,7 @@ function patchModelInPlace(model) {
7711
7835
  if (provider) attrs["neatlogs.llm.provider"] = provider;
7712
7836
  if (isStream) attrs["neatlogs.llm.is_streaming"] = true;
7713
7837
  const promptInput = callOpts?.prompt ?? callOpts?.messages;
7714
- if (promptInput !== void 0) attrs["input.value"] = safeStringify7(promptInput).slice(0, 1e4);
7838
+ if (promptInput !== void 0) attrs["input.value"] = safeStringify8(promptInput).slice(0, 1e4);
7715
7839
  captureInvocationParams(attrs, callOpts);
7716
7840
  return withActiveSpan(`mastra.llm.${modelId || "model"}.${fn}`, attrs, async (span2) => {
7717
7841
  const result = await orig(callOpts);
@@ -7745,12 +7869,12 @@ function patchToolExecute(tool, key) {
7745
7869
  const attrs = {
7746
7870
  "neatlogs.span.kind": "TOOL",
7747
7871
  "neatlogs.tool.name": toolName,
7748
- "input.value": safeStringify7(params).slice(0, 1e4)
7872
+ "input.value": safeStringify8(params).slice(0, 1e4)
7749
7873
  };
7750
7874
  if (tool.description) attrs["neatlogs.tool.description"] = String(tool.description).slice(0, 2e3);
7751
7875
  return withActiveSpan(`mastra.tool.${toolName}`, attrs, async (span2) => {
7752
7876
  const result = await orig(params, options);
7753
- span2.setAttribute("output.value", safeStringify7(result).slice(0, 1e4));
7877
+ span2.setAttribute("output.value", safeStringify8(result).slice(0, 1e4));
7754
7878
  return result;
7755
7879
  });
7756
7880
  };
@@ -7776,13 +7900,13 @@ function patchRunMethod(run, method, workflowName) {
7776
7900
  "neatlogs.workflow.name": workflowName
7777
7901
  };
7778
7902
  if (startOpts?.inputData !== void 0) {
7779
- attrs["input.value"] = safeStringify7(startOpts.inputData).slice(0, 1e4);
7903
+ attrs["input.value"] = safeStringify8(startOpts.inputData).slice(0, 1e4);
7780
7904
  }
7781
7905
  return withActiveSpan(`mastra.workflow.${workflowName}`, attrs, async (span2) => {
7782
7906
  const result = await orig(startOpts);
7783
- if (result?.status) span2.setAttribute("neatlogs.metadata", safeStringify7({ status: result.status }));
7907
+ if (result?.status) span2.setAttribute("neatlogs.metadata", safeStringify8({ status: result.status }));
7784
7908
  if (result?.result !== void 0) {
7785
- span2.setAttribute("output.value", safeStringify7(result.result).slice(0, 1e4));
7909
+ span2.setAttribute("output.value", safeStringify8(result.result).slice(0, 1e4));
7786
7910
  }
7787
7911
  return result;
7788
7912
  });
@@ -7803,14 +7927,14 @@ function patchVectorOp(vector, op, kind) {
7803
7927
  "neatlogs.span.kind": kind,
7804
7928
  "neatlogs.db.system": dbName,
7805
7929
  "neatlogs.db.operation": op,
7806
- "input.value": safeStringify7(params).slice(0, 1e4)
7930
+ "input.value": safeStringify8(params).slice(0, 1e4)
7807
7931
  };
7808
7932
  const indexName = params?.indexName;
7809
7933
  if (indexName) attrs["neatlogs.vectordb.index_name"] = String(indexName);
7810
7934
  if (kind === "RETRIEVER" && params?.topK != null) attrs["neatlogs.retriever.top_k"] = params.topK;
7811
7935
  return withActiveSpan(`mastra.vector.${op}`, attrs, async (span2) => {
7812
7936
  const result = await orig(params);
7813
- span2.setAttribute("output.value", safeStringify7(result).slice(0, 1e4));
7937
+ span2.setAttribute("output.value", safeStringify8(result).slice(0, 1e4));
7814
7938
  return result;
7815
7939
  });
7816
7940
  };
@@ -7824,11 +7948,11 @@ function patchMemory(memory) {
7824
7948
  const attrs = {
7825
7949
  "neatlogs.span.kind": "CHAIN",
7826
7950
  "neatlogs.db.operation": op,
7827
- "input.value": safeStringify7(args?.[0]).slice(0, 1e4)
7951
+ "input.value": safeStringify8(args?.[0]).slice(0, 1e4)
7828
7952
  };
7829
7953
  return withActiveSpan(`mastra.memory.${op}`, attrs, async (span2) => {
7830
7954
  const result = await orig(...args);
7831
- span2.setAttribute("output.value", safeStringify7(result).slice(0, 8e3));
7955
+ span2.setAttribute("output.value", safeStringify8(result).slice(0, 8e3));
7832
7956
  return result;
7833
7957
  });
7834
7958
  };
@@ -8011,7 +8135,7 @@ function finalizeModelResult(span2, result) {
8011
8135
  const tc = toolCalls[i];
8012
8136
  setToolCall(span2, i, tc.toolName, tc.input ?? tc.args, tc.toolCallId);
8013
8137
  }
8014
- span2.setAttribute("output.value", safeStringify7(result.content).slice(0, 1e4));
8138
+ span2.setAttribute("output.value", safeStringify8(result.content).slice(0, 1e4));
8015
8139
  }
8016
8140
  if (result.usage) recordUsage(span2, result.usage);
8017
8141
  span2.setAttribute("neatlogs.llm.stop_reason", normalizeFinishReason(result.finishReason));
@@ -8019,7 +8143,7 @@ function finalizeModelResult(span2, result) {
8019
8143
  function normalizeFinishReason(fr) {
8020
8144
  if (fr == null) return "";
8021
8145
  if (typeof fr === "string") return fr;
8022
- return String(fr.unified ?? fr.reason ?? fr.type ?? safeStringify7(fr));
8146
+ return String(fr.unified ?? fr.reason ?? fr.type ?? safeStringify8(fr));
8023
8147
  }
8024
8148
  function tokenValue(v) {
8025
8149
  if (v == null) return void 0;
@@ -8048,22 +8172,22 @@ function captureInvocationParams(attrs, callOpts) {
8048
8172
  }
8049
8173
  }
8050
8174
  if (Array.isArray(callOpts.stopSequences) && callOpts.stopSequences.length) {
8051
- attrs["neatlogs.llm.stop_sequences"] = safeStringify7(callOpts.stopSequences);
8175
+ attrs["neatlogs.llm.stop_sequences"] = safeStringify8(callOpts.stopSequences);
8052
8176
  invocation.stopSequences = callOpts.stopSequences;
8053
8177
  }
8054
8178
  if (Array.isArray(callOpts.tools)) {
8055
8179
  for (let i = 0; i < callOpts.tools.length; i++) {
8056
- attrs[`neatlogs.llm.tools.${i}`] = safeStringify7(callOpts.tools[i]).slice(0, 4e3);
8180
+ attrs[`neatlogs.llm.tools.${i}`] = safeStringify8(callOpts.tools[i]).slice(0, 4e3);
8057
8181
  }
8058
8182
  invocation.toolChoice = callOpts.toolChoice;
8059
8183
  }
8060
8184
  if (Object.keys(invocation).length) {
8061
- attrs["neatlogs.llm.invocation_parameters"] = safeStringify7(invocation).slice(0, 4e3);
8185
+ attrs["neatlogs.llm.invocation_parameters"] = safeStringify8(invocation).slice(0, 4e3);
8062
8186
  }
8063
8187
  }
8064
8188
  function setToolCall(span2, i, name, args, id) {
8065
8189
  span2.setAttribute(`neatlogs.llm.tool_calls.${i}.name`, name ?? "");
8066
- span2.setAttribute(`neatlogs.llm.tool_calls.${i}.arguments`, safeStringify7(args ?? {}));
8190
+ span2.setAttribute(`neatlogs.llm.tool_calls.${i}.arguments`, safeStringify8(args ?? {}));
8067
8191
  if (id) span2.setAttribute(`neatlogs.llm.tool_calls.${i}.id`, id);
8068
8192
  }
8069
8193
  function recordUsage(span2, usage) {
@@ -8097,9 +8221,9 @@ function withActiveSpan(name, attrs, fn) {
8097
8221
  }
8098
8222
  function markPatched(e) {
8099
8223
  try {
8100
- Object.defineProperty(e, PATCH_FLAG, { value: true, enumerable: false, configurable: true });
8224
+ Object.defineProperty(e, PATCH_FLAG2, { value: true, enumerable: false, configurable: true });
8101
8225
  } catch {
8102
- e[PATCH_FLAG] = true;
8226
+ e[PATCH_FLAG2] = true;
8103
8227
  }
8104
8228
  }
8105
8229
  function extractModelId(model) {
@@ -8108,9 +8232,9 @@ function extractModelId(model) {
8108
8232
  return model.modelId ?? model.name ?? "";
8109
8233
  }
8110
8234
  function toInputValue(input) {
8111
- return (typeof input === "string" ? input : safeStringify7(input)).slice(0, 1e4);
8235
+ return (typeof input === "string" ? input : safeStringify8(input)).slice(0, 1e4);
8112
8236
  }
8113
- function safeStringify7(value) {
8237
+ function safeStringify8(value) {
8114
8238
  if (typeof value === "string") return value;
8115
8239
  try {
8116
8240
  return JSON.stringify(value) ?? "";
@@ -8127,6 +8251,215 @@ function recordError3(span2, err) {
8127
8251
  }
8128
8252
  }
8129
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
+
8130
8463
  // src/core/llm-binder.ts
8131
8464
  var logger15 = getLogger();
8132
8465
  function bindTemplates(llm, systemTpl, userTpl, compiledVars) {
@@ -8202,6 +8535,7 @@ function bindTemplates(llm, systemTpl, userTpl, compiledVars) {
8202
8535
  listPrompts,
8203
8536
  log,
8204
8537
  openaiAgentsProcessor,
8538
+ piAgentHooks,
8205
8539
  registerCrewaiTask,
8206
8540
  removeTag,
8207
8541
  saveAsVersion,