@cognipeer/agent-sdk 0.17.0 → 0.19.0

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.mjs CHANGED
@@ -6,6 +6,8 @@ import path from 'path';
6
6
  import { Buffer as Buffer$1 } from 'buffer';
7
7
  import { nanoid } from 'nanoid';
8
8
  import crypto, { createHash, randomUUID, createHmac } from 'crypto';
9
+ import { gzip } from 'zlib';
10
+ import { promisify } from 'util';
9
11
  import AjvModule from 'ajv';
10
12
 
11
13
  var __defProp = Object.defineProperty;
@@ -1221,9 +1223,1398 @@ function splitUsage(usage) {
1221
1223
  }
1222
1224
  return { own, subagent, ownCalls: ownEntries.length, subagentCalls: subagentEntries.length, ownEntries, subagentEntries };
1223
1225
  }
1226
+ function cacheWriteTokensOf(raw) {
1227
+ if (!raw || typeof raw !== "object") return void 0;
1228
+ const details = raw.prompt_tokens_details || raw.promptTokensDetails || raw.input_token_details || raw.inputTokenDetails || {};
1229
+ const candidates = [
1230
+ details.cache_write_tokens,
1231
+ details.cacheWriteTokens,
1232
+ details.cache_creation,
1233
+ raw.cache_write_tokens,
1234
+ raw.cacheWriteTokens,
1235
+ raw.cache_creation_input_tokens,
1236
+ raw.cacheCreationInputTokens,
1237
+ raw.cacheWriteInputTokens,
1238
+ raw.cacheWriteInputTokenCount
1239
+ ];
1240
+ for (const value of candidates) {
1241
+ const n = Number(value);
1242
+ if (Number.isFinite(n) && n > 0) return n;
1243
+ }
1244
+ return void 0;
1245
+ }
1224
1246
 
1225
1247
  // src/utils/tracing.ts
1226
1248
  init_content();
1249
+
1250
+ // src/version.ts
1251
+ var SDK_VERSION = "0.19.0";
1252
+
1253
+ // src/utils/otlp/content.ts
1254
+ init_content();
1255
+
1256
+ // src/utils/otlp/semconv.ts
1257
+ var GENAI_SEMCONV_COMMIT = "547934a";
1258
+ var ATTR = {
1259
+ operationName: "gen_ai.operation.name",
1260
+ providerName: "gen_ai.provider.name",
1261
+ requestModel: "gen_ai.request.model",
1262
+ responseModel: "gen_ai.response.model",
1263
+ responseId: "gen_ai.response.id",
1264
+ finishReasons: "gen_ai.response.finish_reasons",
1265
+ requestStream: "gen_ai.request.stream",
1266
+ outputType: "gen_ai.output.type",
1267
+ conversationId: "gen_ai.conversation.id",
1268
+ agentName: "gen_ai.agent.name",
1269
+ agentVersion: "gen_ai.agent.version",
1270
+ toolName: "gen_ai.tool.name",
1271
+ toolCallId: "gen_ai.tool.call.id",
1272
+ toolType: "gen_ai.tool.type",
1273
+ usageInput: "gen_ai.usage.input_tokens",
1274
+ usageOutput: "gen_ai.usage.output_tokens",
1275
+ usageCacheRead: "gen_ai.usage.cache_read.input_tokens",
1276
+ usageCacheWrite: "gen_ai.usage.cache_write.input_tokens",
1277
+ usageReasoning: "gen_ai.usage.reasoning.output_tokens",
1278
+ errorType: "error.type",
1279
+ // Content (opt-in).
1280
+ systemInstructions: "gen_ai.system_instructions",
1281
+ inputMessages: "gen_ai.input.messages",
1282
+ outputMessages: "gen_ai.output.messages",
1283
+ toolDefinitions: "gen_ai.tool.definitions",
1284
+ toolCallArguments: "gen_ai.tool.call.arguments",
1285
+ toolCallResult: "gen_ai.tool.call.result"
1286
+ };
1287
+ var OPERATION = {
1288
+ chat: "chat",
1289
+ executeTool: "execute_tool",
1290
+ invokeAgent: "invoke_agent"
1291
+ };
1292
+ var PROVIDERS = {
1293
+ openai: "openai",
1294
+ chatopenai: "openai",
1295
+ azure: "azure.ai.openai",
1296
+ azureopenai: "azure.ai.openai",
1297
+ azurechatopenai: "azure.ai.openai",
1298
+ azureaiopenai: "azure.ai.openai",
1299
+ azureaiinference: "azure.ai.inference",
1300
+ anthropic: "anthropic",
1301
+ chatanthropic: "anthropic",
1302
+ bedrock: "aws.bedrock",
1303
+ awsbedrock: "aws.bedrock",
1304
+ chatbedrock: "aws.bedrock",
1305
+ chatbedrockconverse: "aws.bedrock",
1306
+ vertex: "gcp.vertex_ai",
1307
+ vertexai: "gcp.vertex_ai",
1308
+ gcpvertexai: "gcp.vertex_ai",
1309
+ chatvertexai: "gcp.vertex_ai",
1310
+ gemini: "gcp.gemini",
1311
+ gcpgemini: "gcp.gemini",
1312
+ chatgooglegenerativeai: "gcp.gemini",
1313
+ // Gemini API or Vertex: the name alone does not say which.
1314
+ google: "gcp.gen_ai",
1315
+ gcpgenai: "gcp.gen_ai",
1316
+ mistral: "mistral",
1317
+ mistralai: "mistral",
1318
+ chatmistralai: "mistral",
1319
+ groq: "groq",
1320
+ chatgroq: "groq",
1321
+ deepseek: "deepseek",
1322
+ chatdeepseek: "deepseek",
1323
+ cohere: "cohere",
1324
+ chatcohere: "cohere",
1325
+ xai: "x_ai",
1326
+ chatxai: "x_ai",
1327
+ perplexity: "perplexity",
1328
+ chatperplexity: "perplexity",
1329
+ watsonx: "ibm.watsonx.ai",
1330
+ ibmwatsonxai: "ibm.watsonx.ai"
1331
+ };
1332
+ function genAiProviderName(hint) {
1333
+ if (!hint) return void 0;
1334
+ const key = hint.toLowerCase().replace(/[^a-z0-9]/g, "");
1335
+ return key ? PROVIDERS[key] : void 0;
1336
+ }
1337
+ function errorTypeOf(error) {
1338
+ if (!error) return "_OTHER";
1339
+ if (typeof error.type === "string" && error.type.length > 0) return error.type;
1340
+ if (typeof error.stack === "string") {
1341
+ const match = /^\s*([A-Za-z_$][\w$.]*)\s*(?::|$)/m.exec(error.stack.split("\n", 1)[0] ?? "");
1342
+ if (match) return match[1];
1343
+ }
1344
+ return "_OTHER";
1345
+ }
1346
+ function genAiUsageOf(event) {
1347
+ const num2 = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
1348
+ const input = num2(event.inputTokens);
1349
+ const output = num2(event.outputTokens);
1350
+ const cacheRead = num2(event.cachedInputTokens);
1351
+ const cacheWrite = num2(event.cacheWriteTokens);
1352
+ const reasoning = num2(event.reasoningTokens);
1353
+ if (input + output + cacheRead + cacheWrite + reasoning + num2(event.totalTokens) === 0) return void 0;
1354
+ const basis = event.usageBasis ?? {};
1355
+ return {
1356
+ input: basis.inputExcludesCache ? input + cacheRead + cacheWrite : input,
1357
+ output: basis.outputExcludesReasoning ? output + reasoning : output,
1358
+ ...cacheRead > 0 ? { cacheRead } : {},
1359
+ ...cacheWrite > 0 ? { cacheWrite } : {},
1360
+ ...reasoning > 0 ? { reasoning } : {}
1361
+ };
1362
+ }
1363
+
1364
+ // src/utils/otlp/content.ts
1365
+ var CAPTURE = Symbol.for("cognipeer.agent-sdk.traceCapture");
1366
+ var DEFAULTS = {
1367
+ maxStringChars: 4096,
1368
+ maxMessages: 32,
1369
+ maxAttributeBytes: 32768
1370
+ };
1371
+ var FIELDS = ["system", "input", "output", "tools", "toolArgs", "toolResults", "sections"];
1372
+ function resolveContentOptions(content) {
1373
+ const given = typeof content === "object" && content !== null ? content : {};
1374
+ const enabled = typeof content === "boolean" ? content : given.enabled === true;
1375
+ const positive = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;
1376
+ return {
1377
+ enabled,
1378
+ include: Array.isArray(given.include) ? given.include.filter((field) => FIELDS.includes(field)) : [...FIELDS],
1379
+ maxStringChars: positive(given.maxStringChars, DEFAULTS.maxStringChars),
1380
+ maxMessages: positive(given.maxMessages, DEFAULTS.maxMessages),
1381
+ maxAttributeBytes: positive(given.maxAttributeBytes, DEFAULTS.maxAttributeBytes),
1382
+ redact: typeof given.redact === "function" ? given.redact : void 0,
1383
+ encoding: given.encoding === "structured" ? "structured" : "json"
1384
+ };
1385
+ }
1386
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1387
+ function plain(value) {
1388
+ if (value === void 0) return void 0;
1389
+ try {
1390
+ const text = JSON.stringify(value);
1391
+ return text === void 0 ? void 0 : JSON.parse(text);
1392
+ } catch {
1393
+ return void 0;
1394
+ }
1395
+ }
1396
+ var TRUNCATED_MARKER = /\.\.\.\[truncated (\d+) chars\]$/;
1397
+ function truncateText(text, max) {
1398
+ const earlier = TRUNCATED_MARKER.exec(text);
1399
+ const body = earlier ? text.slice(0, earlier.index) : text;
1400
+ if (body.length <= max) return text;
1401
+ const lost = body.length - max + (earlier ? Number(earlier[1]) : 0);
1402
+ return `${body.slice(0, max)}...[truncated ${lost} chars]`;
1403
+ }
1404
+ function capStrings(value, max) {
1405
+ if (typeof value === "string") return truncateText(value, max);
1406
+ if (Array.isArray(value)) return value.map((item) => capStrings(item, max));
1407
+ if (isRecord2(value)) {
1408
+ const out = {};
1409
+ for (const [key, item] of Object.entries(value)) out[key] = capStrings(item, max);
1410
+ return out;
1411
+ }
1412
+ return value;
1413
+ }
1414
+ function asObject(value) {
1415
+ let parsed = value;
1416
+ if (typeof value === "string") {
1417
+ try {
1418
+ parsed = JSON.parse(value);
1419
+ } catch {
1420
+ parsed = value;
1421
+ }
1422
+ }
1423
+ const copy = plain(parsed);
1424
+ if (copy === void 0) return void 0;
1425
+ return isRecord2(copy) ? copy : { value: copy };
1426
+ }
1427
+ var REASONING_PART_TYPES = /* @__PURE__ */ new Set(["thinking", "redacted_thinking", "reasoning", "reasoning_content"]);
1428
+ function textOf(content) {
1429
+ if (content == null) return "";
1430
+ if (typeof content === "string") return content;
1431
+ if (!Array.isArray(content)) return contentPartToText(content, () => "");
1432
+ return content.filter((part) => !(isRecord2(part) && REASONING_PART_TYPES.has(String(part.type)))).map((part) => contentPartToText(part, () => "")).filter((text) => text.length > 0).join("\n");
1433
+ }
1434
+ function toolCallPartsOf(message) {
1435
+ const calls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
1436
+ const parts = [];
1437
+ for (const call of calls) {
1438
+ if (!isRecord2(call)) continue;
1439
+ const name = call.name ?? call.function?.name;
1440
+ if (typeof name !== "string" || !name) continue;
1441
+ const args = call.args ?? call.arguments ?? call.function?.arguments;
1442
+ const coerced = asObject(args ?? {});
1443
+ const id = typeof call.id === "string" && call.id && !call.idSynthesized ? call.id : void 0;
1444
+ parts.push({ type: "tool_call", ...id ? { id } : {}, name, arguments: coerced ?? {} });
1445
+ }
1446
+ return parts;
1447
+ }
1448
+ function messageOf(raw) {
1449
+ if (!isRecord2(raw)) return void 0;
1450
+ const role = typeof raw.role === "string" ? raw.role : "user";
1451
+ const parts = [];
1452
+ if (role === "tool") {
1453
+ const text2 = textOf(raw.content);
1454
+ const parsed = (() => {
1455
+ try {
1456
+ return JSON.parse(text2);
1457
+ } catch {
1458
+ return text2;
1459
+ }
1460
+ })();
1461
+ parts.push({
1462
+ type: "tool_call_response",
1463
+ ...typeof raw.tool_call_id === "string" && raw.tool_call_id ? { id: raw.tool_call_id } : {},
1464
+ response: plain(parsed) ?? text2
1465
+ });
1466
+ return { role, parts, ...typeof raw.name === "string" && raw.name ? { name: raw.name } : {} };
1467
+ }
1468
+ const text = textOf(raw.content);
1469
+ if (text) parts.push({ type: "text", content: text });
1470
+ if (role === "assistant") parts.push(...toolCallPartsOf(raw));
1471
+ if (parts.length === 0 && role !== "assistant") parts.push({ type: "text", content: "" });
1472
+ return { role, parts };
1473
+ }
1474
+ function buildCapturedContent(source, limits) {
1475
+ const out = {};
1476
+ if (Array.isArray(source.input)) {
1477
+ const system = [];
1478
+ const messages = [];
1479
+ for (const raw of source.input) {
1480
+ const message = messageOf(raw);
1481
+ if (!message) continue;
1482
+ if (message.role === "system") {
1483
+ const content = message.parts.map((part) => part.type === "text" ? part.content : "").join("\n");
1484
+ if (content) system.push({ type: "text", content });
1485
+ } else {
1486
+ messages.push(message);
1487
+ }
1488
+ }
1489
+ if (system.length > 0) out.system = capStrings(system, limits.maxStringChars);
1490
+ const recent = messages.slice(-limits.maxMessages);
1491
+ out.input = capStrings(recent, limits.maxStringChars);
1492
+ }
1493
+ if (source.output !== void 0 && source.output !== null) {
1494
+ const message = messageOf({ ...isRecord2(source.output) ? source.output : { content: String(source.output) }, role: "assistant" });
1495
+ if (message) out.output = capStrings(message, limits.maxStringChars);
1496
+ }
1497
+ if (Array.isArray(source.toolDefinitions) && source.toolDefinitions.length > 0) {
1498
+ out.tools = capStrings(
1499
+ source.toolDefinitions.filter((tool) => tool && typeof tool.name === "string").map((tool) => ({
1500
+ type: "function",
1501
+ name: tool.name,
1502
+ ...tool.description ? { description: tool.description } : {},
1503
+ ...tool.parameters !== void 0 ? { parameters: plain(tool.parameters) } : {}
1504
+ })),
1505
+ limits.maxStringChars
1506
+ );
1507
+ }
1508
+ if (source.toolArguments !== void 0) {
1509
+ const args = asObject(source.toolArguments);
1510
+ if (args !== void 0) out.toolArgs = capStrings(args, limits.maxStringChars);
1511
+ }
1512
+ if (source.hasToolResult || source.toolResult !== void 0) {
1513
+ const result = asObject(source.toolResult);
1514
+ if (result !== void 0) out.toolResults = capStrings(result, limits.maxStringChars);
1515
+ }
1516
+ return out;
1517
+ }
1518
+ function capturedContentOf(event) {
1519
+ return event?.[CAPTURE];
1520
+ }
1521
+ function attachCapturedContent(record, content) {
1522
+ Object.defineProperty(record, CAPTURE, { value: content, enumerable: false, configurable: true, writable: true });
1523
+ }
1524
+ var SEPARATE_SYSTEM = /* @__PURE__ */ new Set(["anthropic", "aws.bedrock", "gcp.vertex_ai", "gcp.gemini"]);
1525
+ function toAnyValue(value) {
1526
+ if (value === null || value === void 0) return void 0;
1527
+ if (typeof value === "string") return { stringValue: value };
1528
+ if (typeof value === "boolean") return { boolValue: value };
1529
+ if (typeof value === "number") {
1530
+ if (!Number.isFinite(value)) return void 0;
1531
+ return Number.isInteger(value) && Number.isSafeInteger(value) ? { intValue: String(value) } : { doubleValue: value };
1532
+ }
1533
+ if (Array.isArray(value)) {
1534
+ return { arrayValue: { values: value.map((item) => toAnyValue(item) ?? { stringValue: "" }) } };
1535
+ }
1536
+ if (isRecord2(value)) {
1537
+ const values = [];
1538
+ for (const [key, item] of Object.entries(value)) {
1539
+ const any = toAnyValue(item);
1540
+ if (any) values.push({ key, value: any });
1541
+ }
1542
+ return { kvlistValue: { values } };
1543
+ }
1544
+ return void 0;
1545
+ }
1546
+ var byteLength = (text) => Buffer$1.byteLength(text, "utf8");
1547
+ function render(value, field, options, info) {
1548
+ let working = plain(value);
1549
+ if (working === void 0) return void 0;
1550
+ if (options.redact) {
1551
+ try {
1552
+ working = options.redact(plain(working), { field, ...info });
1553
+ } catch {
1554
+ return void 0;
1555
+ }
1556
+ working = plain(working);
1557
+ if (working === void 0 || working === null) return void 0;
1558
+ }
1559
+ working = capStrings(working, options.maxStringChars);
1560
+ if ((field === "input" || field === "system" || field === "sections") && Array.isArray(working) && working.length > options.maxMessages) {
1561
+ working = working.slice(-options.maxMessages);
1562
+ }
1563
+ let text = JSON.stringify(working);
1564
+ if (text === void 0) return void 0;
1565
+ if (byteLength(text) > options.maxAttributeBytes) {
1566
+ if (field === "input" && Array.isArray(working)) {
1567
+ const messages = [...working];
1568
+ while (messages.length > 1 && byteLength(JSON.stringify(messages)) > options.maxAttributeBytes) messages.shift();
1569
+ working = messages;
1570
+ text = JSON.stringify(working);
1571
+ }
1572
+ if (byteLength(text) > options.maxAttributeBytes) {
1573
+ working = { truncated: true };
1574
+ text = JSON.stringify(working);
1575
+ }
1576
+ }
1577
+ return options.encoding === "structured" ? toAnyValue(working) : { stringValue: text };
1578
+ }
1579
+ function contentAttributes(kind, event, provider, options) {
1580
+ if (!options?.enabled) return [];
1581
+ const captured = capturedContentOf(event);
1582
+ if (!captured) return [];
1583
+ const include = new Set(options.include);
1584
+ const info = {
1585
+ eventType: event.type,
1586
+ ...event.spanId ? { spanId: event.spanId } : {},
1587
+ ...kind === "execute_tool" && event.actor?.name ? { toolName: event.actor.name } : {},
1588
+ ...event.model ? { model: event.model } : {}
1589
+ };
1590
+ const attrs = [];
1591
+ const add = (key, value) => {
1592
+ if (value) attrs.push({ key, value });
1593
+ };
1594
+ if (kind === "chat") {
1595
+ const separate = provider !== void 0 && SEPARATE_SYSTEM.has(provider);
1596
+ const system = captured.system ?? [];
1597
+ if (separate) {
1598
+ if (include.has("system") && system.length > 0) add(ATTR.systemInstructions, render(system, "system", options, info));
1599
+ if (include.has("input") && captured.input) add(ATTR.inputMessages, render(captured.input, "input", options, info));
1600
+ } else if (include.has("input") && (captured.input || system.length > 0)) {
1601
+ const messages = captured.input ?? [];
1602
+ const capped = messages.slice(-options.maxMessages);
1603
+ const withSystem = system.length > 0 ? [{ role: "system", parts: system }, ...capped] : capped;
1604
+ add(ATTR.inputMessages, render(withSystem, "input", { ...options, maxMessages: options.maxMessages + 1 }, info));
1605
+ }
1606
+ if (include.has("output") && captured.output) {
1607
+ const reason = event.rawFinishReason ?? event.finishReason;
1608
+ const finish = reason === "tool_calls" ? "tool_call" : reason;
1609
+ add(ATTR.outputMessages, render([{ ...captured.output, ...finish ? { finish_reason: finish } : {} }], "output", options, info));
1610
+ }
1611
+ if (include.has("tools") && captured.tools) add(ATTR.toolDefinitions, render(captured.tools, "tools", options, info));
1612
+ } else {
1613
+ if (include.has("toolArgs") && captured.toolArgs !== void 0) add(ATTR.toolCallArguments, render(captured.toolArgs, "toolArgs", options, info));
1614
+ if (include.has("toolResults") && captured.toolResults !== void 0) add(ATTR.toolCallResult, render(captured.toolResults, "toolResults", options, info));
1615
+ }
1616
+ return attrs;
1617
+ }
1618
+ function sectionsAttribute(sections, event, options) {
1619
+ if (!sections || sections.length === 0) return void 0;
1620
+ const identity2 = sections.filter((section) => section.identity === true);
1621
+ const payload = sections.filter((section) => section.identity !== true);
1622
+ let kept = [];
1623
+ if (options?.enabled && options.include.includes("sections") && payload.length > 0) {
1624
+ kept = redactedSections(payload, options, event);
1625
+ }
1626
+ const max = options?.maxAttributeBytes ?? DEFAULTS.maxAttributeBytes;
1627
+ const encode = (list) => {
1628
+ try {
1629
+ return JSON.stringify(list);
1630
+ } catch {
1631
+ return void 0;
1632
+ }
1633
+ };
1634
+ let text = encode([...identity2, ...kept]);
1635
+ while (text !== void 0 && kept.length > 0 && byteLength(text) > max) {
1636
+ kept.shift();
1637
+ text = encode([...identity2, ...kept]);
1638
+ }
1639
+ if (text === void 0) {
1640
+ text = encode(identity2);
1641
+ }
1642
+ if (text === void 0 || text === "[]") return void 0;
1643
+ return { key: "cognipeer.sections", value: { stringValue: text } };
1644
+ }
1645
+ function redactedSections(payload, options, event) {
1646
+ let working = plain(payload);
1647
+ if (working === void 0) return [];
1648
+ if (options.redact) {
1649
+ try {
1650
+ working = plain(options.redact(plain(working), {
1651
+ field: "sections",
1652
+ eventType: event.type,
1653
+ ...event.spanId ? { spanId: event.spanId } : {},
1654
+ ...event.model ? { model: event.model } : {}
1655
+ }));
1656
+ } catch {
1657
+ return [];
1658
+ }
1659
+ if (!Array.isArray(working)) return [];
1660
+ }
1661
+ const capped = capStrings(working, options.maxStringChars);
1662
+ return Array.isArray(capped) ? capped.slice(-options.maxMessages) : [];
1663
+ }
1664
+
1665
+ // src/utils/otlp/convert.ts
1666
+ var SCOPE_NAME = "cognipeer-agent-sdk";
1667
+ var SPAN_KIND_INTERNAL = 1;
1668
+ var SPAN_KIND_CLIENT = 3;
1669
+ var FLAG_HAS_PARENT = 256;
1670
+ var FLAG_REMOTE_PARENT = 512;
1671
+ var MAX_STATUS_MESSAGE = 1024;
1672
+ var str = (key, value) => value != null && value !== "" ? { key, value: { stringValue: value } } : null;
1673
+ var strAllowEmpty = (key, value) => value != null ? { key, value: { stringValue: value } } : null;
1674
+ var int = (key, value) => typeof value === "number" && Number.isFinite(value) ? { key, value: { intValue: String(Math.trunc(value)) } } : null;
1675
+ var dbl = (key, value) => typeof value === "number" && Number.isFinite(value) ? { key, value: { doubleValue: value } } : null;
1676
+ var bool = (key, value) => typeof value === "boolean" ? { key, value: { boolValue: value } } : null;
1677
+ var strArray = (key, values) => ({
1678
+ key,
1679
+ value: { arrayValue: { values: values.map((value) => ({ stringValue: value })) } }
1680
+ });
1681
+ var compact = (list) => list.filter((entry) => Boolean(entry));
1682
+ function msToNs(ms) {
1683
+ const whole = Math.floor(ms);
1684
+ return BigInt(whole) * 1000000n + BigInt(Math.round((ms - whole) * 1e6));
1685
+ }
1686
+ function parseMs(iso) {
1687
+ if (!iso) return void 0;
1688
+ const value = Date.parse(iso);
1689
+ return Number.isNaN(value) ? void 0 : value;
1690
+ }
1691
+ function durationNs(durationMs) {
1692
+ return typeof durationMs === "number" && Number.isFinite(durationMs) && durationMs > 0 ? msToNs(durationMs) : 0n;
1693
+ }
1694
+ function classify(event) {
1695
+ if (event.type === "ai_call" || event.type === "summarization") {
1696
+ if (event.skipReason === "cancelled") return "chat";
1697
+ if (event.skipReason || event.status === "skipped") return "plain";
1698
+ return "chat";
1699
+ }
1700
+ if (event.type === "tool_call") {
1701
+ const source = event.debug?.shortCircuitSource;
1702
+ if (event.skipReason || event.status === "skipped" || source === "cache" || source === "plugin") return "plain";
1703
+ if (event.status === "pending") return "plain";
1704
+ return "execute_tool";
1705
+ }
1706
+ if (event.type === "span" && event.actor?.role === "subagent") return "invoke_agent";
1707
+ return "plain";
1708
+ }
1709
+ var knownModel = (model) => model && model !== "unknown-model" && model !== "unknown_model" ? model : void 0;
1710
+ function toolNameOf(event) {
1711
+ if (event.actor?.name) return event.actor.name;
1712
+ const label = event.label.replace(/\s#\d+$/, "");
1713
+ const dash = label.indexOf(" - ");
1714
+ return dash >= 0 ? label.slice(dash + 3) : void 0;
1715
+ }
1716
+ var stripSequence = (label) => label.replace(/\s#\d+$/, "");
1717
+ function cappedMessage(message) {
1718
+ const text = message && message.length > 0 ? message : "Unknown error";
1719
+ return text.length > MAX_STATUS_MESSAGE ? text.slice(0, MAX_STATUS_MESSAGE) : text;
1720
+ }
1721
+ function exceptionEvent(timeNs, error) {
1722
+ return {
1723
+ timeUnixNano: timeNs.toString(),
1724
+ name: "exception",
1725
+ attributes: compact([
1726
+ str("exception.type", errorTypeOf(error)),
1727
+ strAllowEmpty("exception.message", error.message ?? "Unknown error"),
1728
+ str("exception.stacktrace", error.stack)
1729
+ ])
1730
+ };
1731
+ }
1732
+ function sessionToOtlp(file, options) {
1733
+ const useCognipeer = options.semconv !== "gen_ai";
1734
+ const useGenAi = options.semconv !== "cognipeer";
1735
+ const traceId = file.traceId || generateTraceId();
1736
+ const rootSpanId = file.rootSpanId || generateSpanId();
1737
+ const parent = options.parent;
1738
+ const traceState = parent?.traceState || void 0;
1739
+ const traceFlags = (typeof parent?.flags === "number" ? parent.flags : 1) & 255;
1740
+ const flags = traceFlags | FLAG_HAS_PARENT;
1741
+ const rootFlags = parent?.remote ? flags | FLAG_REMOTE_PARENT : flags;
1742
+ const agentName = file.agent?.name;
1743
+ const everyEvent = file.events;
1744
+ const exportedEvents = foldSupersededSpans(everyEvent).filter(
1745
+ (event) => options.terminal || !(event.type === "span" && (event.status === "pending" || event.status === "running"))
1746
+ );
1747
+ const startMs = parseMs(file.startedAt);
1748
+ const nodes = exportedEvents.map((event) => {
1749
+ const endMs = parseMs(event.timestamp) ?? startMs ?? Date.now();
1750
+ const endNs = msToNs(endMs);
1751
+ let startNs = endNs - durationNs(event.durationMs);
1752
+ if (startNs < 0n) startNs = 0n;
1753
+ return {
1754
+ event,
1755
+ spanId: event.spanId || generateSpanId(),
1756
+ parentId: event.parentSpanId || rootSpanId,
1757
+ startNs,
1758
+ endNs
1759
+ };
1760
+ });
1761
+ const childrenOf = /* @__PURE__ */ new Map();
1762
+ for (const node of nodes) {
1763
+ const list = childrenOf.get(node.parentId);
1764
+ if (list) list.push(node);
1765
+ else childrenOf.set(node.parentId, [node]);
1766
+ }
1767
+ const settled = /* @__PURE__ */ new Set();
1768
+ const inProgress = /* @__PURE__ */ new Set();
1769
+ const widen = (node) => {
1770
+ if (settled.has(node) || inProgress.has(node)) return;
1771
+ inProgress.add(node);
1772
+ for (const child of childrenOf.get(node.spanId) ?? []) {
1773
+ if (child === node) continue;
1774
+ widen(child);
1775
+ if (child.startNs < node.startNs) node.startNs = child.startNs;
1776
+ if (child.endNs > node.endNs) node.endNs = child.endNs;
1777
+ }
1778
+ inProgress.delete(node);
1779
+ settled.add(node);
1780
+ };
1781
+ for (const node of nodes) widen(node);
1782
+ const byId = /* @__PURE__ */ new Map();
1783
+ for (const event of everyEvent) if (event.spanId) byId.set(event.spanId, event);
1784
+ const agentOf = (event) => {
1785
+ let cursor = event;
1786
+ for (let hops = 0; cursor && hops < 64; hops++) {
1787
+ if (cursor !== event && cursor.type === "span" && cursor.actor?.role === "subagent") return cursor.actor.name;
1788
+ cursor = cursor.parentSpanId ? byId.get(cursor.parentSpanId) : void 0;
1789
+ }
1790
+ return agentName;
1791
+ };
1792
+ const spans = [];
1793
+ const sessionErrors = (file.errors ?? []).filter((error) => error.eventId === "session");
1794
+ if (options.terminal) {
1795
+ const earliestChild = nodes.reduce(
1796
+ (earliest, node) => earliest === void 0 || node.startNs < earliest ? node.startNs : earliest,
1797
+ void 0
1798
+ );
1799
+ let rootStart = startMs !== void 0 ? msToNs(startMs) : earliestChild ?? msToNs(Date.now());
1800
+ let rootEnd = msToNs(parseMs(file.endedAt) ?? (startMs !== void 0 ? startMs + (file.durationMs ?? 0) : Date.now()));
1801
+ for (const node of childrenOf.get(rootSpanId) ?? []) {
1802
+ if (node.startNs < rootStart) rootStart = node.startNs;
1803
+ if (node.endNs > rootEnd) rootEnd = node.endNs;
1804
+ }
1805
+ if (rootEnd < rootStart) rootEnd = rootStart;
1806
+ const rootName = useGenAi ? agentName ? `${OPERATION.invokeAgent} ${agentName}` : OPERATION.invokeAgent : `agent_session: ${agentName || "agent"}`;
1807
+ const summary = file.summary;
1808
+ const cumulativeEvents = summary?.eventCounts ? Object.values(summary.eventCounts).reduce((total, count) => total + (Number(count) || 0), 0) : file.events.length;
1809
+ const attributes = [];
1810
+ if (useCognipeer) {
1811
+ attributes.push(
1812
+ ...compact([
1813
+ strAllowEmpty("cognipeer.session.status", options.cancelled ? "partial" : file.status),
1814
+ dbl("cognipeer.session.duration_ms", file.durationMs),
1815
+ int("cognipeer.session.total_input_tokens", summary?.totalInputTokens),
1816
+ int("cognipeer.session.total_output_tokens", summary?.totalOutputTokens),
1817
+ int("cognipeer.session.total_cached_input_tokens", summary?.totalCachedInputTokens),
1818
+ int("cognipeer.session.total_bytes_in", summary?.totalBytesIn),
1819
+ int("cognipeer.session.total_bytes_out", summary?.totalBytesOut),
1820
+ int("cognipeer.session.event_count", cumulativeEvents)
1821
+ ])
1822
+ );
1823
+ for (const [key, count] of Object.entries(summary?.eventCounts ?? {})) {
1824
+ attributes.push({ key: `cognipeer.session.event_count.${key}`, value: { intValue: String(count) } });
1825
+ }
1826
+ }
1827
+ if (useGenAi) {
1828
+ attributes.push(
1829
+ ...compact([
1830
+ str(ATTR.operationName, OPERATION.invokeAgent),
1831
+ str(ATTR.agentName, agentName),
1832
+ str(ATTR.agentVersion, file.agent?.version),
1833
+ str(ATTR.requestModel, knownModel(file.agent?.model)),
1834
+ str(ATTR.conversationId, file.threadId)
1835
+ ])
1836
+ );
1837
+ }
1838
+ const root = {
1839
+ traceId,
1840
+ spanId: rootSpanId,
1841
+ parentSpanId: parent?.spanId ?? "",
1842
+ ...traceState ? { traceState } : {},
1843
+ flags: rootFlags,
1844
+ name: rootName,
1845
+ kind: SPAN_KIND_INTERNAL,
1846
+ startTimeUnixNano: rootStart.toString(),
1847
+ endTimeUnixNano: rootEnd.toString(),
1848
+ attributes,
1849
+ status: { code: 0 }
1850
+ };
1851
+ if (sessionErrors.length > 0) {
1852
+ root.status = {
1853
+ code: 2,
1854
+ message: cappedMessage(sessionErrors.map((error) => error.message).join("; "))
1855
+ };
1856
+ if (useGenAi) root.attributes.push({ key: ATTR.errorType, value: { stringValue: errorTypeOf({ type: sessionErrors[0].errorName, stack: sessionErrors[0].stack }) } });
1857
+ root.events = sessionErrors.map((error) => {
1858
+ const at = parseMs(error.timestamp);
1859
+ return exceptionEvent(at !== void 0 ? msToNs(at) : rootEnd, {
1860
+ message: error.message,
1861
+ stack: error.stack,
1862
+ type: error.errorName
1863
+ });
1864
+ });
1865
+ }
1866
+ spans.push(root);
1867
+ }
1868
+ for (const node of nodes) {
1869
+ const event = node.event;
1870
+ const kind = classify(event);
1871
+ const failed = event.status === "error";
1872
+ const cancelledChat = kind === "chat" && event.skipReason === "cancelled";
1873
+ const attributes = [];
1874
+ if (useCognipeer) {
1875
+ attributes.push(
1876
+ ...compact([
1877
+ strAllowEmpty("cognipeer.event.type", event.type),
1878
+ strAllowEmpty("cognipeer.event.label", event.label),
1879
+ int("cognipeer.event.sequence", event.sequence),
1880
+ strAllowEmpty("cognipeer.actor.scope", event.actor?.scope),
1881
+ strAllowEmpty("cognipeer.actor.name", event.actor?.name),
1882
+ strAllowEmpty("cognipeer.actor.role", event.actor?.role),
1883
+ strAllowEmpty("cognipeer.model", event.model),
1884
+ int("cognipeer.tokens.reasoning", event.reasoningTokens),
1885
+ strAllowEmpty("cognipeer.finish_reason", event.finishReason),
1886
+ strAllowEmpty("cognipeer.provider", event.provider),
1887
+ strAllowEmpty("cognipeer.tool.details", event.toolDetails ? JSON.stringify(event.toolDetails) : void 0),
1888
+ int("cognipeer.tokens.input", event.inputTokens),
1889
+ int("cognipeer.tokens.output", event.outputTokens),
1890
+ int("cognipeer.tokens.total", event.totalTokens),
1891
+ int("cognipeer.tokens.cached_input", event.cachedInputTokens),
1892
+ int("cognipeer.bytes.request", event.requestBytes),
1893
+ int("cognipeer.bytes.response", event.responseBytes),
1894
+ strAllowEmpty("cognipeer.tool.execution_id", event.toolExecutionId),
1895
+ strAllowEmpty("cognipeer.retry_of", event.retryOf),
1896
+ strAllowEmpty("cognipeer.event.id", event.id)
1897
+ ])
1898
+ );
1899
+ const sectionsAttr = sectionsAttribute(event.data?.sections, event, options.content);
1900
+ if (sectionsAttr) attributes.push(sectionsAttr);
1901
+ attributes.push({ key: "cognipeer.event.status", value: { stringValue: event.status } });
1902
+ }
1903
+ let name = event.label || event.type;
1904
+ let spanKind = SPAN_KIND_INTERNAL;
1905
+ if (kind === "chat") spanKind = SPAN_KIND_CLIENT;
1906
+ if (useGenAi) {
1907
+ const conversation = str(ATTR.conversationId, file.threadId);
1908
+ if (kind === "chat") {
1909
+ const model = knownModel(event.model);
1910
+ name = model ? `${OPERATION.chat} ${model}` : OPERATION.chat;
1911
+ attributes.push(
1912
+ ...compact([
1913
+ str(ATTR.operationName, OPERATION.chat),
1914
+ str(ATTR.providerName, genAiProviderName(event.provider)),
1915
+ str(ATTR.requestModel, model),
1916
+ str(ATTR.responseModel, event.responseModel),
1917
+ str(ATTR.responseId, event.responseId),
1918
+ bool(ATTR.requestStream, event.streaming),
1919
+ str(ATTR.outputType, event.outputType)
1920
+ ])
1921
+ );
1922
+ if (failed || cancelledChat) {
1923
+ attributes.push(strArray(ATTR.finishReasons, ["error"]));
1924
+ } else {
1925
+ const reason = event.rawFinishReason ?? event.finishReason;
1926
+ if (reason) attributes.push(strArray(ATTR.finishReasons, [reason]));
1927
+ }
1928
+ const usageAllowed = !failed && !cancelledChat && (event.type !== "summarization" || event.debug?.usageFromModel === true);
1929
+ const usage = usageAllowed ? genAiUsageOf(event) : void 0;
1930
+ if (usage) {
1931
+ attributes.push(
1932
+ ...compact([
1933
+ int(ATTR.usageInput, usage.input),
1934
+ int(ATTR.usageOutput, usage.output),
1935
+ int(ATTR.usageCacheRead, usage.cacheRead),
1936
+ int(ATTR.usageCacheWrite, usage.cacheWrite),
1937
+ int(ATTR.usageReasoning, usage.reasoning)
1938
+ ])
1939
+ );
1940
+ }
1941
+ if (conversation) attributes.push(conversation);
1942
+ attributes.push(...contentAttributes("chat", event, genAiProviderName(event.provider), options.content));
1943
+ } else if (kind === "execute_tool") {
1944
+ const tool = toolNameOf(event);
1945
+ name = tool ? `${OPERATION.executeTool} ${tool}` : OPERATION.executeTool;
1946
+ attributes.push(
1947
+ ...compact([
1948
+ str(ATTR.operationName, OPERATION.executeTool),
1949
+ str(ATTR.toolName, tool),
1950
+ str(ATTR.toolCallId, event.toolCallId),
1951
+ str(ATTR.toolType, "function"),
1952
+ str(ATTR.agentName, agentOf(event)),
1953
+ conversation
1954
+ ])
1955
+ );
1956
+ attributes.push(...contentAttributes("execute_tool", event, void 0, options.content));
1957
+ } else if (kind === "invoke_agent") {
1958
+ const child = event.actor?.name;
1959
+ name = child ? `${OPERATION.invokeAgent} ${child}` : OPERATION.invokeAgent;
1960
+ attributes.push(...compact([str(ATTR.operationName, OPERATION.invokeAgent), str(ATTR.agentName, child), conversation]));
1961
+ } else {
1962
+ name = stripSequence(name);
1963
+ }
1964
+ }
1965
+ const span = {
1966
+ traceId: event.traceId || traceId,
1967
+ spanId: node.spanId,
1968
+ parentSpanId: node.parentId,
1969
+ ...traceState ? { traceState } : {},
1970
+ flags,
1971
+ name,
1972
+ kind: spanKind,
1973
+ startTimeUnixNano: node.startNs.toString(),
1974
+ endTimeUnixNano: node.endNs.toString(),
1975
+ attributes,
1976
+ status: { code: 0 }
1977
+ };
1978
+ if (failed) {
1979
+ const error = event.error ?? { message: "Unknown error" };
1980
+ span.status = { code: 2, message: cappedMessage(error.message) };
1981
+ if (useGenAi) attributes.push({ key: ATTR.errorType, value: { stringValue: errorTypeOf(error) } });
1982
+ span.events = [exceptionEvent(node.endNs, error)];
1983
+ }
1984
+ spans.push(span);
1985
+ }
1986
+ return {
1987
+ resourceSpans: [
1988
+ {
1989
+ resource: { attributes: resourceAttributesOf(file, options, useCognipeer) },
1990
+ scopeSpans: [{ scope: { name: SCOPE_NAME, version: SDK_VERSION }, spans }]
1991
+ }
1992
+ ]
1993
+ };
1994
+ }
1995
+ function resourceAttributesOf(file, options, useCognipeer) {
1996
+ const custom = options.resourceAttributes ?? {};
1997
+ const serviceName = options.serviceName || custom["service.name"] || file.agent?.name || "cognipeer-agent";
1998
+ const attributes = compact([
1999
+ str("service.name", serviceName),
2000
+ str("service.version", file.agent?.version)
2001
+ ]);
2002
+ if (useCognipeer) {
2003
+ attributes.push(
2004
+ ...compact([
2005
+ str("cognipeer.session.id", file.sessionId),
2006
+ str("cognipeer.thread.id", file.threadId),
2007
+ str("cognipeer.agent.model", file.agent?.model),
2008
+ str("cognipeer.agent.provider", file.agent?.provider),
2009
+ ...Object.entries(file.metadata ?? {}).map(([key, value]) => str(`cognipeer.metadata.${key}`, value))
2010
+ ])
2011
+ );
2012
+ }
2013
+ attributes.push(
2014
+ ...compact([
2015
+ str("telemetry.sdk.name", SCOPE_NAME),
2016
+ str("telemetry.sdk.language", "nodejs"),
2017
+ str("telemetry.sdk.version", SDK_VERSION)
2018
+ ])
2019
+ );
2020
+ for (const [key, value] of Object.entries(custom)) {
2021
+ if (key === "service.name") continue;
2022
+ const index = attributes.findIndex((attr) => attr.key === key);
2023
+ const entry = str(key, value);
2024
+ if (!entry) continue;
2025
+ if (index >= 0) attributes[index] = entry;
2026
+ else attributes.push(entry);
2027
+ }
2028
+ return attributes;
2029
+ }
2030
+ function countSpans(request) {
2031
+ let total = 0;
2032
+ for (const rs of request.resourceSpans) for (const ss of rs.scopeSpans) total += ss.spans.length;
2033
+ return total;
2034
+ }
2035
+
2036
+ // src/utils/otlp/env.ts
2037
+ var warned = /* @__PURE__ */ new Set();
2038
+ function warnOnce(message) {
2039
+ if (warned.has(message)) return;
2040
+ warned.add(message);
2041
+ if (typeof console !== "undefined" && typeof console.warn === "function") console.warn(message);
2042
+ }
2043
+ function pick(env, ...names) {
2044
+ for (const name of names) {
2045
+ const value = env[name];
2046
+ if (typeof value === "string" && value.trim().length > 0) return value.trim();
2047
+ }
2048
+ return void 0;
2049
+ }
2050
+ function decode(value) {
2051
+ try {
2052
+ return decodeURIComponent(value);
2053
+ } catch {
2054
+ return value;
2055
+ }
2056
+ }
2057
+ function parseKeyValueList(raw) {
2058
+ const out = {};
2059
+ if (!raw) return out;
2060
+ for (const part of raw.split(",")) {
2061
+ const index = part.indexOf("=");
2062
+ if (index <= 0) continue;
2063
+ const key = part.slice(0, index).trim();
2064
+ if (!key) continue;
2065
+ out[key] = decode(part.slice(index + 1).trim());
2066
+ }
2067
+ return out;
2068
+ }
2069
+ function tracesEndpointFrom(base) {
2070
+ return `${base.replace(/\/+$/, "")}/v1/traces`;
2071
+ }
2072
+ function protocolFrom(raw, fallback) {
2073
+ if (!raw) return fallback;
2074
+ const value = raw.toLowerCase();
2075
+ if (value === "http/protobuf" || value === "http/json") return value;
2076
+ warnOnce(
2077
+ value === "grpc" ? `[agent-sdk] OTLP/gRPC is not supported; exporting over ${fallback} instead.` : `[agent-sdk] OTLP protocol "${raw}" is not supported (use http/json or http/protobuf); falling back to ${fallback}.`
2078
+ );
2079
+ return fallback;
2080
+ }
2081
+ function resolveOtlpEnv(env, explicit) {
2082
+ const explicitEndpoint = typeof explicit.endpoint === "string" ? explicit.endpoint.trim() : "";
2083
+ const envDriven = explicitEndpoint.length === 0;
2084
+ const resourceAttributes = parseKeyValueList(pick(env, "OTEL_RESOURCE_ATTRIBUTES"));
2085
+ const serviceName = pick(env, "OTEL_SERVICE_NAME");
2086
+ if (!envDriven) {
2087
+ return {
2088
+ envDriven,
2089
+ endpoint: explicitEndpoint,
2090
+ headers: { ...explicit.headers ?? {} },
2091
+ protocol: explicit.protocol ?? "http/json",
2092
+ compression: explicit.compression ?? "none",
2093
+ timeoutMs: explicit.timeoutMs,
2094
+ serviceName,
2095
+ resourceAttributes,
2096
+ disabled: false
2097
+ };
2098
+ }
2099
+ const tracesEndpoint = pick(env, "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT");
2100
+ const baseEndpoint = pick(env, "OTEL_EXPORTER_OTLP_ENDPOINT");
2101
+ const endpoint = tracesEndpoint ?? (baseEndpoint ? tracesEndpointFrom(baseEndpoint) : void 0);
2102
+ const envHeaders = {
2103
+ ...parseKeyValueList(pick(env, "OTEL_EXPORTER_OTLP_HEADERS")),
2104
+ ...parseKeyValueList(pick(env, "OTEL_EXPORTER_OTLP_TRACES_HEADERS"))
2105
+ };
2106
+ const timeoutRaw = pick(env, "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT", "OTEL_EXPORTER_OTLP_TIMEOUT");
2107
+ const timeout = timeoutRaw !== void 0 ? Number(timeoutRaw) : void 0;
2108
+ const compressionRaw = pick(env, "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION", "OTEL_EXPORTER_OTLP_COMPRESSION")?.toLowerCase();
2109
+ return {
2110
+ envDriven,
2111
+ endpoint,
2112
+ headers: { ...envHeaders, ...explicit.headers ?? {} },
2113
+ protocol: explicit.protocol ?? protocolFrom(pick(env, "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "OTEL_EXPORTER_OTLP_PROTOCOL"), "http/protobuf"),
2114
+ compression: explicit.compression ?? (compressionRaw === "gzip" ? "gzip" : "none"),
2115
+ timeoutMs: explicit.timeoutMs ?? (timeout !== void 0 && Number.isFinite(timeout) && timeout > 0 ? timeout : void 0),
2116
+ serviceName,
2117
+ resourceAttributes,
2118
+ disabled: pick(env, "OTEL_SDK_DISABLED")?.toLowerCase() === "true" || pick(env, "OTEL_TRACES_EXPORTER")?.toLowerCase() === "none"
2119
+ };
2120
+ }
2121
+ function currentEnv() {
2122
+ return typeof process !== "undefined" && process.env ? process.env : {};
2123
+ }
2124
+ var WIRE_VARINT = 0;
2125
+ var WIRE_FIXED64 = 1;
2126
+ var WIRE_LEN = 2;
2127
+ var WIRE_FIXED32 = 5;
2128
+ var textEncoder = new TextEncoder();
2129
+ var Writer = class {
2130
+ constructor() {
2131
+ this.buf = new Uint8Array(128);
2132
+ this.len = 0;
2133
+ this.view = new DataView(this.buf.buffer);
2134
+ }
2135
+ ensure(extra) {
2136
+ if (this.len + extra <= this.buf.length) return;
2137
+ let size = this.buf.length * 2;
2138
+ while (size < this.len + extra) size *= 2;
2139
+ const next = new Uint8Array(size);
2140
+ next.set(this.buf.subarray(0, this.len));
2141
+ this.buf = next;
2142
+ this.view = new DataView(next.buffer);
2143
+ }
2144
+ byte(value) {
2145
+ this.ensure(1);
2146
+ this.buf[this.len++] = value;
2147
+ }
2148
+ varint(value) {
2149
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
2150
+ let n2 = value;
2151
+ while (n2 >= 128) {
2152
+ this.byte(n2 % 128 | 128);
2153
+ n2 = Math.floor(n2 / 128);
2154
+ }
2155
+ this.byte(n2);
2156
+ return;
2157
+ }
2158
+ let n = BigInt.asUintN(64, BigInt(value));
2159
+ while (n >= 128n) {
2160
+ this.byte(Number(n & 127n) | 128);
2161
+ n >>= 7n;
2162
+ }
2163
+ this.byte(Number(n));
2164
+ }
2165
+ tag(field, wire) {
2166
+ this.varint(field * 8 + wire);
2167
+ }
2168
+ raw(bytes) {
2169
+ this.ensure(bytes.length);
2170
+ this.buf.set(bytes, this.len);
2171
+ this.len += bytes.length;
2172
+ }
2173
+ fixed64(value) {
2174
+ this.ensure(8);
2175
+ this.view.setBigUint64(this.len, BigInt.asUintN(64, value), true);
2176
+ this.len += 8;
2177
+ }
2178
+ fixed32(value) {
2179
+ this.ensure(4);
2180
+ this.view.setUint32(this.len, value >>> 0, true);
2181
+ this.len += 4;
2182
+ }
2183
+ double(value) {
2184
+ this.ensure(8);
2185
+ this.view.setFloat64(this.len, value, true);
2186
+ this.len += 8;
2187
+ }
2188
+ finish() {
2189
+ return this.buf.slice(0, this.len);
2190
+ }
2191
+ };
2192
+ function lenField(w, field, bytes) {
2193
+ w.tag(field, WIRE_LEN);
2194
+ w.varint(bytes.length);
2195
+ w.raw(bytes);
2196
+ }
2197
+ function stringField(w, field, value) {
2198
+ if (!value) return;
2199
+ lenField(w, field, textEncoder.encode(value));
2200
+ }
2201
+ function hexBytes(hex, bytes) {
2202
+ if (!hex) return void 0;
2203
+ const out = new Uint8Array(bytes);
2204
+ for (let i = 0; i < bytes; i++) {
2205
+ const pair = hex.slice(i * 2, i * 2 + 2);
2206
+ const value = /^[0-9a-fA-F]{2}$/.test(pair) ? parseInt(pair, 16) : 0;
2207
+ out[i] = value;
2208
+ }
2209
+ return out;
2210
+ }
2211
+ function base64Bytes(value) {
2212
+ return new Uint8Array(Buffer$1.from(value, "base64"));
2213
+ }
2214
+ function encodeAnyValue(value) {
2215
+ const w = new Writer();
2216
+ if (value.stringValue !== void 0) {
2217
+ lenField(w, 1, textEncoder.encode(value.stringValue));
2218
+ } else if (value.boolValue !== void 0) {
2219
+ w.tag(2, WIRE_VARINT);
2220
+ w.varint(value.boolValue ? 1 : 0);
2221
+ } else if (value.intValue !== void 0) {
2222
+ w.tag(3, WIRE_VARINT);
2223
+ w.varint(BigInt(value.intValue));
2224
+ } else if (value.doubleValue !== void 0) {
2225
+ w.tag(4, WIRE_FIXED64);
2226
+ w.double(value.doubleValue);
2227
+ } else if (value.arrayValue !== void 0) {
2228
+ const inner = new Writer();
2229
+ for (const item of value.arrayValue.values) lenField(inner, 1, encodeAnyValue(item));
2230
+ lenField(w, 5, inner.finish());
2231
+ } else if (value.kvlistValue !== void 0) {
2232
+ const inner = new Writer();
2233
+ for (const kv of value.kvlistValue.values) lenField(inner, 1, encodeKeyValue(kv));
2234
+ lenField(w, 6, inner.finish());
2235
+ } else if (value.bytesValue !== void 0) {
2236
+ lenField(w, 7, base64Bytes(value.bytesValue));
2237
+ }
2238
+ return w.finish();
2239
+ }
2240
+ function encodeKeyValue(kv) {
2241
+ const w = new Writer();
2242
+ stringField(w, 1, kv.key);
2243
+ lenField(w, 2, encodeAnyValue(kv.value));
2244
+ return w.finish();
2245
+ }
2246
+ function encodeSpanEvent(event) {
2247
+ const w = new Writer();
2248
+ w.tag(1, WIRE_FIXED64);
2249
+ w.fixed64(BigInt(event.timeUnixNano));
2250
+ stringField(w, 2, event.name);
2251
+ for (const attr of event.attributes) lenField(w, 3, encodeKeyValue(attr));
2252
+ return w.finish();
2253
+ }
2254
+ function encodeSpan(span) {
2255
+ const w = new Writer();
2256
+ const traceId = hexBytes(span.traceId, 16);
2257
+ if (traceId) lenField(w, 1, traceId);
2258
+ const spanId = hexBytes(span.spanId, 8);
2259
+ if (spanId) lenField(w, 2, spanId);
2260
+ stringField(w, 3, span.traceState);
2261
+ const parent = hexBytes(span.parentSpanId, 8);
2262
+ if (parent) lenField(w, 4, parent);
2263
+ stringField(w, 5, span.name);
2264
+ if (span.kind) {
2265
+ w.tag(6, WIRE_VARINT);
2266
+ w.varint(span.kind);
2267
+ }
2268
+ w.tag(7, WIRE_FIXED64);
2269
+ w.fixed64(BigInt(span.startTimeUnixNano));
2270
+ w.tag(8, WIRE_FIXED64);
2271
+ w.fixed64(BigInt(span.endTimeUnixNano));
2272
+ for (const attr of span.attributes) lenField(w, 9, encodeKeyValue(attr));
2273
+ for (const event of span.events ?? []) lenField(w, 11, encodeSpanEvent(event));
2274
+ const status = new Writer();
2275
+ stringField(status, 2, span.status.message);
2276
+ if (span.status.code) {
2277
+ status.tag(3, WIRE_VARINT);
2278
+ status.varint(span.status.code);
2279
+ }
2280
+ lenField(w, 15, status.finish());
2281
+ if (span.flags) {
2282
+ w.tag(16, WIRE_FIXED32);
2283
+ w.fixed32(span.flags);
2284
+ }
2285
+ return w.finish();
2286
+ }
2287
+ function encodeExportTraceServiceRequest(request) {
2288
+ const w = new Writer();
2289
+ for (const rs of request.resourceSpans) {
2290
+ const resourceSpans = new Writer();
2291
+ const resource = new Writer();
2292
+ for (const attr of rs.resource.attributes) lenField(resource, 1, encodeKeyValue(attr));
2293
+ lenField(resourceSpans, 1, resource.finish());
2294
+ for (const ss of rs.scopeSpans) {
2295
+ const scopeSpans = new Writer();
2296
+ const scope = new Writer();
2297
+ stringField(scope, 1, ss.scope.name);
2298
+ stringField(scope, 2, ss.scope.version);
2299
+ lenField(scopeSpans, 1, scope.finish());
2300
+ for (const span of ss.spans) lenField(scopeSpans, 2, encodeSpan(span));
2301
+ lenField(resourceSpans, 2, scopeSpans.finish());
2302
+ }
2303
+ stringField(resourceSpans, 3, rs.schemaUrl);
2304
+ lenField(w, 1, resourceSpans.finish());
2305
+ }
2306
+ return w.finish();
2307
+ }
2308
+ var Reader = class {
2309
+ constructor(bytes) {
2310
+ this.bytes = bytes;
2311
+ this.pos = 0;
2312
+ }
2313
+ get done() {
2314
+ return this.pos >= this.bytes.length;
2315
+ }
2316
+ varint() {
2317
+ let result = 0n;
2318
+ let shift = 0n;
2319
+ for (; ; ) {
2320
+ if (this.pos >= this.bytes.length) throw new Error("truncated varint");
2321
+ const byte = this.bytes[this.pos++];
2322
+ result |= BigInt(byte & 127) << shift;
2323
+ if ((byte & 128) === 0) return result;
2324
+ shift += 7n;
2325
+ if (shift > 70n) throw new Error("varint too long");
2326
+ }
2327
+ }
2328
+ slice(length) {
2329
+ if (this.pos + length > this.bytes.length) throw new Error("truncated field");
2330
+ const out = this.bytes.subarray(this.pos, this.pos + length);
2331
+ this.pos += length;
2332
+ return out;
2333
+ }
2334
+ skip(wire) {
2335
+ if (wire === WIRE_VARINT) this.varint();
2336
+ else if (wire === WIRE_FIXED64) this.slice(8);
2337
+ else if (wire === WIRE_FIXED32) this.slice(4);
2338
+ else if (wire === WIRE_LEN) this.slice(Number(this.varint()));
2339
+ else throw new Error(`unsupported wire type ${wire}`);
2340
+ }
2341
+ };
2342
+ function decodeExportTraceServiceResponse(bytes) {
2343
+ const top = new Reader(bytes);
2344
+ let result;
2345
+ while (!top.done) {
2346
+ const key = Number(top.varint());
2347
+ const field = key >>> 3;
2348
+ const wire = key & 7;
2349
+ if (field === 1 && wire === WIRE_LEN) {
2350
+ const inner = new Reader(top.slice(Number(top.varint())));
2351
+ let rejected = 0n;
2352
+ let message;
2353
+ while (!inner.done) {
2354
+ const innerKey = Number(inner.varint());
2355
+ const innerField = innerKey >>> 3;
2356
+ const innerWire = innerKey & 7;
2357
+ if (innerField === 1 && innerWire === WIRE_VARINT) rejected = BigInt.asIntN(64, inner.varint());
2358
+ else if (innerField === 2 && innerWire === WIRE_LEN) message = new TextDecoder().decode(inner.slice(Number(inner.varint())));
2359
+ else inner.skip(innerWire);
2360
+ }
2361
+ result = { rejectedSpans: Number(rejected), ...message ? { message } : {} };
2362
+ } else {
2363
+ top.skip(wire);
2364
+ }
2365
+ }
2366
+ return result;
2367
+ }
2368
+
2369
+ // src/utils/otlp/exporter.ts
2370
+ var gzipAsync = promisify(gzip);
2371
+ var DEFAULT_TIMEOUT_MS = 1e4;
2372
+ var RETRY_DEFAULTS = {
2373
+ maxAttempts: 3,
2374
+ initialDelayMs: 250,
2375
+ maxDelayMs: 4e3,
2376
+ maxElapsedMs: 25e3
2377
+ };
2378
+ var RETRYABLE_STATUS = /* @__PURE__ */ new Set([429, 502, 503, 504]);
2379
+ function retryPolicy(retry) {
2380
+ if (retry === false) return { ...RETRY_DEFAULTS, maxAttempts: 1 };
2381
+ const merged = { ...RETRY_DEFAULTS, ...retry ?? {} };
2382
+ return { ...merged, maxAttempts: Math.max(1, Math.floor(merged.maxAttempts)) };
2383
+ }
2384
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2385
+ function retryAfterMs(response) {
2386
+ let raw;
2387
+ try {
2388
+ raw = response?.headers?.get?.("retry-after");
2389
+ } catch {
2390
+ return void 0;
2391
+ }
2392
+ if (typeof raw !== "string" || raw.trim() === "") return void 0;
2393
+ const seconds = Number(raw);
2394
+ if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
2395
+ const date = Date.parse(raw);
2396
+ return Number.isNaN(date) ? void 0 : Math.max(0, date - Date.now());
2397
+ }
2398
+ async function attemptOnce(fetchFn, url, init, timeoutMs, protocol) {
2399
+ const controller = new AbortController();
2400
+ let timer;
2401
+ const timeout = new Promise((_, reject) => {
2402
+ timer = setTimeout(() => {
2403
+ controller.abort();
2404
+ reject(new Error(`timed out after ${timeoutMs} ms`));
2405
+ }, timeoutMs);
2406
+ });
2407
+ try {
2408
+ const pending = fetchFn(url, { ...init, signal: controller.signal });
2409
+ Promise.resolve(pending).catch(() => void 0);
2410
+ const response = await Promise.race([pending, timeout]);
2411
+ const status = typeof response?.status === "number" ? response.status : response?.ok ? 200 : 0;
2412
+ const ok = typeof response?.ok === "boolean" ? response.ok : status >= 200 && status < 300;
2413
+ if (ok) {
2414
+ const lateBody = timeout.catch(() => void 0);
2415
+ const partialSuccess = await Promise.race([readPartialSuccess(response, protocol), lateBody]);
2416
+ return { kind: "ok", status, ...partialSuccess ? { partialSuccess } : {} };
2417
+ }
2418
+ let body = "";
2419
+ try {
2420
+ if (typeof response?.text === "function") body = String(await response.text());
2421
+ } catch {
2422
+ }
2423
+ const statusText = typeof response?.statusText === "string" && response.statusText ? ` ${response.statusText}` : "";
2424
+ return {
2425
+ kind: "http",
2426
+ status,
2427
+ message: `HTTP ${status}${statusText}${body ? ` - ${body.slice(0, 200)}` : ""}`,
2428
+ retryable: RETRYABLE_STATUS.has(status),
2429
+ retryAfter: retryAfterMs(response)
2430
+ };
2431
+ } catch (err) {
2432
+ return { kind: "network", message: err instanceof Error ? err.message : String(err) };
2433
+ } finally {
2434
+ if (timer !== void 0) clearTimeout(timer);
2435
+ }
2436
+ }
2437
+ async function readPartialSuccess(response, protocol) {
2438
+ try {
2439
+ if (protocol === "http/protobuf") {
2440
+ if (typeof response?.arrayBuffer !== "function") return void 0;
2441
+ const bytes = new Uint8Array(await response.arrayBuffer());
2442
+ if (bytes.length === 0) return void 0;
2443
+ const decoded = decodeExportTraceServiceResponse(bytes);
2444
+ return decoded && (decoded.rejectedSpans > 0 || decoded.message) ? decoded : void 0;
2445
+ }
2446
+ if (typeof response?.text !== "function") return void 0;
2447
+ const text = String(await response.text());
2448
+ if (!text.trim()) return void 0;
2449
+ const partial = JSON.parse(text)?.partialSuccess;
2450
+ if (!partial || typeof partial !== "object") return void 0;
2451
+ const rejectedSpans = Number(partial.rejectedSpans ?? 0);
2452
+ const message = typeof partial.errorMessage === "string" && partial.errorMessage ? partial.errorMessage : void 0;
2453
+ if (!(rejectedSpans > 0) && !message) return void 0;
2454
+ return { rejectedSpans: Number.isFinite(rejectedSpans) ? rejectedSpans : 0, ...message ? { message } : {} };
2455
+ } catch {
2456
+ return void 0;
2457
+ }
2458
+ }
2459
+ function createOtlpExporter(options = {}) {
2460
+ const env = resolveOtlpEnv(currentEnv(), options);
2461
+ if (!env.endpoint && !env.disabled) {
2462
+ throw new Error(
2463
+ "[agent-sdk] OTLP export needs an `endpoint` (or OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_TRACES_ENDPOINT in the environment)."
2464
+ );
2465
+ }
2466
+ const semconv = options.semconv ?? "both";
2467
+ const protocol = env.protocol;
2468
+ const compression = env.compression;
2469
+ const timeoutMs = env.timeoutMs ?? DEFAULT_TIMEOUT_MS;
2470
+ const policy = retryPolicy(options.retry);
2471
+ const serviceName = options.serviceName ?? env.serviceName;
2472
+ const resourceAttributes = { ...env.resourceAttributes, ...options.resourceAttributes ?? {} };
2473
+ const endpoint = env.endpoint ?? "";
2474
+ const content = resolveContentOptions(options.content);
2475
+ return {
2476
+ name: options.name ?? "otlp",
2477
+ endpoint,
2478
+ semconv,
2479
+ protocol,
2480
+ wantsContent: content.enabled,
2481
+ contentOptions: content,
2482
+ async exportSession(file, run) {
2483
+ try {
2484
+ if (env.disabled) {
2485
+ return { ok: true, skipped: true, reason: "disabled by the environment (OTEL_SDK_DISABLED / OTEL_TRACES_EXPORTER)", attempts: 0, spans: 0, bytes: 0 };
2486
+ }
2487
+ const convertOptions = {
2488
+ semconv,
2489
+ serviceName,
2490
+ resourceAttributes,
2491
+ terminal: run.terminal,
2492
+ cancelled: run.cancelled,
2493
+ parent: run.parent,
2494
+ content
2495
+ };
2496
+ const request = sessionToOtlp(file, convertOptions);
2497
+ const spans = countSpans(request);
2498
+ if (spans === 0) return { ok: true, skipped: true, reason: "no spans to export", attempts: 0, spans: 0, bytes: 0 };
2499
+ const fetchFn = options.fetch ?? (typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0);
2500
+ if (!fetchFn) return { ok: false, attempts: 0, spans, bytes: 0, error: "OTLP export requires fetch to be available in this runtime." };
2501
+ let body = protocol === "http/protobuf" ? encodeExportTraceServiceRequest(request) : JSON.stringify(request);
2502
+ const headers = {
2503
+ "content-type": protocol === "http/protobuf" ? "application/x-protobuf" : "application/json"
2504
+ };
2505
+ if (compression === "gzip") {
2506
+ body = await gzipAsync(typeof body === "string" ? Buffer$1.from(body, "utf8") : body);
2507
+ headers["content-encoding"] = "gzip";
2508
+ }
2509
+ Object.assign(headers, env.headers);
2510
+ const bytes = typeof body === "string" ? Buffer$1.byteLength(body, "utf8") : body.length;
2511
+ const started = Date.now();
2512
+ let attempts = 0;
2513
+ let lastError = "export failed";
2514
+ let lastStatus;
2515
+ for (; ; ) {
2516
+ attempts += 1;
2517
+ const remaining = policy.maxElapsedMs - (Date.now() - started);
2518
+ const outcome = await attemptOnce(
2519
+ fetchFn,
2520
+ env.endpoint,
2521
+ { method: "POST", headers, body },
2522
+ Math.max(1, Math.min(timeoutMs, remaining)),
2523
+ protocol
2524
+ );
2525
+ if (outcome.kind === "ok") {
2526
+ return { ok: true, attempts, status: outcome.status, spans, bytes, ...outcome.partialSuccess ? { partialSuccess: outcome.partialSuccess } : {} };
2527
+ }
2528
+ lastError = outcome.message;
2529
+ lastStatus = outcome.kind === "http" ? outcome.status : void 0;
2530
+ const retryable = outcome.kind === "network" || outcome.retryable;
2531
+ if (!retryable || attempts >= policy.maxAttempts) break;
2532
+ const ceiling = Math.min(policy.maxDelayMs, policy.initialDelayMs * 2 ** (attempts - 1));
2533
+ const wait = outcome.kind === "http" && outcome.retryAfter !== void 0 ? Math.min(outcome.retryAfter, policy.maxDelayMs) : Math.random() * ceiling;
2534
+ if (Date.now() - started + wait >= policy.maxElapsedMs) break;
2535
+ await sleep(wait);
2536
+ }
2537
+ return { ok: false, attempts, ...lastStatus !== void 0 ? { status: lastStatus } : {}, spans, bytes, error: lastError };
2538
+ } catch (err) {
2539
+ return { ok: false, attempts: 0, spans: 0, bytes: 0, error: err instanceof Error ? err.message : String(err) };
2540
+ }
2541
+ }
2542
+ };
2543
+ }
2544
+
2545
+ // src/utils/otlp/context.ts
2546
+ var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
2547
+ var ALL_ZERO_TRACE = /^0{32}$/;
2548
+ var ALL_ZERO_SPAN = /^0{16}$/;
2549
+ var MAX_TRACESTATE = 512;
2550
+ function parseTraceparent(header) {
2551
+ if (typeof header !== "string") return void 0;
2552
+ const match = TRACEPARENT.exec(header.trim());
2553
+ if (!match) return void 0;
2554
+ const [, version, traceId, spanId, flagsHex, rest] = match;
2555
+ if (version === "ff") return void 0;
2556
+ if (version === "00" && rest) return void 0;
2557
+ if (ALL_ZERO_TRACE.test(traceId) || ALL_ZERO_SPAN.test(spanId)) return void 0;
2558
+ const flags = parseInt(flagsHex, 16);
2559
+ return { traceId, spanId, flags, sampled: (flags & 1) === 1 };
2560
+ }
2561
+ function formatTraceparent(parts) {
2562
+ const flags = typeof parts.flags === "number" ? parts.flags & 255 : parts.sampled === false ? 0 : 1;
2563
+ return `00-${parts.traceId}-${parts.spanId}-${flags.toString(16).padStart(2, "0")}`;
2564
+ }
2565
+ function traceparentOf(ctx) {
2566
+ if (!ctx?.traceId || !ctx.traceSpanId) return void 0;
2567
+ return formatTraceparent({ traceId: ctx.traceId, spanId: ctx.traceSpanId, flags: ctx.traceFlags ?? 1 });
2568
+ }
2569
+ function cleanTraceState(value) {
2570
+ if (typeof value !== "string") return void 0;
2571
+ const trimmed = value.trim();
2572
+ if (!trimmed || trimmed.length > MAX_TRACESTATE || !/^[\x20-\x7e]+$/.test(trimmed)) return void 0;
2573
+ return trimmed;
2574
+ }
2575
+ function resolveTraceParent(input) {
2576
+ if (input === void 0 || input === null) return void 0;
2577
+ const header = typeof input === "string" ? input : input?.traceparent;
2578
+ const parsed = parseTraceparent(header);
2579
+ if (!parsed) {
2580
+ warnOnce("[agent-sdk] Ignoring an invalid W3C traceparent; the trace starts a new root.");
2581
+ return void 0;
2582
+ }
2583
+ const traceState = typeof input === "object" ? cleanTraceState(input.tracestate) : void 0;
2584
+ return {
2585
+ traceId: parsed.traceId,
2586
+ spanId: parsed.spanId,
2587
+ flags: parsed.flags,
2588
+ sampled: parsed.sampled,
2589
+ remote: true,
2590
+ ...traceState ? { traceState } : {}
2591
+ };
2592
+ }
2593
+ function persistedParentOf(parent) {
2594
+ if (!parent) return void 0;
2595
+ return { spanId: parent.spanId, flags: parent.flags, ...parent.traceState ? { traceState: parent.traceState } : {} };
2596
+ }
2597
+ function readPersistedParent(value) {
2598
+ if (!value || typeof value !== "object") return void 0;
2599
+ const raw = value;
2600
+ if (typeof raw.spanId !== "string" || !/^[0-9a-f]{16}$/.test(raw.spanId) || ALL_ZERO_SPAN.test(raw.spanId)) return void 0;
2601
+ const flags = Number(raw.flags);
2602
+ if (!Number.isInteger(flags) || flags < 0 || flags > 255) return void 0;
2603
+ const traceState = cleanTraceState(raw.traceState);
2604
+ return { spanId: raw.spanId, flags, ...traceState ? { traceState } : {} };
2605
+ }
2606
+ function restoreParent(persisted, traceId) {
2607
+ return {
2608
+ traceId,
2609
+ spanId: persisted.spanId,
2610
+ flags: persisted.flags,
2611
+ sampled: (persisted.flags & 1) === 1,
2612
+ remote: true,
2613
+ ...persisted.traceState ? { traceState: persisted.traceState } : {}
2614
+ };
2615
+ }
2616
+
2617
+ // src/utils/tracing.ts
1227
2618
  var DEFAULT_COGNIPEER_URL = "https://console.cognipeer.com/api/client/v1/tracing/sessions";
1228
2619
  function fileSink(path2) {
1229
2620
  return { type: "file", path: path2 };
@@ -1249,8 +2640,9 @@ function cognipeerSink(first, second) {
1249
2640
  function httpSink(url, headers) {
1250
2641
  return { type: "http", url, headers };
1251
2642
  }
1252
- function otlpSink(endpoint, headers) {
1253
- return { type: "otlp", endpoint, headers };
2643
+ function otlpSink(first, headers, options) {
2644
+ if (first !== null && typeof first === "object") return { type: "otlp", ...first };
2645
+ return { type: "otlp", endpoint: first, headers, ...options ?? {} };
1254
2646
  }
1255
2647
  function resolveLogsBaseDir(customPath, ensureDirectory = true) {
1256
2648
  const root = process.cwd();
@@ -1323,23 +2715,23 @@ function extractMetadata(model, paths) {
1323
2715
  if (!model) return void 0;
1324
2716
  for (const path2 of paths) {
1325
2717
  const value = getNestedValue2(model, path2);
1326
- const str = coerceToString(value);
1327
- if (str) return str;
2718
+ const str2 = coerceToString(value);
2719
+ if (str2) return str2;
1328
2720
  }
1329
2721
  const maybeLc = model?._lc;
1330
2722
  if (maybeLc) {
1331
2723
  for (const path2 of paths) {
1332
2724
  const value = getNestedValue2(maybeLc, path2);
1333
- const str = coerceToString(value);
1334
- if (str) return str;
2725
+ const str2 = coerceToString(value);
2726
+ if (str2) return str2;
1335
2727
  }
1336
2728
  }
1337
2729
  const maybeClient = model?.client || model?.api || model?.service;
1338
2730
  if (maybeClient) {
1339
2731
  for (const path2 of paths) {
1340
2732
  const value = getNestedValue2(maybeClient, path2);
1341
- const str = coerceToString(value);
1342
- if (str) return str;
2733
+ const str2 = coerceToString(value);
2734
+ if (str2) return str2;
1343
2735
  }
1344
2736
  }
1345
2737
  const constructorName = model?.constructor?.name;
@@ -1370,8 +2762,8 @@ function inferModelFromMessages(messageList) {
1370
2762
  if (!message) continue;
1371
2763
  for (const path2 of messagePaths) {
1372
2764
  const value = getNestedValue2(message, path2);
1373
- const str = coerceToString(value);
1374
- if (str) return str;
2765
+ const str2 = coerceToString(value);
2766
+ if (str2) return str2;
1375
2767
  }
1376
2768
  }
1377
2769
  return void 0;
@@ -1389,8 +2781,8 @@ function inferProviderFromMessages(messageList) {
1389
2781
  if (!message) continue;
1390
2782
  for (const path2 of messagePaths) {
1391
2783
  const value = getNestedValue2(message, path2);
1392
- const str = coerceToString(value);
1393
- if (str) return str;
2784
+ const str2 = coerceToString(value);
2785
+ if (str2) return str2;
1394
2786
  }
1395
2787
  }
1396
2788
  return void 0;
@@ -1452,12 +2844,18 @@ function resolveSink(sink) {
1452
2844
  return headers ? { type: "http", url, headers } : { type: "http", url };
1453
2845
  }
1454
2846
  case "otlp": {
1455
- const endpoint = typeof candidate.endpoint === "string" ? candidate.endpoint.trim() : "";
1456
- if (!endpoint) {
2847
+ const given = candidate.endpoint;
2848
+ if (given !== void 0 && (typeof given !== "string" || given.trim().length === 0)) {
2849
+ throw new Error("otlp sink requires a non-empty endpoint");
2850
+ }
2851
+ let exporter;
2852
+ try {
2853
+ exporter = createOtlpExporter({ ...candidate, endpoint: given?.trim() });
2854
+ } catch {
1457
2855
  throw new Error("otlp sink requires a non-empty endpoint");
1458
2856
  }
1459
2857
  const headers = candidate.headers ? { ...candidate.headers } : void 0;
1460
- return headers ? { type: "otlp", endpoint, headers } : { type: "otlp", endpoint };
2858
+ return headers ? { type: "otlp", endpoint: exporter.endpoint, headers, exporter } : { type: "otlp", endpoint: exporter.endpoint, exporter };
1461
2859
  }
1462
2860
  default: {
1463
2861
  if (typeof console !== "undefined" && typeof console.warn === "function") {
@@ -1467,6 +2865,17 @@ function resolveSink(sink) {
1467
2865
  }
1468
2866
  }
1469
2867
  }
2868
+ function withoutUserinfo(endpoint) {
2869
+ try {
2870
+ const url = new URL(endpoint);
2871
+ if (!url.username && !url.password) return endpoint;
2872
+ url.username = "";
2873
+ url.password = "";
2874
+ return url.toString();
2875
+ } catch {
2876
+ return endpoint;
2877
+ }
2878
+ }
1470
2879
  function snapshotSink(runtime) {
1471
2880
  const sink = runtime.resolvedConfig.sink;
1472
2881
  switch (sink.type) {
@@ -1479,7 +2888,7 @@ function snapshotSink(runtime) {
1479
2888
  case "http":
1480
2889
  return { type: "http", url: sink.url };
1481
2890
  case "otlp":
1482
- return { type: "otlp", endpoint: sink.endpoint };
2891
+ return { type: "otlp", endpoint: withoutUserinfo(sink.endpoint) };
1483
2892
  default:
1484
2893
  return { type: "custom" };
1485
2894
  }
@@ -1497,11 +2906,11 @@ var TRACE_HTTP_RETRYABLE_STATUS = /* @__PURE__ */ new Set([404, 408, 425, 429, 5
1497
2906
  var TRACE_HTTP_RETRY_BASE_MS = 250;
1498
2907
  var TRACE_HTTP_RETRY_MAX_MS = 4e3;
1499
2908
  var RetryableHttpError = class extends Error {
1500
- constructor(status, message, retryAfterMs) {
2909
+ constructor(status, message, retryAfterMs2) {
1501
2910
  super(message);
1502
2911
  this.name = "RetryableHttpError";
1503
2912
  this.status = status;
1504
- this.retryAfterMs = retryAfterMs;
2913
+ this.retryAfterMs = retryAfterMs2;
1505
2914
  }
1506
2915
  };
1507
2916
  function traceSleep(ms) {
@@ -1594,206 +3003,23 @@ async function postStreamingSessionEnd(baseUrl, headers, payload) {
1594
3003
  const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/end`;
1595
3004
  await postJsonReliable(url, headers, payload, { retry: true });
1596
3005
  }
1597
- function isoToUnixNano(iso) {
1598
- const ms = new Date(iso).getTime();
1599
- return `${ms}000000`;
1600
- }
1601
- function toOtlpStatusCode(status) {
1602
- if (status === "error") return 2;
1603
- if (status === "success" || status === "completed") return 1;
1604
- return 0;
1605
- }
1606
- function toOtlpSpanKind(type) {
1607
- switch (type) {
1608
- case "ai_call":
1609
- case "summarization":
1610
- return 3;
1611
- // CLIENT — outgoing LLM request (the summarizer is one too)
1612
- case "tool_call":
1613
- return 1;
1614
- // INTERNAL
1615
- case "agent_iteration":
1616
- return 1;
1617
- // INTERNAL
1618
- default:
1619
- return 1;
1620
- }
1621
- }
1622
- function stringAttr(key, val) {
1623
- return val != null ? { key, value: { stringValue: val } } : null;
1624
- }
1625
- function intAttr(key, val) {
1626
- return val != null && !Number.isNaN(val) ? { key, value: { intValue: String(val) } } : null;
1627
- }
1628
- function doubleAttr(key, val) {
1629
- return val != null && !Number.isNaN(val) ? { key, value: { doubleValue: val } } : null;
1630
- }
1631
- function eventToOtlpSpan(event) {
1632
- const startNano = isoToUnixNano(event.timestamp);
1633
- const endNano = event.durationMs != null ? `${new Date(new Date(event.timestamp).getTime() + event.durationMs).getTime()}000000` : startNano;
1634
- const attrs = [
1635
- stringAttr("cognipeer.event.type", event.type),
1636
- stringAttr("cognipeer.event.label", event.label),
1637
- intAttr("cognipeer.event.sequence", event.sequence),
1638
- stringAttr("cognipeer.actor.scope", event.actor?.scope),
1639
- stringAttr("cognipeer.actor.name", event.actor?.name),
1640
- stringAttr("cognipeer.actor.role", event.actor?.role),
1641
- stringAttr("cognipeer.model", event.model),
1642
- intAttr("cognipeer.tokens.reasoning", event.reasoningTokens),
1643
- stringAttr("cognipeer.finish_reason", event.finishReason),
1644
- stringAttr("cognipeer.provider", event.provider),
1645
- stringAttr("cognipeer.tool.details", event.toolDetails ? JSON.stringify(event.toolDetails) : void 0),
1646
- intAttr("cognipeer.tokens.input", event.inputTokens),
1647
- intAttr("cognipeer.tokens.output", event.outputTokens),
1648
- intAttr("cognipeer.tokens.total", event.totalTokens),
1649
- intAttr("cognipeer.tokens.cached_input", event.cachedInputTokens),
1650
- intAttr("cognipeer.bytes.request", event.requestBytes),
1651
- intAttr("cognipeer.bytes.response", event.responseBytes),
1652
- stringAttr("cognipeer.tool.execution_id", event.toolExecutionId),
1653
- stringAttr("cognipeer.retry_of", event.retryOf),
1654
- stringAttr("cognipeer.event.id", event.id)
1655
- ].filter(Boolean);
1656
- if (event.data?.sections && event.data.sections.length > 0) {
1657
- try {
1658
- attrs.push({ key: "cognipeer.sections", value: { stringValue: JSON.stringify(event.data.sections) } });
1659
- } catch {
1660
- }
1661
- }
1662
- const span = {
1663
- traceId: event.traceId,
1664
- spanId: event.spanId,
1665
- parentSpanId: event.parentSpanId || "",
1666
- name: event.label || event.type,
1667
- kind: toOtlpSpanKind(event.type),
1668
- startTimeUnixNano: startNano,
1669
- endTimeUnixNano: endNano,
1670
- attributes: attrs,
1671
- status: {
1672
- code: toOtlpStatusCode(event.status),
1673
- ...event.status === "error" && event.error?.message ? { message: event.error.message } : {}
1674
- }
1675
- };
1676
- if (event.error) {
1677
- span.events = [{
1678
- timeUnixNano: startNano,
1679
- name: "exception",
1680
- attributes: [
1681
- { key: "exception.message", value: { stringValue: event.error.message } },
1682
- ...event.error.stack ? [{ key: "exception.stacktrace", value: { stringValue: event.error.stack } }] : []
1683
- ]
1684
- }];
1685
- }
1686
- return span;
1687
- }
1688
- function traceSessionToOtlp(session) {
1689
- const traceId = session.traceId || generateTraceId();
1690
- const rootSpanId = session.rootSpanId || generateSpanId();
1691
- const startNano = isoToUnixNano(session.startedAt);
1692
- const endNano = session.endedAt ? isoToUnixNano(session.endedAt) : startNano;
1693
- const resourceAttrs = [
1694
- { key: "service.name", value: { stringValue: session.agent?.name || "cognipeer-agent" } },
1695
- stringAttr("service.version", session.agent?.version),
1696
- stringAttr("cognipeer.session.id", session.sessionId),
1697
- stringAttr("cognipeer.thread.id", session.threadId),
1698
- stringAttr("cognipeer.agent.model", session.agent?.model),
1699
- stringAttr("cognipeer.agent.provider", session.agent?.provider),
1700
- ...Object.entries(session.metadata || {}).map(([key, value]) => stringAttr(`cognipeer.metadata.${key}`, value))
1701
- ].filter(Boolean);
1702
- const rootAttrs = [
1703
- stringAttr("cognipeer.session.status", session.status),
1704
- doubleAttr("cognipeer.session.duration_ms", session.durationMs),
1705
- intAttr("cognipeer.session.total_input_tokens", session.summary.totalInputTokens),
1706
- intAttr("cognipeer.session.total_output_tokens", session.summary.totalOutputTokens),
1707
- intAttr("cognipeer.session.total_cached_input_tokens", session.summary.totalCachedInputTokens),
1708
- intAttr("cognipeer.session.total_bytes_in", session.summary.totalBytesIn),
1709
- intAttr("cognipeer.session.total_bytes_out", session.summary.totalBytesOut),
1710
- intAttr("cognipeer.session.event_count", session.events.length)
1711
- ].filter(Boolean);
1712
- if (session.summary.eventCounts) {
1713
- for (const [key, count] of Object.entries(session.summary.eventCounts)) {
1714
- rootAttrs.push({ key: `cognipeer.session.event_count.${key}`, value: { intValue: String(count) } });
1715
- }
1716
- }
1717
- const rootSpan = {
1718
- traceId,
1719
- spanId: rootSpanId,
1720
- parentSpanId: "",
1721
- name: `agent_session: ${session.agent?.name || "agent"}`,
1722
- kind: 1,
1723
- // INTERNAL
1724
- startTimeUnixNano: startNano,
1725
- endTimeUnixNano: endNano,
1726
- attributes: rootAttrs,
1727
- status: {
1728
- code: toOtlpStatusCode(session.status),
1729
- ...session.status === "error" && session.errors.length > 0 ? { message: session.errors.map((e) => e.message).join("; ") } : {}
1730
- }
1731
- };
1732
- if (session.errors.length > 0) {
1733
- rootSpan.events = session.errors.map((err) => ({
1734
- timeUnixNano: err.timestamp ? isoToUnixNano(err.timestamp) : startNano,
1735
- name: "exception",
1736
- attributes: [
1737
- { key: "exception.message", value: { stringValue: err.message } },
1738
- ...err.stack ? [{ key: "exception.stacktrace", value: { stringValue: err.stack } }] : [],
1739
- ...err.type ? [{ key: "exception.type", value: { stringValue: err.type } }] : []
1740
- ]
1741
- }));
1742
- }
1743
- const childSpans = session.events.map((event) => {
1744
- const span = eventToOtlpSpan({
1745
- ...event,
1746
- traceId: event.traceId || traceId,
1747
- spanId: event.spanId || generateSpanId(),
1748
- parentSpanId: event.parentSpanId || rootSpanId
1749
- });
1750
- return span;
3006
+ function traceSessionToOtlp(session, options = {}) {
3007
+ return sessionToOtlp(session, {
3008
+ semconv: "both",
3009
+ terminal: session.status !== "paused" && session.status !== "in_progress",
3010
+ ...options,
3011
+ content: resolveContentOptions(options.content)
1751
3012
  });
1752
- return {
1753
- resourceSpans: [{
1754
- resource: { attributes: resourceAttrs },
1755
- scopeSpans: [{
1756
- scope: {
1757
- name: "cognipeer-agent-sdk",
1758
- version: "1.0.0"
1759
- },
1760
- spans: [rootSpan, ...childSpans]
1761
- }]
1762
- }]
1763
- };
1764
3013
  }
1765
- async function postOtlpTraces(endpoint, headers, payload) {
1766
- const fetchFn = typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0;
1767
- if (!fetchFn) {
1768
- throw new Error("OTLP sink requires fetch to be available in this runtime.");
1769
- }
1770
- const finalHeaders = {
1771
- "content-type": "application/json",
1772
- ...headers || {}
3014
+ function traceErrorOf(err) {
3015
+ const e = err;
3016
+ const message = typeof e?.message === "string" && e.message ? e.message : String(err);
3017
+ const type = err instanceof Error && typeof err.name === "string" && err.name ? err.name : void 0;
3018
+ return {
3019
+ message,
3020
+ ...typeof e?.stack === "string" ? { stack: e.stack } : {},
3021
+ ...type ? { type } : {}
1773
3022
  };
1774
- try {
1775
- const response = await fetchFn(endpoint, {
1776
- method: "POST",
1777
- headers: finalHeaders,
1778
- body: JSON.stringify(payload)
1779
- });
1780
- if (!response.ok) {
1781
- let responseText = "";
1782
- try {
1783
- responseText = await response.text();
1784
- } catch {
1785
- }
1786
- const statusLine = `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
1787
- const bodyPreview = responseText ? ` - ${responseText.slice(0, 200)}` : "";
1788
- throw new Error(`${statusLine}${bodyPreview}`);
1789
- }
1790
- } catch (err) {
1791
- const errMsg = err instanceof Error ? err.message : String(err);
1792
- if (typeof console !== "undefined" && typeof console.error === "function") {
1793
- console.error("[Tracing] OTLP export failed:", errMsg);
1794
- }
1795
- throw err;
1796
- }
1797
3023
  }
1798
3024
  function createEmptySummary() {
1799
3025
  return {
@@ -1813,10 +3039,16 @@ function generateEventId(sequence) {
1813
3039
  return `evt_${String(sequence).padStart(4, "0")}_${nanoid(4)}`;
1814
3040
  }
1815
3041
  function generateTraceId() {
1816
- return crypto.randomBytes(16).toString("hex");
3042
+ for (; ; ) {
3043
+ const id = crypto.randomBytes(16).toString("hex");
3044
+ if (/[1-9a-f]/.test(id)) return id;
3045
+ }
1817
3046
  }
1818
3047
  function generateSpanId() {
1819
- return crypto.randomBytes(8).toString("hex");
3048
+ for (; ; ) {
3049
+ const id = crypto.randomBytes(8).toString("hex");
3050
+ if (/[1-9a-f]/.test(id)) return id;
3051
+ }
1820
3052
  }
1821
3053
  function defaultEventLabel(type) {
1822
3054
  switch (type) {
@@ -2093,9 +3325,64 @@ function readTraceContinuation(value) {
2093
3325
  nextSequence,
2094
3326
  part,
2095
3327
  summary,
2096
- errors: Array.isArray(raw.errors) ? raw.errors : []
3328
+ errors: Array.isArray(raw.errors) ? raw.errors : [],
3329
+ ...(() => {
3330
+ const parent = readPersistedParent(raw.parent);
3331
+ return parent ? { parent } : {};
3332
+ })(),
3333
+ ...(() => {
3334
+ const pendingSpans = readPendingSpans(raw.pendingSpans);
3335
+ return pendingSpans.length > 0 ? { pendingSpans } : {};
3336
+ })()
3337
+ };
3338
+ }
3339
+ var MAX_CARRIED_SPANS = 64;
3340
+ var isSubagentSpanRecord = (event) => event.type === "span" && event.actor?.role === "subagent";
3341
+ function carriedSpanOf(record) {
3342
+ const identity2 = (record.data?.sections ?? []).filter(
3343
+ (section) => section.kind === "metadata" && section.identity === true
3344
+ );
3345
+ return {
3346
+ sessionId: record.sessionId,
3347
+ traceId: record.traceId,
3348
+ spanId: record.spanId,
3349
+ parentSpanId: record.parentSpanId,
3350
+ id: record.id,
3351
+ type: record.type,
3352
+ label: record.label,
3353
+ sequence: record.sequence,
3354
+ timestamp: record.timestamp,
3355
+ actor: record.actor,
3356
+ status: record.status,
3357
+ durationMs: record.durationMs,
3358
+ ...identity2.length > 0 ? { data: { sections: identity2 } } : {}
2097
3359
  };
2098
3360
  }
3361
+ function readPendingSpans(value) {
3362
+ if (!Array.isArray(value)) return [];
3363
+ const out = [];
3364
+ for (const item of value.slice(0, MAX_CARRIED_SPANS)) {
3365
+ if (!item || typeof item !== "object") continue;
3366
+ const raw = item;
3367
+ if (typeof raw.spanId !== "string" || raw.spanId.length === 0) continue;
3368
+ if (raw.status !== "pending" || !isSubagentSpanRecord(raw)) continue;
3369
+ if (typeof raw.sequence !== "number" || !Number.isInteger(raw.sequence) || raw.sequence < 1) continue;
3370
+ if (typeof raw.timestamp !== "string" || Number.isNaN(Date.parse(raw.timestamp))) continue;
3371
+ if (typeof raw.label !== "string" || typeof raw.id !== "string" || typeof raw.sessionId !== "string") continue;
3372
+ if (raw.parentSpanId !== void 0 && typeof raw.parentSpanId !== "string") continue;
3373
+ if (raw.durationMs !== void 0 && (typeof raw.durationMs !== "number" || !Number.isFinite(raw.durationMs))) continue;
3374
+ out.push(carriedSpanOf(raw));
3375
+ }
3376
+ return out;
3377
+ }
3378
+ function pendingSpansOf(session) {
3379
+ const candidates = [
3380
+ ...session.carriedSpans ?? [],
3381
+ ...session.events.filter(isSubagentSpanRecord)
3382
+ ];
3383
+ if (candidates.length === 0) return [];
3384
+ return foldSupersededSpans(candidates).filter((event) => event.status === "pending").slice(-MAX_CARRIED_SPANS).map(carriedSpanOf);
3385
+ }
2099
3386
  function traceContinuationOf(session) {
2100
3387
  return {
2101
3388
  v: 1,
@@ -2109,15 +3396,32 @@ function traceContinuationOf(session) {
2109
3396
  summary: JSON.parse(JSON.stringify(session.summary)),
2110
3397
  // Sink failures belong to the part that hit them; carrying them on would
2111
3398
  // mark every later part `partial`.
2112
- errors: session.errors.filter((error) => error.type !== "sink")
3399
+ errors: session.errors.filter((error) => error.type !== "sink"),
3400
+ // Where the root hangs, so the leg that ends the run exports it under the same remote parent.
3401
+ ...session.parent ? { parent: persistedParentOf(session.parent) } : {},
3402
+ ...(() => {
3403
+ const pendingSpans = pendingSpansOf(session);
3404
+ return pendingSpans.length > 0 ? { pendingSpans } : {};
3405
+ })()
2113
3406
  };
2114
3407
  }
2115
- function createTraceSession(opts, continuation) {
3408
+ function createTraceSession(opts, continuation, extras) {
2116
3409
  const cfg = withDefaults(opts.tracing);
2117
3410
  if (!cfg.enabled) return void 0;
3411
+ let parent;
3412
+ if (continuation) {
3413
+ if (continuation.parent && continuation.traceId) parent = restoreParent(continuation.parent, continuation.traceId);
3414
+ } else {
3415
+ parent = resolveTraceParent(extras?.traceParent ?? opts.tracing?.parent);
3416
+ }
3417
+ const exporters = [...extras?.exporters ?? []];
3418
+ const contentExporters = [
3419
+ ...cfg.sink.type === "otlp" ? [cfg.sink.exporter] : [],
3420
+ ...exporters
3421
+ ].filter((exporter) => exporter.wantsContent);
2118
3422
  const providedSessionId = opts.tracing?.sessionId?.trim();
2119
3423
  const sessionId = continuation?.sessionId || providedSessionId || generateSessionId();
2120
- const traceId = continuation?.traceId || generateTraceId();
3424
+ const traceId = continuation?.traceId || parent?.traceId || generateTraceId();
2121
3425
  const rootSpanId = continuation?.rootSpanId || generateSpanId();
2122
3426
  const runtime = {
2123
3427
  sessionId,
@@ -2136,7 +3440,20 @@ function createTraceSession(opts, continuation) {
2136
3440
  // again would reset a streaming receiver's copy.
2137
3441
  sessionStarted: Boolean(continuation),
2138
3442
  sequenceOffset: continuation ? continuation.nextSequence - 1 : 0,
2139
- part: continuation ? continuation.part + 1 : 1
3443
+ part: continuation ? continuation.part + 1 : 1,
3444
+ ...continuation?.pendingSpans?.length ? { carriedSpans: continuation.pendingSpans } : {},
3445
+ ...exporters.length ? { exporters } : {},
3446
+ exportReports: [],
3447
+ ...parent ? { parent } : {},
3448
+ ...contentExporters.length > 0 ? {
3449
+ captureContent: true,
3450
+ captureLimits: {
3451
+ // Headroom over the export cap: a redact hook runs before the cap and must see a
3452
+ // secret whole, even one that straddles the point where the export cuts.
3453
+ maxStringChars: 4 * Math.max(...contentExporters.map((exporter) => exporter.contentOptions?.maxStringChars ?? 4096)),
3454
+ maxMessages: Math.max(...contentExporters.map((exporter) => exporter.contentOptions?.maxMessages ?? 32))
3455
+ }
3456
+ } : {}
2140
3457
  };
2141
3458
  if (cfg.sink.type === "file") {
2142
3459
  const baseDir = cfg.sink.baseDir;
@@ -2252,8 +3569,15 @@ function recordTraceEvent(session, event) {
2252
3569
  }
2253
3570
  }
2254
3571
  }
3572
+ if (!session.resolvedConfig.logData && event.sections?.length) {
3573
+ const identity2 = event.sections.filter((section) => section.kind === "metadata" && section.identity === true);
3574
+ if (identity2.length > 0) sections = ensureUniqueSections(id, identity2);
3575
+ }
2255
3576
  if (event.alwaysSections?.length) {
2256
- sections = ensureUniqueSections(id, [...event.alwaysSections, ...sections ?? []]);
3577
+ const identity2 = event.alwaysSections.map(
3578
+ (section) => section.kind === "metadata" ? { ...section, identity: true } : section
3579
+ );
3580
+ sections = ensureUniqueSections(id, [...identity2, ...sections ?? []]);
2257
3581
  }
2258
3582
  const resolvedModel = event.model ?? inferModelFromMessages(event.messageList);
2259
3583
  const resolvedProvider = event.provider ?? inferProviderFromMessages(event.messageList);
@@ -2289,6 +3613,16 @@ function recordTraceEvent(session, event) {
2289
3613
  // different facts, and a zero would erase the difference.
2290
3614
  ...reasoningTokens !== void 0 && !Number.isNaN(reasoningTokens) ? { reasoningTokens } : {},
2291
3615
  ...event.finishReason ? { finishReason: event.finishReason } : {},
3616
+ // Provider facts: absent when the provider did not say, never zero or empty.
3617
+ ...event.responseId ? { responseId: event.responseId } : {},
3618
+ ...event.responseModel ? { responseModel: event.responseModel } : {},
3619
+ ...event.rawFinishReason ? { rawFinishReason: event.rawFinishReason } : {},
3620
+ ...typeof event.cacheWriteTokens === "number" && event.cacheWriteTokens > 0 ? { cacheWriteTokens: event.cacheWriteTokens } : {},
3621
+ ...event.usageBasis && (event.usageBasis.inputExcludesCache || event.usageBasis.outputExcludesReasoning) ? { usageBasis: { ...event.usageBasis } } : {},
3622
+ ...event.streaming ? { streaming: true } : {},
3623
+ ...event.outputType ? { outputType: event.outputType } : {},
3624
+ ...event.toolCallId ? { toolCallId: event.toolCallId } : {},
3625
+ ...event.skipReason ? { skipReason: event.skipReason } : {},
2292
3626
  requestBytes,
2293
3627
  responseBytes,
2294
3628
  model: resolvedModel,
@@ -2310,6 +3644,15 @@ function recordTraceEvent(session, event) {
2310
3644
  timestamp: timestampIso
2311
3645
  });
2312
3646
  }
3647
+ if (session.captureContent && event.capture) {
3648
+ try {
3649
+ attachCapturedContent(
3650
+ record,
3651
+ buildCapturedContent(event.capture, session.captureLimits ?? { maxStringChars: 4096, maxMessages: 32 })
3652
+ );
3653
+ } catch {
3654
+ }
3655
+ }
2313
3656
  session.events.push(record);
2314
3657
  const sink = session.resolvedConfig.sink;
2315
3658
  if (sink.type === "custom" && typeof sink.onEvent === "function") {
@@ -2404,6 +3747,19 @@ function recordSubagentSpan(session, span) {
2404
3747
  sections
2405
3748
  });
2406
3749
  }
3750
+ function foldSupersededSpans(events) {
3751
+ const rank = (event, index) => typeof event.sequence === "number" && Number.isFinite(event.sequence) ? event.sequence : index;
3752
+ const winner = /* @__PURE__ */ new Map();
3753
+ for (let i = 0; i < events.length; i++) {
3754
+ const id = events[i].spanId;
3755
+ if (!id) continue;
3756
+ const current = winner.get(id);
3757
+ if (current === void 0 || rank(events[i], i) >= rank(events[current], current)) winner.set(id, i);
3758
+ }
3759
+ return events.filter(
3760
+ (event, i) => !(event.spanId && (event.status === "pending" || event.status === "running") && winner.get(event.spanId) !== i)
3761
+ );
3762
+ }
2407
3763
  function recordOrDeferTraceEvent(ctx, event, options) {
2408
3764
  const session = ctx?.__traceSession;
2409
3765
  if (isTraceSessionOpen(session)) {
@@ -2414,7 +3770,8 @@ function recordOrDeferTraceEvent(ctx, event, options) {
2414
3770
  const held = Array.isArray(ctx?.[DEFERRED_TRACE_EVENTS_KEY]) ? ctx[DEFERRED_TRACE_EVENTS_KEY] : [];
2415
3771
  return {
2416
3772
  ...ctx || {},
2417
- [DEFERRED_TRACE_EVENTS_KEY]: [...held, { ...event, timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString() }]
3773
+ // `capture` (content for exporters) is never parked on ctx, which callers persist.
3774
+ [DEFERRED_TRACE_EVENTS_KEY]: [...held, { ...event, capture: void 0, timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString() }]
2418
3775
  };
2419
3776
  }
2420
3777
  function replayDeferredTraceEvents(session, deferred) {
@@ -2448,6 +3805,7 @@ async function finalizeTraceSession(session, params = {}) {
2448
3805
  message: params.error.message || "Unknown error",
2449
3806
  stack: params.error.stack,
2450
3807
  type: "session",
3808
+ ...params.error.name ? { errorName: params.error.name } : {},
2451
3809
  timestamp: endedAtIso
2452
3810
  });
2453
3811
  }
@@ -2471,24 +3829,62 @@ async function finalizeTraceSession(session, params = {}) {
2471
3829
  ...(session.part ?? 1) > 1 ? { continuation: { part: session.part, firstSequence: (session.sequenceOffset ?? 0) + 1 } } : {}
2472
3830
  });
2473
3831
  const payloadForSink = buildPayload(initialStatus);
3832
+ const carried = session.carriedSpans ?? [];
3833
+ const exportPayload = carried.length > 0 ? { ...payloadForSink, events: [...carried, ...payloadForSink.events] } : payloadForSink;
2474
3834
  let sinkFailed = false;
2475
3835
  const sink = session.resolvedConfig.sink;
2476
3836
  const isStreamingMode = session.resolvedConfig.mode === "streaming";
2477
- if (sink.type === "otlp") {
2478
- try {
2479
- const otlpPayload = traceSessionToOtlp(payloadForSink);
2480
- await postOtlpTraces(sink.endpoint, sink.headers, otlpPayload);
2481
- } catch (err) {
2482
- sinkFailed = true;
2483
- const message = err instanceof Error ? err.message : String(err);
2484
- session.errors.push({
2485
- eventId: "sink",
2486
- message,
2487
- type: "sink",
2488
- timestamp: endedAtIso
2489
- });
2490
- }
2491
- } else if (sink.type === "cognipeer" || sink.type === "http") {
3837
+ const terminal = initialStatus !== "paused" && initialStatus !== "in_progress";
3838
+ const exportTargets = [];
3839
+ if (sink.type === "otlp") exportTargets.push({ exporter: sink.exporter, isSink: true });
3840
+ if (!isSubagentTraceScope(session)) {
3841
+ for (const exporter of session.exporters ?? []) exportTargets.push({ exporter, isSink: false });
3842
+ }
3843
+ const unsampled = session.parent !== void 0 && !session.parent.sampled;
3844
+ if (exportTargets.length > 0) {
3845
+ const results = await Promise.all(
3846
+ exportTargets.map(async ({ exporter }) => {
3847
+ if (unsampled) {
3848
+ return { ok: true, skipped: true, reason: "the upstream traceparent is not sampled (sampled=0)", attempts: 0, spans: 0, bytes: 0 };
3849
+ }
3850
+ try {
3851
+ return await exporter.exportSession(exportPayload, {
3852
+ terminal,
3853
+ cancelled: params.cancelled,
3854
+ parent: session.parent
3855
+ });
3856
+ } catch (err) {
3857
+ return { ok: false, attempts: 0, spans: 0, bytes: 0, error: err instanceof Error ? err.message : String(err) };
3858
+ }
3859
+ })
3860
+ );
3861
+ results.forEach((result, index) => {
3862
+ const { exporter, isSink } = exportTargets[index];
3863
+ (session.exportReports ?? (session.exportReports = [])).push({ exporter: exporter.name, endpoint: exporter.endpoint, sink: isSink, terminal, result });
3864
+ if (result.ok) {
3865
+ const rejected = result.partialSuccess?.rejectedSpans ?? 0;
3866
+ if ((rejected > 0 || result.partialSuccess?.message) && typeof console !== "undefined" && typeof console.warn === "function") {
3867
+ const detail = result.partialSuccess?.message ? `: ${result.partialSuccess.message}` : "";
3868
+ console.warn(`[Tracing] OTLP exporter "${exporter.name}": the collector rejected ${rejected} span(s)${detail}`);
3869
+ }
3870
+ return;
3871
+ }
3872
+ const message = result.error ?? "OTLP export failed";
3873
+ if (isSink) {
3874
+ sinkFailed = true;
3875
+ session.errors.push({ eventId: "sink", message, type: "sink", timestamp: endedAtIso });
3876
+ if (typeof console !== "undefined" && typeof console.error === "function") {
3877
+ console.error("[Tracing] OTLP export failed:", message);
3878
+ }
3879
+ } else if (typeof console !== "undefined" && typeof console.warn === "function") {
3880
+ console.warn(`[Tracing] OTLP exporter "${exporter.name}" failed:`, message);
3881
+ }
3882
+ });
3883
+ }
3884
+ if (params.exportOnly) {
3885
+ return buildPayload(payloadForSink.status);
3886
+ }
3887
+ if (sink.type === "cognipeer" || sink.type === "http") {
2492
3888
  try {
2493
3889
  const headers = sink.type === "cognipeer" ? { Authorization: `Bearer ${sink.apiKey}` } : sink.headers;
2494
3890
  if (isStreamingMode && session.sessionStarted) {
@@ -2584,6 +3980,23 @@ async function finalizeTraceSession(session, params = {}) {
2584
3980
  }
2585
3981
  return finalPayload;
2586
3982
  }
3983
+ async function closeTraceContinuation(continuation, params = {}) {
3984
+ const parsed = readTraceContinuation(continuation);
3985
+ if (!parsed) return void 0;
3986
+ const tracing = { ...params.tracing ?? {}, enabled: true };
3987
+ const hasOtlpSink = withDefaults(tracing).sink.type === "otlp";
3988
+ if (!hasOtlpSink && !params.exporters?.length) return void 0;
3989
+ const session = createTraceSession({ tracing }, parsed, { exporters: params.exporters });
3990
+ if (!session) return void 0;
3991
+ replayDeferredTraceEvents(session, params.events);
3992
+ const status = params.status ?? "partial";
3993
+ return finalizeTraceSession(session, {
3994
+ agentRuntime: params.agentRuntime,
3995
+ status,
3996
+ error: status === "error" ? params.error ?? { message: "The run ended in an error before it could be resumed." } : null,
3997
+ exportOnly: true
3998
+ });
3999
+ }
2587
4000
  function sanitizeTracePayload(value) {
2588
4001
  if (value === void 0) return void 0;
2589
4002
  try {
@@ -2623,6 +4036,72 @@ function estimatePayloadBytes(value) {
2623
4036
  }
2624
4037
  }
2625
4038
  }
4039
+
4040
+ // src/providers/wireInfo.ts
4041
+ var WIRE_INFO = Symbol.for("cognipeer.agent-sdk.wireInfo");
4042
+ function usageBasisOf(provider) {
4043
+ switch (provider) {
4044
+ case "anthropic":
4045
+ case "bedrock":
4046
+ return { inputExcludesCache: true };
4047
+ case "vertex":
4048
+ return { outputExcludesReasoning: true };
4049
+ default:
4050
+ return void 0;
4051
+ }
4052
+ }
4053
+ function attachWireInfo(message, info) {
4054
+ const clean = {};
4055
+ if (info.provider) clean.provider = info.provider;
4056
+ if (info.responseId) clean.responseId = info.responseId;
4057
+ if (info.responseModel) clean.responseModel = info.responseModel;
4058
+ if (info.rawFinishReason) clean.rawFinishReason = info.rawFinishReason;
4059
+ if (info.streaming) clean.streaming = true;
4060
+ const basis = info.usageBasis ?? usageBasisOf(info.provider);
4061
+ if (basis) clean.usageBasis = basis;
4062
+ message[WIRE_INFO] = clean;
4063
+ return message;
4064
+ }
4065
+ function wireInfoOf(message) {
4066
+ if (!message || typeof message !== "object") return void 0;
4067
+ return message[WIRE_INFO];
4068
+ }
4069
+
4070
+ // src/utils/traceFacts.ts
4071
+ var nonEmpty2 = (value) => typeof value === "string" && value.trim().length > 0 ? value : void 0;
4072
+ var isRunId = (id) => /^(run-|lc_run)/i.test(id);
4073
+ function providerHintOf(model, response) {
4074
+ const named = getProviderName(model);
4075
+ if (named) return named;
4076
+ const fromWire = wireInfoOf(response)?.provider;
4077
+ if (fromWire) return fromWire;
4078
+ try {
4079
+ return nonEmpty2(getModelCapabilities(model).provider);
4080
+ } catch {
4081
+ return void 0;
4082
+ }
4083
+ }
4084
+ function traceResponseFacts(model, response, rawUsage, streaming) {
4085
+ const wire = wireInfoOf(response);
4086
+ const meta = response?.response_metadata ?? {};
4087
+ const message = response;
4088
+ const idCandidate = nonEmpty2(wire?.responseId) ?? nonEmpty2(meta.id) ?? nonEmpty2(message?.id);
4089
+ const responseId = idCandidate && !isRunId(idCandidate) ? idCandidate : void 0;
4090
+ const responseModel = nonEmpty2(wire?.responseModel) ?? nonEmpty2(meta.model_name) ?? nonEmpty2(meta.model) ?? nonEmpty2(meta.modelName);
4091
+ const rawFinishReason = nonEmpty2(wire?.rawFinishReason) ?? nonEmpty2(meta.stop_reason) ?? nonEmpty2(meta.finish_reason) ?? nonEmpty2(meta.finishReason);
4092
+ const cacheWriteTokens = cacheWriteTokensOf(rawUsage);
4093
+ const provider = providerHintOf(model, response);
4094
+ const isStreaming = streaming ?? wire?.streaming;
4095
+ return {
4096
+ ...provider ? { provider } : {},
4097
+ ...responseId ? { responseId } : {},
4098
+ ...responseModel ? { responseModel } : {},
4099
+ ...rawFinishReason ? { rawFinishReason } : {},
4100
+ ...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {},
4101
+ ...wire?.usageBasis ? { usageBasis: { ...wire.usageBasis } } : {},
4102
+ ...isStreaming ? { streaming: true } : {}
4103
+ };
4104
+ }
2626
4105
  function toMessageUsage(u) {
2627
4106
  return {
2628
4107
  prompt_tokens: u.inputTokens,
@@ -2645,7 +4124,12 @@ function fromNativeProvider(provider, options) {
2645
4124
  if (link.signal) request.signal = link.signal;
2646
4125
  request = await applyTransform(request);
2647
4126
  const response = await provider.complete(request);
2648
- return toBaseChatMessage(response);
4127
+ return attachWireInfo(toBaseChatMessage(response), {
4128
+ provider: provider.providerName,
4129
+ responseId: response.id,
4130
+ responseModel: response.model,
4131
+ rawFinishReason: response.rawFinishReason
4132
+ });
2649
4133
  } finally {
2650
4134
  link.dispose();
2651
4135
  }
@@ -2664,6 +4148,8 @@ function fromNativeProvider(provider, options) {
2664
4148
  let reasoningText = "";
2665
4149
  let finishReason;
2666
4150
  let responseModel;
4151
+ let responseId;
4152
+ let rawFinishReason;
2667
4153
  const toolCallBuffers = /* @__PURE__ */ new Map();
2668
4154
  for await (const chunk of provider.completeStream(request)) {
2669
4155
  if (chunk.delta.content) {
@@ -2671,6 +4157,8 @@ function fromNativeProvider(provider, options) {
2671
4157
  yield chunk.delta.content;
2672
4158
  }
2673
4159
  if (chunk.model) responseModel = chunk.model;
4160
+ if (chunk.id) responseId = chunk.id;
4161
+ if (chunk.rawFinishReason) rawFinishReason = chunk.rawFinishReason;
2674
4162
  if (chunk.finishReason) finishReason = chunk.finishReason;
2675
4163
  if (chunk.delta.reasoning?.blocks?.length) {
2676
4164
  reasoningBlocks = chunk.delta.reasoning.blocks;
@@ -2692,7 +4180,8 @@ function fromNativeProvider(provider, options) {
2692
4180
  id: tc.id,
2693
4181
  name: tc.name ?? "",
2694
4182
  arguments: tc.arguments ?? "",
2695
- ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
4183
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
4184
+ ...tc.idSynthesized ? { idSynthesized: true } : {}
2696
4185
  });
2697
4186
  }
2698
4187
  }
@@ -2716,7 +4205,13 @@ function fromNativeProvider(provider, options) {
2716
4205
  ...responseModel ? { model_name: responseModel } : {}
2717
4206
  };
2718
4207
  }
2719
- yield finalMessage;
4208
+ yield attachWireInfo(finalMessage, {
4209
+ provider: provider.providerName,
4210
+ responseId,
4211
+ responseModel,
4212
+ rawFinishReason,
4213
+ streaming: true
4214
+ });
2720
4215
  } finally {
2721
4216
  link.dispose();
2722
4217
  }
@@ -3090,7 +4585,8 @@ function toBaseChatMessage(response) {
3090
4585
  id: tc.id,
3091
4586
  type: "function",
3092
4587
  function: { name: tc.name, arguments: tc.arguments },
3093
- ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
4588
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
4589
+ ...tc.idSynthesized ? { idSynthesized: true } : {}
3094
4590
  }));
3095
4591
  }
3096
4592
  if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
@@ -3112,7 +4608,8 @@ function assembleMessage(content, toolCalls, usage) {
3112
4608
  id: tc.id,
3113
4609
  type: "function",
3114
4610
  function: { name: tc.name, arguments: tc.arguments },
3115
- ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
4611
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
4612
+ ...tc.idSynthesized ? { idSynthesized: true } : {}
3116
4613
  }));
3117
4614
  }
3118
4615
  return msg;
@@ -4006,7 +5503,7 @@ var CCRStore = class _CCRStore {
4006
5503
  }
4007
5504
  static hashOf(value) {
4008
5505
  const serialized = typeof value === "string" ? value : JSON.stringify(value);
4009
- return createHash("sha1").update(serialized).digest("hex").slice(0, 16);
5506
+ return createHash("sha256").update(serialized).digest("hex").slice(0, 16);
4010
5507
  }
4011
5508
  };
4012
5509
  var DedupTracker = class {
@@ -4019,7 +5516,7 @@ var DedupTracker = class {
4019
5516
  * first time it has been seen.
4020
5517
  */
4021
5518
  checkAndRegister(content, executionId, toolName) {
4022
- const hash = createHash("sha1").update(content).digest("hex");
5519
+ const hash = createHash("sha256").update(content).digest("hex");
4023
5520
  const existing = this.seen.get(hash);
4024
5521
  if (!existing) {
4025
5522
  this.seen.set(hash, { executionId, toolName });
@@ -4556,7 +6053,7 @@ function createAgentCoreNode(opts) {
4556
6053
  const actorVersion = runtime.version ?? opts.version;
4557
6054
  let traceToolDefinitions;
4558
6055
  const computeTraceToolDefinitions = (menu) => {
4559
- if (!traceSession || !traceSession.resolvedConfig.logData || menu.length === 0) return void 0;
6056
+ if (!traceSession || !(traceSession.resolvedConfig.logData || traceSession.captureContent) || menu.length === 0) return void 0;
4560
6057
  try {
4561
6058
  const wire = shouldUseStrictToolCalling ? prepareStrictToolMenu(menu).menu : menu;
4562
6059
  return wire.map((tool) => {
@@ -4769,8 +6266,9 @@ ${append}`;
4769
6266
  // outcome, and an "error" status would flip the whole trace session
4770
6267
  // status to error for a run that behaved exactly as configured.
4771
6268
  status: "skipped",
6269
+ skipReason: "blocked",
4772
6270
  model: getModelName(runtime.model || opts.model),
4773
- provider: getProviderName(runtime.model || opts.model),
6271
+ provider: providerHintOf(runtime.model || opts.model),
4774
6272
  messageList: state.messages
4775
6273
  });
4776
6274
  return {
@@ -4799,9 +6297,12 @@ ${append}`;
4799
6297
  for (const key of ["usage", "usage_metadata", "response_metadata"]) {
4800
6298
  if (merged[key] === void 0 && original?.[key] !== void 0) merged[key] = original[key];
4801
6299
  }
6300
+ if (wireInfoOf(merged) === void 0 && wireInfoOf(original) !== void 0) merged[WIRE_INFO] = wireInfoOf(original);
4802
6301
  return merged;
4803
6302
  };
4804
6303
  let response;
6304
+ let sentMessages;
6305
+ let streamedCall = false;
4805
6306
  let modelAttempt = 0;
4806
6307
  const maxModelRetries = host?.maxModelRetries ?? 0;
4807
6308
  const finishCancelledTurn = (partialText) => {
@@ -4815,12 +6316,16 @@ ${append}`;
4815
6316
  // "skipped", not "error": the call did not fail, the caller ended it —
4816
6317
  // and an "error" would flip the whole session to error.
4817
6318
  status: "skipped",
6319
+ // The call reached the provider and was hung up on: still a model call, not a skipped one.
6320
+ skipReason: "cancelled",
6321
+ ...streamedCall ? { streaming: true } : {},
4818
6322
  durationMs: Date.now() - start,
4819
6323
  requestBytes: promptBytes,
4820
6324
  model: getModelName(runtime.model || opts.model),
4821
- provider: getProviderName(runtime.model || opts.model),
6325
+ provider: providerHintOf(runtime.model || opts.model),
4822
6326
  messageList: state.messages,
4823
- toolDefinitions: traceToolDefinitions
6327
+ toolDefinitions: traceToolDefinitions,
6328
+ capture: { input: sentMessages ?? wireMessages, toolDefinitions: traceToolDefinitions }
4824
6329
  });
4825
6330
  onEvent?.({ type: "cancelled", stage: "agent", reason });
4826
6331
  onProgress?.({ stage: "agent", message: "Cancelled", detail: { reason } });
@@ -4836,8 +6341,9 @@ ${append}`;
4836
6341
  label: "Assistant (plugin short-circuit)",
4837
6342
  actor: { scope: "agent", name: actorName, role: "assistant", version: actorVersion },
4838
6343
  status: "skipped",
6344
+ skipReason: "short_circuit",
4839
6345
  model: getModelName(runtime.model || opts.model),
4840
- provider: getProviderName(runtime.model || opts.model),
6346
+ provider: providerHintOf(runtime.model || opts.model),
4841
6347
  messageList: state.messages,
4842
6348
  toolDefinitions: traceToolDefinitions
4843
6349
  });
@@ -4845,8 +6351,10 @@ ${append}`;
4845
6351
  let streamedText = "";
4846
6352
  try {
4847
6353
  const normalizedMessages = normalizeBedrockToolPairing([...wireMessages]);
6354
+ sentMessages = normalizedMessages;
4848
6355
  debugToolPairing(normalizedMessages);
4849
6356
  if (streamingEnabled && typeof modelWithTools.stream === "function") {
6357
+ streamedCall = true;
4850
6358
  let streamedMessage;
4851
6359
  let cutByCancel = false;
4852
6360
  for await (const chunk of modelWithTools.stream(normalizedMessages, invokeParams)) {
@@ -4892,12 +6400,14 @@ ${append}`;
4892
6400
  durationMs: durationMs2,
4893
6401
  requestBytes: promptBytes,
4894
6402
  model: getModelName(runtime.model || opts.model),
4895
- provider: getProviderName(runtime.model || opts.model),
4896
- error: { message: err?.message || String(err), stack: err?.stack },
6403
+ provider: providerHintOf(runtime.model || opts.model),
6404
+ error: traceErrorOf(err),
6405
+ ...streamedCall ? { streaming: true } : {},
4897
6406
  messageList: state.messages,
4898
6407
  toolDefinitions: traceToolDefinitions,
4899
6408
  responseFormat: traceResponseFormat,
4900
- responseFormatStrategy: traceResponseFormatStrategy
6409
+ responseFormatStrategy: traceResponseFormatStrategy,
6410
+ capture: { input: sentMessages ?? wireMessages, toolDefinitions: traceToolDefinitions }
4901
6411
  });
4902
6412
  throw err;
4903
6413
  }
@@ -4950,6 +6460,8 @@ ${append}`;
4950
6460
  const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
4951
6461
  const responseBytes = responsePayload !== void 0 ? estimatePayloadBytes(responsePayload) : void 0;
4952
6462
  const finishReason = response?.response_metadata?.finish_reason ?? response?.response_metadata?.finishReason ?? response?.finishReason;
6463
+ const facts = traceResponseFacts(runtime.model || opts.model, response, rawUsage, streamedCall);
6464
+ const jsonOutput = Boolean(responseFormat) && responseFormat?.response_format?.type !== "text" && responseFormat?.type !== "text";
4953
6465
  recordTraceEvent(traceSession, {
4954
6466
  type: "ai_call",
4955
6467
  label: "Assistant Response",
@@ -4966,11 +6478,13 @@ ${append}`;
4966
6478
  requestBytes: promptBytes,
4967
6479
  responseBytes,
4968
6480
  model: modelName,
4969
- provider: getProviderName(runtime.model || opts.model),
6481
+ ...facts,
6482
+ outputType: jsonOutput ? "json" : "text",
4970
6483
  messageList: messagesWithResponse,
4971
6484
  toolDefinitions: traceToolDefinitions,
4972
6485
  responseFormat: traceResponseFormat,
4973
- responseFormatStrategy: traceResponseFormatStrategy
6486
+ responseFormatStrategy: traceResponseFormatStrategy,
6487
+ capture: { input: sentMessages ?? wireMessages, output: response, toolDefinitions: traceToolDefinitions }
4974
6488
  });
4975
6489
  if (normalized) {
4976
6490
  recordUsage(state, modelName, normalized);
@@ -4996,6 +6510,12 @@ function sameJson(a, b) {
4996
6510
  return false;
4997
6511
  }
4998
6512
  }
6513
+ var idSection = (label, data) => ({
6514
+ kind: "metadata",
6515
+ label,
6516
+ data,
6517
+ identity: true
6518
+ });
4999
6519
  function recordApprovalRequested(session, entry) {
5000
6520
  if (!session || surfacedFromSubagent(entry) || !canPauseForHuman(session)) return;
5001
6521
  const logData = session.resolvedConfig.logData;
@@ -5021,7 +6541,7 @@ function recordApprovalRequested(session, entry) {
5021
6541
  timestamp: entry.requestedAt,
5022
6542
  status: "pending",
5023
6543
  actor: { scope: "agent", name: entry.toolName, role: "approval_request" },
5024
- sections
6544
+ sections: [...sections, idSection("Approval ids", { approvalId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt })]
5025
6545
  });
5026
6546
  }
5027
6547
  function recordHumanDecisions(session, state) {
@@ -5062,7 +6582,14 @@ function recordHumanDecisions(session, state) {
5062
6582
  durationMs: waitedMs(entry.requestedAt, entry.decidedAt),
5063
6583
  status: "success",
5064
6584
  actor: { scope: "human", name: entry.decidedBy || "reviewer", role: "approver" },
5065
- sections
6585
+ sections: [...sections, idSection("Decision ids", {
6586
+ approvalId: entry.id,
6587
+ toolCallId: entry.toolCallId,
6588
+ decision: entry.status,
6589
+ requestedAt: entry.requestedAt,
6590
+ decidedAt: entry.decidedAt,
6591
+ ...waitedMs(entry.requestedAt, entry.decidedAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.decidedAt) } : {}
6592
+ })]
5066
6593
  });
5067
6594
  entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
5068
6595
  }
@@ -5107,7 +6634,14 @@ function recordHumanDecisions(session, state) {
5107
6634
  durationMs: waitedMs(entry.requestedAt, entry.answeredAt),
5108
6635
  status: cancelled ? "skipped" : "success",
5109
6636
  actor: { scope: "human", name: entry.answeredBy || "user", role: "user" },
5110
- sections
6637
+ sections: [...sections, idSection("Answer ids", {
6638
+ questionId: entry.id,
6639
+ toolCallId: entry.toolCallId,
6640
+ status: entry.status,
6641
+ requestedAt: entry.requestedAt,
6642
+ answeredAt: entry.answeredAt,
6643
+ ...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
6644
+ })]
5111
6645
  });
5112
6646
  entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
5113
6647
  }
@@ -5132,7 +6666,7 @@ function recordClientToolRequested(session, entry) {
5132
6666
  timestamp: entry.requestedAt,
5133
6667
  status: "pending",
5134
6668
  actor: { scope: "client", name: clientTool.name, role: "tool" },
5135
- sections
6669
+ sections: [...sections, idSection("Client tool ids", { questionId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt })]
5136
6670
  });
5137
6671
  }
5138
6672
  function readClientTool(entry) {
@@ -5179,7 +6713,14 @@ function recordClientToolResult(session, entry, clientTool, toolHistory) {
5179
6713
  durationMs: waitedMs(entry.requestedAt, entry.answeredAt) ?? ranMs,
5180
6714
  status: failed ? "error" : "success",
5181
6715
  actor: { scope: "client", name: clientTool.name, role: "tool" },
5182
- sections
6716
+ sections: [...sections, idSection("Client tool ids", {
6717
+ questionId: entry.id,
6718
+ toolCallId: entry.toolCallId,
6719
+ status: failed ? "error" : "answered",
6720
+ requestedAt: entry.requestedAt,
6721
+ answeredAt: entry.answeredAt,
6722
+ ...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
6723
+ })]
5183
6724
  });
5184
6725
  }
5185
6726
 
@@ -5285,9 +6826,11 @@ function normalizeToolCall(call) {
5285
6826
  return {
5286
6827
  id: call.id,
5287
6828
  name,
5288
- args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments
6829
+ args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments,
6830
+ ...call.idSynthesized === true ? { idSynthesized: true } : {}
5289
6831
  };
5290
6832
  }
6833
+ var providerToolCallId = (tc) => tc.id && !tc.idSynthesized ? tc.id : void 0;
5291
6834
  function normalizeToolSchema(tool, toolName) {
5292
6835
  const schema = tool.schema;
5293
6836
  if (!schema) return void 0;
@@ -5545,6 +7088,8 @@ function createToolsNode(initialTools, opts) {
5545
7088
  label: `Tool Denied - ${toolName}`,
5546
7089
  actor: { scope: "tool", name: toolName, role: "tool" },
5547
7090
  status: "skipped",
7091
+ skipReason: "denied",
7092
+ toolCallId: providerToolCallId(tc),
5548
7093
  toolDetails,
5549
7094
  toolExecutionId: toolCallId,
5550
7095
  sections: buildToolTraceSections({
@@ -5616,6 +7161,8 @@ function createToolsNode(initialTools, opts) {
5616
7161
  label: `Tool Skipped - ${toolName}`,
5617
7162
  actor: { scope: "tool", name: toolName, role: "tool" },
5618
7163
  status: "skipped",
7164
+ skipReason: "skipped",
7165
+ toolCallId: providerToolCallId(tc),
5619
7166
  toolDetails,
5620
7167
  toolExecutionId: tc.id,
5621
7168
  sections: buildToolTraceSections({
@@ -5752,10 +7299,13 @@ function createToolsNode(initialTools, opts) {
5752
7299
  label: `Tool Error - ${toolName}`,
5753
7300
  actor: { scope: "tool", name: toolName, role: "tool" },
5754
7301
  status: "error",
7302
+ // The tool was not run: an open breaker refused the call.
7303
+ skipReason: "skipped",
7304
+ toolCallId: providerToolCallId(tc),
5755
7305
  requestBytes: inputBytes,
5756
7306
  toolDetails,
5757
7307
  toolExecutionId: toolCallId,
5758
- error: { message: breakerMsg },
7308
+ error: { message: breakerMsg, type: "circuit_breaker_open" },
5759
7309
  sections: buildToolTraceSections({
5760
7310
  args,
5761
7311
  executionId: toolCallId,
@@ -5815,6 +7365,9 @@ function createToolsNode(initialTools, opts) {
5815
7365
  type: "tool_call",
5816
7366
  label: shortCircuitSource === "plugin" ? `Tool Short-Circuited - ${toolName}` : `Tool Execution - ${toolName}`,
5817
7367
  actor: { scope: "tool", name: toolName, role: "tool" },
7368
+ // Answered from the cache or by a plugin: nothing executed.
7369
+ skipReason: "short_circuit",
7370
+ toolCallId: providerToolCallId(tc),
5818
7371
  durationMs: 0,
5819
7372
  requestBytes: inputBytes,
5820
7373
  responseBytes: outputBytes2,
@@ -5850,7 +7403,15 @@ function createToolsNode(initialTools, opts) {
5850
7403
  onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
5851
7404
  const anyTool = tool;
5852
7405
  traceSpanId = traceSession ? generateSpanId() : void 0;
5853
- const callOptions = { cancellationToken, signal: abortSignal, toolCallId, ...traceSpanId ? { traceSpanId } : {} };
7406
+ const callOptions = {
7407
+ cancellationToken,
7408
+ signal: abortSignal,
7409
+ toolCallId,
7410
+ ...traceSpanId ? { traceSpanId } : {},
7411
+ // So the tool can propagate the trace to what it calls (traceparentOf).
7412
+ ...traceSpanId && traceSession?.traceId ? { traceId: traceSession.traceId } : {},
7413
+ ...traceSpanId && traceSession?.parent ? { traceFlags: traceSession.parent.flags } : {}
7414
+ };
5854
7415
  const invokeOnce = async () => {
5855
7416
  if (typeof anyTool.func === "function") return anyTool.func(args, callOptions);
5856
7417
  if (typeof anyTool.invoke === "function") return anyTool.invoke(args, callOptions);
@@ -6036,7 +7597,10 @@ function createToolsNode(initialTools, opts) {
6036
7597
  spanId: traceSpanId,
6037
7598
  label: `Tool Execution - ${toolName}`,
6038
7599
  actor: { scope: "tool", name: toolName, role: "tool" },
6039
- ...reportedFailure ? { status: "error", error: { message: reportedFailure } } : {},
7600
+ ...reportedFailure ? { status: "error", error: { message: reportedFailure, type: "tool_error" } } : {},
7601
+ toolCallId: providerToolCallId(tc),
7602
+ // `output` is already past postToolUse, so a redaction plugin has applied.
7603
+ capture: reportedFailure ? { toolArguments: args } : { toolArguments: args, toolResult: output, hasToolResult: true },
6040
7604
  durationMs,
6041
7605
  requestBytes: inputBytes,
6042
7606
  responseBytes: outputBytes,
@@ -6100,12 +7664,14 @@ function createToolsNode(initialTools, opts) {
6100
7664
  label: `Tool Error - ${toolName}`,
6101
7665
  actor: { scope: "tool", name: toolName, role: "tool" },
6102
7666
  status: "error",
7667
+ toolCallId: providerToolCallId(tc),
7668
+ capture: { toolArguments: args },
6103
7669
  durationMs,
6104
7670
  requestBytes: inputBytes,
6105
7671
  responseBytes: traceSession?.resolvedConfig.logData ? estimatePayloadBytes(errorOutput) : void 0,
6106
7672
  toolDetails,
6107
7673
  toolExecutionId: executionId,
6108
- error: { message, stack: host?.has("postToolUse") ? void 0 : error?.stack },
7674
+ error: { ...traceErrorOf(error), message, stack: host?.has("postToolUse") ? void 0 : error?.stack },
6109
7675
  sections: buildToolTraceSections({
6110
7676
  args: sanitizedArgs,
6111
7677
  durationMs,
@@ -6220,6 +7786,8 @@ function createToolsNode(initialTools, opts) {
6220
7786
  label: `Tool Skipped - ${tc.name}`,
6221
7787
  actor: { scope: "tool", name: tc.name, role: "tool" },
6222
7788
  status: "skipped",
7789
+ skipReason: "skipped",
7790
+ toolCallId: providerToolCallId(tc),
6223
7791
  toolDetails,
6224
7792
  toolExecutionId: tc.id,
6225
7793
  sections: buildToolTraceSections({
@@ -6386,7 +7954,7 @@ function createReflectionNode(opts, resolved) {
6386
7954
  label: "Reflection error",
6387
7955
  actor: { scope: "agent", name: opts.name || "agent", role: "reflection" },
6388
7956
  status: "error",
6389
- error: { message: err?.message || String(err) }
7957
+ error: traceErrorOf(err)
6390
7958
  });
6391
7959
  return {};
6392
7960
  }
@@ -7397,7 +8965,7 @@ function buildSubagentCatalogBlock(subagents, policy, toolNames, opts) {
7397
8965
  // src/plugins/host.ts
7398
8966
  init_content();
7399
8967
  var DEFAULT_PRIORITY = 100;
7400
- var DEFAULT_TIMEOUT_MS = 1e4;
8968
+ var DEFAULT_TIMEOUT_MS2 = 1e4;
7401
8969
  var HOOK_SPECS = {
7402
8970
  sessionStart: { kind: "gate", mutable: ["messages"], collect: ["systemPromptAppend"] },
7403
8971
  userPromptSubmit: {
@@ -7502,7 +9070,7 @@ function collectRegistrations(plugin, registrations, into, orderRef) {
7502
9070
  plugin: plugin.name,
7503
9071
  priority: plugin.priority ?? DEFAULT_PRIORITY,
7504
9072
  failureMode: plugin.failureMode ?? "open",
7505
- timeoutMs: plugin.timeoutMs ?? DEFAULT_TIMEOUT_MS,
9073
+ timeoutMs: plugin.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
7506
9074
  order: orderRef.value++,
7507
9075
  handler
7508
9076
  });
@@ -7557,6 +9125,7 @@ function createPluginHost(plugins = [], options = {}) {
7557
9125
  let contributions = {
7558
9126
  tools: [],
7559
9127
  toolDescriptions: {},
9128
+ traceExporters: [],
7560
9129
  guardrails: [],
7561
9130
  applySystemPrompt: (base) => base,
7562
9131
  applyModelWrappers: (model) => model
@@ -7565,6 +9134,7 @@ function createPluginHost(plugins = [], options = {}) {
7565
9134
  async function runSetup(setupInput) {
7566
9135
  const tools = [];
7567
9136
  const toolDescriptions = {};
9137
+ const traceExporters = [];
7568
9138
  const guardrails = [];
7569
9139
  const promptSteps = [];
7570
9140
  const modelWrappers = [];
@@ -7602,6 +9172,7 @@ function createPluginHost(plugins = [], options = {}) {
7602
9172
  );
7603
9173
  }
7604
9174
  if (plugin.toolDescriptions) Object.assign(toolDescriptions, plugin.toolDescriptions);
9175
+ if (plugin.traceExporters?.length) traceExporters.push(...plugin.traceExporters.filter(Boolean));
7605
9176
  if (plugin.guardrails?.length) guardrails.push(...plugin.guardrails);
7606
9177
  if (typeof plugin.wrapModel === "function") {
7607
9178
  modelWrappers.push({ plugin: plugin.name, wrap: plugin.wrapModel });
@@ -7617,6 +9188,7 @@ function createPluginHost(plugins = [], options = {}) {
7617
9188
  contributions = {
7618
9189
  tools,
7619
9190
  toolDescriptions,
9191
+ traceExporters,
7620
9192
  guardrails,
7621
9193
  applySystemPrompt: (base) => promptSteps.reduce((current, step) => {
7622
9194
  try {
@@ -8640,7 +10212,10 @@ function createAgent(opts) {
8640
10212
  }
8641
10213
  emit({ type: "progress", ...progress });
8642
10214
  };
8643
- const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation));
10215
+ const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation), {
10216
+ exporters: pluginHost.contributions.traceExporters,
10217
+ traceParent: config?.traceParent
10218
+ });
8644
10219
  const ctx = {
8645
10220
  ...input.ctx || {},
8646
10221
  __onEvent: onEvent,
@@ -8792,7 +10367,7 @@ function createAgent(opts) {
8792
10367
  await finalizeTraceSession(traceSession, {
8793
10368
  agentRuntime: runtime,
8794
10369
  status: "error",
8795
- error: { message: err?.message, stack: err?.stack }
10370
+ error: { message: err?.message, stack: err?.stack, name: err?.name }
8796
10371
  });
8797
10372
  await endSession("error", { error: err instanceof Error ? err : new Error(String(err)), state: stateHolder.value });
8798
10373
  if (userTokenCounter) {
@@ -8813,7 +10388,10 @@ function createAgent(opts) {
8813
10388
  const midTurn = pausedForHuman || Boolean(res.ctx?.__needsSummarization);
8814
10389
  await finalizeTraceSession(traceSession, {
8815
10390
  agentRuntime: res.agent || runtime,
8816
- status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success"
10391
+ status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success",
10392
+ // The file says `success` for a cancelled run (it did not fail); the
10393
+ // exported root says `partial`, the old plugin mapping.
10394
+ cancelled: statusFor(res) === "cancelled"
8817
10395
  });
8818
10396
  if (traceSession && midTurn) {
8819
10397
  res.ctx = { ...res.ctx || {}, __traceContinuation: traceContinuationOf(traceSession) };
@@ -8958,14 +10536,16 @@ function createAgent(opts) {
8958
10536
  const startedAt = Date.now();
8959
10537
  const recordSpan = (status, extra) => {
8960
10538
  if (!traced || !isTraceSessionOpen(parentSession)) return;
10539
+ const running = status === "running";
8961
10540
  recordSubagentSpan(parentSession, {
8962
10541
  spanId: agentSpanId,
8963
- parentSpanId: context?.traceSpanId ?? parentIterationSpanId,
10542
+ // The delegating tool_call span only exists once the tool returns.
10543
+ parentSpanId: running ? parentIterationSpanId : context?.traceSpanId ?? parentIterationSpanId,
8964
10544
  name: opts.name || "agent",
8965
10545
  status,
8966
- durationMs: Date.now() - startedAt,
10546
+ durationMs: running ? void 0 : Date.now() - startedAt,
8967
10547
  error: extra.error,
8968
- info: { name: opts.name || "agent", mode: "asTool", depth: currentDepth + 1, parentToolCallId: context?.toolCallId, status: status === "success" ? "ok" : "error" },
10548
+ info: { name: opts.name || "agent", mode: "asTool", depth: currentDepth + 1, parentToolCallId: context?.toolCallId, status: running ? "running" : status === "success" ? "ok" : "error" },
8969
10549
  task: input,
8970
10550
  result: extra.result
8971
10551
  });
@@ -8985,6 +10565,7 @@ function createAgent(opts) {
8985
10565
  stream: Boolean(parentCtx.__streaming),
8986
10566
  cancellationToken: parentCtx.__cancellationToken ?? parentCtx.__abortSignal
8987
10567
  };
10568
+ recordSpan("running", {});
8988
10569
  let res;
8989
10570
  try {
8990
10571
  res = await instance.invoke({ messages: childMessages, ctx: childCtx }, childConfig);
@@ -9069,9 +10650,10 @@ function createAgentNode(opts) {
9069
10650
  durationMs: durationMs2,
9070
10651
  requestBytes: promptBytes,
9071
10652
  model: getModelName(runtime.model || opts.model),
9072
- provider: getProviderName(runtime.model || opts.model),
9073
- error: { message: err?.message || String(err), stack: err?.stack },
9074
- messageList: promptMessages
10653
+ provider: providerHintOf(runtime.model || opts.model),
10654
+ error: traceErrorOf(err),
10655
+ messageList: promptMessages,
10656
+ capture: { input: promptMessages }
9075
10657
  });
9076
10658
  throw err;
9077
10659
  }
@@ -9082,7 +10664,7 @@ function createAgentNode(opts) {
9082
10664
  const rawUsage = response?.usage || response?.usage_metadata || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage || response?.response_metadata?.usage_metadata || response?.response_metadata?.usageMetadata;
9083
10665
  const normalized = normalizeUsage(rawUsage);
9084
10666
  const modelName = getModelName(runtime.model || opts.model) || "unknown_model";
9085
- const providerName = getProviderName(runtime.model || opts.model);
10667
+ const facts = traceResponseFacts(runtime.model || opts.model, response, rawUsage);
9086
10668
  const durationMs = Date.now() - start;
9087
10669
  const shouldLogResponse = !!traceSession && traceSession.resolvedConfig.logData;
9088
10670
  const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
@@ -9099,8 +10681,9 @@ function createAgentNode(opts) {
9099
10681
  requestBytes: promptBytes,
9100
10682
  responseBytes,
9101
10683
  model: modelName,
9102
- provider: providerName,
9103
- messageList: messagesWithResponse
10684
+ ...facts,
10685
+ messageList: messagesWithResponse,
10686
+ capture: { input: promptMessages, output: response }
9104
10687
  });
9105
10688
  if (normalized) {
9106
10689
  recordUsage(state, modelName, normalized);
@@ -9751,7 +11334,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9751
11334
  ];
9752
11335
  const inputTokensEstimate = countApproxTokens(summaryPrompt.map((m) => m.content).join("\n"));
9753
11336
  const modelName = getModelName(model);
9754
- const providerName = getProviderName(model);
11337
+ const providerName = providerHintOf(model);
9755
11338
  const tracingEnabled = Boolean(opts.tracing?.enabled);
9756
11339
  let ctxWithDeferredTrace;
9757
11340
  const traceSummarization = (event) => {
@@ -9782,6 +11365,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9782
11365
  let reasoningTokensActual;
9783
11366
  let fallback = false;
9784
11367
  let summarizerError;
11368
+ let responseFacts;
9785
11369
  const directivesSection = () => ({
9786
11370
  kind: "metadata",
9787
11371
  label: "User directives",
@@ -9823,6 +11407,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9823
11407
  summaryText = renderStructuredSummary(structuredSummary);
9824
11408
  const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
9825
11409
  const normalized = normalizeUsage(rawUsage);
11410
+ responseFacts = traceResponseFacts(model, response, rawUsage);
9826
11411
  if (normalized) {
9827
11412
  inputTokensActual = normalized.prompt_tokens;
9828
11413
  outputTokensActual = normalized.completion_tokens;
@@ -9859,7 +11444,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9859
11444
  ...droppedDirectives.length > 0 ? { droppedDirectives } : {}
9860
11445
  };
9861
11446
  onEvent?.(errorEvent);
9862
- summarizerError = { message: err?.message || String(err), stack: err?.stack };
11447
+ summarizerError = traceErrorOf(err);
9863
11448
  }
9864
11449
  const toolCallIdToAssistantIdx = /* @__PURE__ */ new Map();
9865
11450
  messages.forEach((m, idx) => {
@@ -10015,10 +11600,16 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
10015
11600
  outputTokens: outputTokensActual ?? outputTokensEstimate,
10016
11601
  cachedInputTokens,
10017
11602
  totalTokens: totalTokensActual,
10018
- ...reasoningTokensActual !== void 0 ? { reasoningTokens: reasoningTokensActual } : {}
11603
+ ...reasoningTokensActual !== void 0 ? { reasoningTokens: reasoningTokensActual } : {},
11604
+ // Which counting rules the usage above follows (only when the provider reported it).
11605
+ ...inputTokensActual !== void 0 && responseFacts?.usageBasis ? { usageBasis: responseFacts.usageBasis } : {},
11606
+ ...inputTokensActual !== void 0 && responseFacts?.cacheWriteTokens ? { cacheWriteTokens: responseFacts.cacheWriteTokens } : {}
10019
11607
  },
11608
+ ...responseFacts?.responseId ? { responseId: responseFacts.responseId } : {},
11609
+ ...responseFacts?.responseModel ? { responseModel: responseFacts.responseModel } : {},
11610
+ ...responseFacts?.rawFinishReason ? { rawFinishReason: responseFacts.rawFinishReason } : {},
10020
11611
  ...modelName ? { model: modelName } : {},
10021
- ...providerName ? { provider: providerName } : {},
11612
+ ...responseFacts?.provider ?? providerName ? { provider: responseFacts?.provider ?? providerName } : {},
10022
11613
  ...summarizerError ? { error: summarizerError } : {},
10023
11614
  sections: [
10024
11615
  ...promptAndOutputSections(),
@@ -11162,19 +12753,29 @@ async function runChild(spec, input, deps, ref, opts) {
11162
12753
  const childDepth = (Number(parentCtx.__delegationDepth) || 0) + 1;
11163
12754
  const parentSession = parentCtx.__traceSession;
11164
12755
  const traced = isTraceSessionOpen(parentSession);
11165
- const agentSpanId = generateSpanId();
12756
+ const sessionStart = traced ? parentSession.startedAt : void 0;
12757
+ const persistedId = opts.record?.agentSpanId;
12758
+ const agentSpanId = typeof persistedId === "string" && /^[0-9a-f]{16}$/.test(persistedId) ? persistedId : generateSpanId();
12759
+ const persistedStart = opts.record?.startedAt;
12760
+ const startValid = typeof persistedStart === "number" && Number.isFinite(persistedStart) && persistedStart > 0 && persistedStart <= start;
12761
+ const runStartedAt = startValid ? Math.min(start, Math.max(persistedStart, sessionStart ?? persistedStart)) : start;
12762
+ const persistedSegments = opts.record?.segments;
12763
+ const segment = (typeof persistedSegments === "number" && Number.isInteger(persistedSegments) && persistedSegments >= 1 && persistedSegments <= 1e3 ? persistedSegments : 0) + 1;
12764
+ const elapsedMs = () => Math.max(0, Date.now() - runStartedAt);
11166
12765
  const parentIterationSpanId = traced ? parentSession.currentIterationSpanId : void 0;
11167
12766
  const traceScope = traced ? createSubagentTraceScope(parentSession, { agentSpanId, name: spec.name, spawnId, mode: spec.mode, hitl: opts.allowHITL, iterations: opts.record?.iterations }) : void 0;
11168
12767
  const recordSegment = (status, info) => {
11169
12768
  if (!traced || !isTraceSessionOpen(parentSession)) return;
12769
+ const unfinished = status === "pending" || status === "running";
11170
12770
  recordSubagentSpan(parentSession, {
11171
12771
  spanId: agentSpanId,
11172
- // The tool_call span only exists once the tool returns; a paused child
11173
- // has not returned, so its span hangs off the iteration.
11174
- parentSpanId: status === "pending" ? parentIterationSpanId : opts.parentSpanId ?? parentIterationSpanId,
12772
+ // The tool_call span only exists once the tool returns; a running or
12773
+ // paused child has not returned, so its span hangs off the iteration.
12774
+ parentSpanId: unfinished ? parentIterationSpanId : opts.parentSpanId ?? parentIterationSpanId,
11175
12775
  name: spec.name,
11176
12776
  status,
11177
- durationMs: Date.now() - start,
12777
+ // A starting segment has no extent yet; a reader draws it over its children.
12778
+ durationMs: status === "running" ? void 0 : elapsedMs(),
11178
12779
  error: info.error,
11179
12780
  info: {
11180
12781
  id: spawnId,
@@ -11184,6 +12785,8 @@ async function runChild(spec, input, deps, ref, opts) {
11184
12785
  depth: childDepth,
11185
12786
  parentToolCallId: opts.parentToolCallId,
11186
12787
  status: info.subagentStatus,
12788
+ // Only a run that paused has more than one segment to tell about.
12789
+ ...segment > 1 || unfinished ? { segments: segment } : {},
11187
12790
  ...info.note ? { note: info.note } : {},
11188
12791
  ...spec.metadata ? { metadata: spec.metadata } : {}
11189
12792
  },
@@ -11307,6 +12910,7 @@ async function runChild(spec, input, deps, ref, opts) {
11307
12910
  }
11308
12911
  if (traceScope) childInput = { ...childInput, ctx: { ...childInput.ctx || {}, __traceSession: traceScope } };
11309
12912
  const usageBaseline = childInput.usage?.perRequest?.length ?? 0;
12913
+ recordSegment("running", { subagentStatus: "running", input });
11310
12914
  let res;
11311
12915
  try {
11312
12916
  res = await child.invoke(childInput, childConfig);
@@ -11348,7 +12952,10 @@ async function runChild(spec, input, deps, ref, opts) {
11348
12952
  pendingKind: "approval",
11349
12953
  pendingId: childEntry.id,
11350
12954
  spawnId,
11351
- iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
12955
+ iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0,
12956
+ agentSpanId,
12957
+ startedAt: runStartedAt,
12958
+ segments: segment
11352
12959
  };
11353
12960
  recordSegment("pending", { subagentStatus: "paused", input });
11354
12961
  parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
@@ -11374,7 +12981,10 @@ async function runChild(spec, input, deps, ref, opts) {
11374
12981
  pendingKind: "user_question",
11375
12982
  pendingId: childEntry.id,
11376
12983
  spawnId,
11377
- iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
12984
+ iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0,
12985
+ agentSpanId,
12986
+ startedAt: runStartedAt,
12987
+ segments: segment
11378
12988
  };
11379
12989
  recordSegment("pending", { subagentStatus: "paused", input });
11380
12990
  parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
@@ -12061,6 +13671,30 @@ ${pluginAppend}`;
12061
13671
  };
12062
13672
  }
12063
13673
  }
13674
+ const traceHandoff = {};
13675
+ const noteTraceHandoff = (current) => {
13676
+ traceHandoff.continuation = current.ctx?.__traceContinuation;
13677
+ traceHandoff.events = current.ctx?.[DEFERRED_TRACE_EVENTS_KEY];
13678
+ };
13679
+ const closeDanglingTrace = async (status, error) => {
13680
+ const continuation = traceHandoff.continuation;
13681
+ const events = traceHandoff.events;
13682
+ traceHandoff.continuation = void 0;
13683
+ traceHandoff.events = void 0;
13684
+ if (!continuation) return;
13685
+ try {
13686
+ await closeTraceContinuation(continuation, {
13687
+ tracing: opts.tracing,
13688
+ exporters: pluginHost?.contributions.traceExporters,
13689
+ status,
13690
+ error,
13691
+ agentRuntime: base.__runtime,
13692
+ events
13693
+ });
13694
+ } catch (closeError) {
13695
+ console.warn("[agent-sdk] closing the trace failed:", closeError);
13696
+ }
13697
+ };
12064
13698
  try {
12065
13699
  const toolSet = buildInvokeToolSet();
12066
13700
  const stateRef = toolSet.stateRef;
@@ -12139,11 +13773,15 @@ ${pluginAppend}`;
12139
13773
  const result = await trySummarize(state, rawMessages, stateRef);
12140
13774
  state = result.state;
12141
13775
  rawMessages = result.rawMessages;
13776
+ noteTraceHandoff(state);
12142
13777
  if (result.compressed) continue;
12143
13778
  }
12144
13779
  const modelMessages = buildModelMessages(state, resolved);
13780
+ traceHandoff.continuation = void 0;
13781
+ traceHandoff.events = void 0;
12145
13782
  const res = await base.invoke({ ...state, messages: modelMessages }, turnConfig);
12146
13783
  lastResult = res;
13784
+ noteTraceHandoff(res.state ?? state);
12147
13785
  const currentSummaries = state.summaries;
12148
13786
  const currentSummaryRecords = state.summaryRecords;
12149
13787
  const currentPlan = state.plan;
@@ -12170,6 +13808,7 @@ ${pluginAppend}`;
12170
13808
  const result = await trySummarize(state, rawMessages, stateRef);
12171
13809
  state = result.state;
12172
13810
  rawMessages = result.rawMessages;
13811
+ noteTraceHandoff(state);
12173
13812
  continue;
12174
13813
  }
12175
13814
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
@@ -12181,6 +13820,7 @@ ${pluginAppend}`;
12181
13820
  const result = await trySummarize(state, rawMessages, stateRef);
12182
13821
  state = result.state;
12183
13822
  rawMessages = result.rawMessages;
13823
+ noteTraceHandoff(state);
12184
13824
  if (result.compressed) continue;
12185
13825
  }
12186
13826
  }
@@ -12191,6 +13831,7 @@ ${pluginAppend}`;
12191
13831
  lastResult = res;
12192
13832
  }
12193
13833
  if (state.ctx?.[DEFERRED_TRACE_EVENTS_KEY]) {
13834
+ traceHandoff.events = state.ctx[DEFERRED_TRACE_EVENTS_KEY];
12194
13835
  const ctx = { ...state.ctx || {} };
12195
13836
  delete ctx[DEFERRED_TRACE_EVENTS_KEY];
12196
13837
  state = { ...state, ctx };
@@ -12210,8 +13851,12 @@ ${pluginAppend}`;
12210
13851
  const strippedCtx = { ...endCtx };
12211
13852
  delete strippedCtx.__traceContinuation;
12212
13853
  lastResult = { ...lastResult, state: { ...lastResult.state, ctx: strippedCtx } };
13854
+ traceHandoff.continuation = endCtx.__traceContinuation;
13855
+ await closeDanglingTrace("success");
12213
13856
  }
12214
13857
  }
13858
+ traceHandoff.continuation = void 0;
13859
+ traceHandoff.events = void 0;
12215
13860
  if (skillsEnabled && lastResult.state) {
12216
13861
  const persisted = skillStateFromRegistry(toolSet.skillRegistryRef);
12217
13862
  if (persisted) {
@@ -12257,6 +13902,11 @@ ${pluginAppend}`;
12257
13902
  await endSession(endStatus, { result: lastResult });
12258
13903
  return lastResult;
12259
13904
  } catch (err) {
13905
+ await closeDanglingTrace("error", {
13906
+ message: err instanceof Error ? err.message : String(err),
13907
+ stack: err instanceof Error ? err.stack : void 0,
13908
+ name: err instanceof Error ? err.name : void 0
13909
+ });
12260
13910
  await endSession("error", { error: err instanceof Error ? err : new Error(String(err)) });
12261
13911
  throw err;
12262
13912
  }
@@ -13173,7 +14823,7 @@ function isHookImplemented(hook) {
13173
14823
  // src/plugins/builtin/guardrail.ts
13174
14824
  init_content();
13175
14825
  var ALLOW = { action: "allow" };
13176
- var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
14826
+ var RETRYABLE_STATUS2 = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
13177
14827
  var RetryableGuardrailError = class extends Error {
13178
14828
  constructor(message) {
13179
14829
  super(message);
@@ -13271,7 +14921,7 @@ function httpGuardrail(options) {
13271
14921
  } catch {
13272
14922
  }
13273
14923
  const message = `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ""}${text ? ` - ${text.slice(0, 200)}` : ""}`;
13274
- if (RETRYABLE_STATUS.has(response.status)) throw new RetryableGuardrailError(message);
14924
+ if (RETRYABLE_STATUS2.has(response.status)) throw new RetryableGuardrailError(message);
13275
14925
  throw new Error(message);
13276
14926
  }
13277
14927
  return response.json();
@@ -13378,9 +15028,9 @@ function createGuardrailPlugin(options) {
13378
15028
  });
13379
15029
  const resolved = verdict ?? ALLOW;
13380
15030
  if (resolved.raw?.disabled === true) {
13381
- const warned = (_b = ctx.store).__disabledWarned ?? (_b.__disabledWarned = /* @__PURE__ */ new Set());
13382
- if (!warned.has(request.phase)) {
13383
- warned.add(request.phase);
15031
+ const warned2 = (_b = ctx.store).__disabledWarned ?? (_b.__disabledWarned = /* @__PURE__ */ new Set());
15032
+ if (!warned2.has(request.phase)) {
15033
+ warned2.add(request.phase);
13384
15034
  ctx.logger.warn(
13385
15035
  `guardrail reports it is not active for the "${request.phase}" surface; nothing is being enforced there`
13386
15036
  );
@@ -13877,7 +15527,7 @@ function safeJson(value) {
13877
15527
  function matches(pattern, toolName) {
13878
15528
  return typeof pattern === "string" ? pattern === toolName : pattern.test(toolName);
13879
15529
  }
13880
- function asObject(args) {
15530
+ function asObject2(args) {
13881
15531
  return args && typeof args === "object" ? args : {};
13882
15532
  }
13883
15533
  function toolPolicy(config = {}) {
@@ -13898,7 +15548,7 @@ function toolPolicy(config = {}) {
13898
15548
  hooks: {
13899
15549
  preToolUse: ({ toolName, args }, ctx) => {
13900
15550
  var _a;
13901
- const argObject = asObject(args);
15551
+ const argObject = asObject2(args);
13902
15552
  const isControlPlane = CONTROL_PLANE_TOOL_NAMES.includes(toolName);
13903
15553
  const allowListApplies = !isControlPlane || config.governControlPlaneTools === true;
13904
15554
  if (config.allowOnly && allowListApplies && !config.allowOnly.some((pattern) => matches(pattern, toolName))) {
@@ -13960,7 +15610,7 @@ function pathSandbox(config) {
13960
15610
  hooks: {
13961
15611
  preToolUse: ({ toolName, args }) => {
13962
15612
  if (config.tools && !config.tools.some((pattern) => matches(pattern, toolName))) return void 0;
13963
- const argObject = asObject(args);
15613
+ const argObject = asObject2(args);
13964
15614
  for (const key of argNames) {
13965
15615
  const value = argObject[key];
13966
15616
  if (typeof value !== "string" || value.length === 0) continue;
@@ -14728,7 +16378,7 @@ function mcp(config) {
14728
16378
  }
14729
16379
 
14730
16380
  // src/plugins/builtin/rateLimit.ts
14731
- function sleep(ms, signal) {
16381
+ function sleep2(ms, signal) {
14732
16382
  return new Promise((resolve) => {
14733
16383
  let timer;
14734
16384
  const done = () => {
@@ -14785,7 +16435,7 @@ function rateLimit(config = {}) {
14785
16435
  while (!attempt.ok) {
14786
16436
  const remaining = deadline - Date.now();
14787
16437
  if (!Number.isFinite(attempt.waitMs) || attempt.waitMs > remaining) break;
14788
- await sleep(Math.max(1, attempt.waitMs), ctx.signal);
16438
+ await sleep2(Math.max(1, attempt.waitMs), ctx.signal);
14789
16439
  if (ctx.signal?.aborted) break;
14790
16440
  attempt = consume(applicable);
14791
16441
  }
@@ -15881,18 +17531,21 @@ function langfuseTracing(config = {}) {
15881
17531
  }
15882
17532
 
15883
17533
  // src/plugins/builtin/otel.ts
15884
- function toSessionStatus(status) {
15885
- if (status === "success") return "success";
15886
- if (status === "error") return "error";
15887
- return status === "paused" ? "in_progress" : "partial";
15888
- }
15889
- function otelTracing(config) {
15890
- const endpoint = config.endpoint?.trim();
15891
- if (!endpoint) {
17534
+ function otelTracing(config = {}) {
17535
+ if (config.endpoint !== void 0 && !config.endpoint.trim()) {
15892
17536
  throw new Error("[agent-sdk] otelTracing requires a non-empty `endpoint`.");
15893
17537
  }
17538
+ const name = config.name ?? "otel-tracing";
17539
+ let exporter;
17540
+ try {
17541
+ exporter = createOtlpExporter({ ...config, endpoint: config.endpoint?.trim(), name });
17542
+ } catch {
17543
+ throw new Error(
17544
+ "[agent-sdk] otelTracing requires a non-empty `endpoint` (or OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_TRACES_ENDPOINT in the environment)."
17545
+ );
17546
+ }
15894
17547
  return {
15895
- name: config.name ?? "otel-tracing",
17548
+ name,
15896
17549
  // Registers only the `sessionEnd` observer, and observers run concurrently,
15897
17550
  // so this number orders nothing at runtime. It is set above checkpointing
15898
17551
  // (900) to record intent: this plugin is the last thing interested in the
@@ -15900,8 +17553,9 @@ function otelTracing(config) {
15900
17553
  priority: 950,
15901
17554
  // Observability. A dropped export is a reporting gap, never a safety hole.
15902
17555
  failureMode: "open",
17556
+ traceExporters: [exporter],
15903
17557
  hooks: {
15904
- sessionEnd: async ({ status, durationMs, error }, ctx) => {
17558
+ sessionEnd: async (_event, ctx) => {
15905
17559
  const state = ctx.state;
15906
17560
  const session = state.ctx?.__traceSession;
15907
17561
  if (isSubagentTraceScope(session)) return;
@@ -15911,57 +17565,29 @@ function otelTracing(config) {
15911
17565
  ctx.emit({ type: "metadata", otelTracing: { exported: false, reason: message } });
15912
17566
  return;
15913
17567
  }
15914
- const endedAtMs = Date.now();
15915
- const startedAtIso = new Date(session.startedAt).toISOString();
15916
- const errors = error ? [...session.errors, { eventId: "session", message: error.message, stack: error.stack, type: "session" }] : session.errors;
15917
- const payload = {
15918
- sessionId: session.sessionId,
15919
- traceId: session.traceId,
15920
- rootSpanId: session.rootSpanId,
15921
- threadId: session.threadId,
15922
- startedAt: startedAtIso,
15923
- endedAt: new Date(endedAtMs).toISOString(),
15924
- durationMs: durationMs ?? endedAtMs - session.startedAt,
15925
- // `service.name` is read off `agent.name` inside the conversion, so
15926
- // the override is applied here rather than by editing spans after.
15927
- agent: {
15928
- ...session.agentInfo ?? {},
15929
- name: config.serviceName ?? session.agentInfo?.name ?? session.configAgentName ?? ctx.agentName
15930
- },
15931
- metadata: session.configMetadata,
15932
- // Carried only to satisfy the type: `traceSessionToOtlp` reads the
15933
- // events, summary and identifiers, never the sink snapshot.
15934
- config: { enabled: true, logData: session.resolvedConfig.logData, sink: { type: "otlp", endpoint } },
15935
- summary: session.summary,
15936
- events: session.events,
15937
- status: toSessionStatus(status),
15938
- errors
15939
- };
15940
- try {
15941
- const fetchFn = typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0;
15942
- if (!fetchFn) {
15943
- ctx.logger.warn("otelTracing needs fetch to be available in this runtime; export skipped.");
15944
- return;
15945
- }
15946
- const response = await fetchFn(endpoint, {
15947
- method: "POST",
15948
- headers: { "content-type": "application/json", ...config.headers ?? {} },
15949
- body: JSON.stringify(traceSessionToOtlp(payload)),
15950
- // The run is over, but a host that cancelled it should not be made
15951
- // to wait on a collector that is refusing to answer.
15952
- signal: ctx.signal
15953
- });
15954
- if (!response.ok) {
15955
- ctx.logger.warn(`otelTracing export returned HTTP ${response.status}.`);
15956
- return;
15957
- }
15958
- ctx.emit({
15959
- type: "metadata",
15960
- otelTracing: { exported: true, endpoint, spans: session.events.length + 1 }
15961
- });
15962
- } catch (err) {
15963
- ctx.logger.warn("otelTracing export failed:", err instanceof Error ? err.message : err);
17568
+ const reports = (session.exportReports ?? []).filter((report2) => !report2.sink && report2.exporter === name);
17569
+ const report = reports[reports.length - 1];
17570
+ if (!report) return;
17571
+ const { result } = report;
17572
+ if (!result.ok) {
17573
+ ctx.logger.warn(`otelTracing export failed: ${result.error ?? "unknown error"}`);
17574
+ return;
17575
+ }
17576
+ if (result.skipped) {
17577
+ ctx.emit({ type: "metadata", otelTracing: { exported: false, reason: result.reason ?? "nothing to export" } });
17578
+ return;
15964
17579
  }
17580
+ ctx.emit({
17581
+ type: "metadata",
17582
+ otelTracing: {
17583
+ exported: true,
17584
+ endpoint: report.endpoint,
17585
+ spans: result.spans,
17586
+ terminal: report.terminal,
17587
+ // A 200 that refused some spans: the collector's count and message.
17588
+ ...result.partialSuccess ? { rejectedSpans: result.partialSuccess.rejectedSpans, ...result.partialSuccess.message ? { rejectionMessage: result.partialSuccess.message } : {} } : {}
17589
+ }
17590
+ });
15965
17591
  }
15966
17592
  }
15967
17593
  };
@@ -18997,9 +20623,9 @@ function mapAnthropicStopReason(reason) {
18997
20623
  return "stop";
18998
20624
  }
18999
20625
  }
19000
- function safeJsonParse(str) {
20626
+ function safeJsonParse(str2) {
19001
20627
  try {
19002
- return JSON.parse(str);
20628
+ return JSON.parse(str2);
19003
20629
  } catch {
19004
20630
  return {};
19005
20631
  }
@@ -19869,9 +21495,9 @@ function mediaTypeToFormat(mediaType) {
19869
21495
  };
19870
21496
  return map[mediaType] ?? "png";
19871
21497
  }
19872
- function safeJsonParse2(str) {
21498
+ function safeJsonParse2(str2) {
19873
21499
  try {
19874
- return JSON.parse(str);
21500
+ return JSON.parse(str2);
19875
21501
  } catch {
19876
21502
  return {};
19877
21503
  }
@@ -20268,10 +21894,13 @@ var VertexProvider = class extends BaseProvider {
20268
21894
  textParts.push(part.text);
20269
21895
  }
20270
21896
  } else if (part.functionCall) {
21897
+ const suppliedId = typeof part.functionCall.id === "string" && part.functionCall.id ? part.functionCall.id : void 0;
21898
+ const position = toolCallIdx++;
20271
21899
  toolCalls.push({
20272
- id: `call_${toolCallIdx++}`,
21900
+ id: suppliedId ?? `call_${position}`,
20273
21901
  name: part.functionCall.name,
20274
21902
  arguments: JSON.stringify(part.functionCall.args ?? {}),
21903
+ ...suppliedId ? {} : { idSynthesized: true },
20275
21904
  ...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
20276
21905
  });
20277
21906
  }
@@ -20311,12 +21940,15 @@ var VertexProvider = class extends BaseProvider {
20311
21940
  }
20312
21941
  } else if (part.functionCall) {
20313
21942
  if (!delta.toolCalls) delta.toolCalls = [];
21943
+ const suppliedId = typeof part.functionCall.id === "string" && part.functionCall.id ? part.functionCall.id : void 0;
21944
+ const position = counter.next++;
20314
21945
  delta.toolCalls.push({
20315
21946
  // Unique across the whole stream: the adapter merges chunks by id.
20316
- id: `call_${counter.next}`,
20317
- index: counter.next++,
21947
+ id: suppliedId ?? `call_${position}`,
21948
+ index: position,
20318
21949
  name: part.functionCall.name,
20319
21950
  arguments: JSON.stringify(part.functionCall.args ?? {}),
21951
+ ...suppliedId ? {} : { idSynthesized: true },
20320
21952
  ...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
20321
21953
  });
20322
21954
  }
@@ -20369,12 +22001,12 @@ function mapGeminiFinishReason(reason) {
20369
22001
  return "stop";
20370
22002
  }
20371
22003
  }
20372
- function base64url(str) {
20373
- return Buffer.from(str).toString("base64url");
22004
+ function base64url(str2) {
22005
+ return Buffer.from(str2).toString("base64url");
20374
22006
  }
20375
- function safeJsonParse3(str) {
22007
+ function safeJsonParse3(str2) {
20376
22008
  try {
20377
- return JSON.parse(str);
22009
+ return JSON.parse(str2);
20378
22010
  } catch {
20379
22011
  return {};
20380
22012
  }
@@ -20402,6 +22034,6 @@ function createProvider(config) {
20402
22034
  }
20403
22035
  }
20404
22036
 
20405
- export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, JevProvider, LAST_SUMMARIZATION_CALL_KEY, MAX_ADJUSTMENTS, MODEL_RULES, ModelRequestError, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, allowsSampling, appendBoundTools, applyDropParams, asModelRequestError, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, clearLearnedModelRules, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentPartToText, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, describeContentPart, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, effortBudget, emptyUsage, evaluateGuardrails, extractLatestUserQuery, extractMessageText, fileCheckpointStore, fileSink, findSubagent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getLearnedModelRulePatch, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasMediaPart, hasToolResponseRecoveryReference, httpGuardrail, httpSink, inMemoryCheckpointStore, inMemoryConversationStore, isHookImplemented, isOpenAIHostedEndpoint, isSmartModel, isTraceSessionOpen, isValidIban, isValidLuhn, isValidTckn, jsonSchemaRule, defaultBuildPayload as langfuseDefaultPayload, langfuseTracing, languageGuard, listLearnedModelRules, loadSkillsFromDisk, mapConsoleHookVerdict, mapReasoningEffort, mapTextParts, mcp, mediaKindOf, mediaPolicy, mergeRulePatch, modelIdCandidates, normalizeSmartAgentOptions, normalizeVerdicts, openAIModeration, otelTracing, otlpSink, outputGuard, parseApprovalDecision, parseModelError, parseSkillFrontmatter, pathSandbox, piiRedaction, pluginCapabilities, portkeyGateway, portkeyGuardrail, preopenSkills, preopenToolCallId, prepareStrictToolMenu, promptInjectionGuard, rateLimit, readMemoryFacts, readTraceContinuation, recordOrDeferTraceEvent, redactText, regexGuardrail, regexRule, rememberModelRulePatch, replaceTextContent, replayDeferredTraceEvents, resolveAvailableSkills, resolveAvailableSubagents, resolveInputRetention, resolveMemoryStore, resolveModelRule, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveSummarizationRetention, resolveToolApprovalState, resolveUserQuestionState, responseCache, restoreSnapshot, restoreToolCalls, runSmartAgentEvalHarness, runWithModelAdjustments, scoreItemsByRelevance, searchSkills, seedChildMessages, selectTopIndicesInOrder, sessionMetrics, setTokenCounter, startStreamingSession, summarizeObject, supportsAdaptiveThinking, textFromContent, toMessageUsage, toModelResult, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceContinuationOf, traceSectionsFromMessages, traceSessionToOtlp, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
22037
+ export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GENAI_SEMCONV_COMMIT, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, JevProvider, LAST_SUMMARIZATION_CALL_KEY, MAX_ADJUSTMENTS, MODEL_RULES, ModelRequestError, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, allowsSampling, appendBoundTools, applyDropParams, asModelRequestError, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, clearLearnedModelRules, closeTraceContinuation, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentPartToText, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createOtlpExporter, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, describeContentPart, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, effortBudget, emptyUsage, evaluateGuardrails, extractLatestUserQuery, extractMessageText, fileCheckpointStore, fileSink, findSubagent, foldSupersededSpans, formatTraceparent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getLearnedModelRulePatch, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasMediaPart, hasToolResponseRecoveryReference, httpGuardrail, httpSink, inMemoryCheckpointStore, inMemoryConversationStore, isHookImplemented, isOpenAIHostedEndpoint, isSmartModel, isTraceSessionOpen, isValidIban, isValidLuhn, isValidTckn, jsonSchemaRule, defaultBuildPayload as langfuseDefaultPayload, langfuseTracing, languageGuard, listLearnedModelRules, loadSkillsFromDisk, mapConsoleHookVerdict, mapReasoningEffort, mapTextParts, mcp, mediaKindOf, mediaPolicy, mergeRulePatch, modelIdCandidates, normalizeSmartAgentOptions, normalizeVerdicts, openAIModeration, otelTracing, otlpSink, outputGuard, parseApprovalDecision, parseModelError, parseSkillFrontmatter, parseTraceparent, pathSandbox, piiRedaction, pluginCapabilities, portkeyGateway, portkeyGuardrail, preopenSkills, preopenToolCallId, prepareStrictToolMenu, promptInjectionGuard, rateLimit, readMemoryFacts, readTraceContinuation, recordOrDeferTraceEvent, redactText, regexGuardrail, regexRule, rememberModelRulePatch, replaceTextContent, replayDeferredTraceEvents, resolveAvailableSkills, resolveAvailableSubagents, resolveInputRetention, resolveMemoryStore, resolveModelRule, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveSummarizationRetention, resolveToolApprovalState, resolveUserQuestionState, responseCache, restoreSnapshot, restoreToolCalls, runSmartAgentEvalHarness, runWithModelAdjustments, scoreItemsByRelevance, searchSkills, seedChildMessages, selectTopIndicesInOrder, sessionMetrics, setTokenCounter, startStreamingSession, summarizeObject, supportsAdaptiveThinking, textFromContent, toMessageUsage, toModelResult, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceContinuationOf, traceSectionsFromMessages, traceSessionToOtlp, traceparentOf, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
20406
22038
  //# sourceMappingURL=index.mjs.map
20407
22039
  //# sourceMappingURL=index.mjs.map