@cognipeer/agent-sdk 0.17.0 → 0.18.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.cjs CHANGED
@@ -8,6 +8,8 @@ var path = require('path');
8
8
  var buffer = require('buffer');
9
9
  var nanoid = require('nanoid');
10
10
  var crypto = require('crypto');
11
+ var zlib = require('zlib');
12
+ var util = require('util');
11
13
  var AjvModule = require('ajv');
12
14
 
13
15
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
@@ -1231,9 +1233,1398 @@ function splitUsage(usage) {
1231
1233
  }
1232
1234
  return { own, subagent, ownCalls: ownEntries.length, subagentCalls: subagentEntries.length, ownEntries, subagentEntries };
1233
1235
  }
1236
+ function cacheWriteTokensOf(raw) {
1237
+ if (!raw || typeof raw !== "object") return void 0;
1238
+ const details = raw.prompt_tokens_details || raw.promptTokensDetails || raw.input_token_details || raw.inputTokenDetails || {};
1239
+ const candidates = [
1240
+ details.cache_write_tokens,
1241
+ details.cacheWriteTokens,
1242
+ details.cache_creation,
1243
+ raw.cache_write_tokens,
1244
+ raw.cacheWriteTokens,
1245
+ raw.cache_creation_input_tokens,
1246
+ raw.cacheCreationInputTokens,
1247
+ raw.cacheWriteInputTokens,
1248
+ raw.cacheWriteInputTokenCount
1249
+ ];
1250
+ for (const value of candidates) {
1251
+ const n = Number(value);
1252
+ if (Number.isFinite(n) && n > 0) return n;
1253
+ }
1254
+ return void 0;
1255
+ }
1234
1256
 
1235
1257
  // src/utils/tracing.ts
1236
1258
  init_content();
1259
+
1260
+ // src/version.ts
1261
+ var SDK_VERSION = "0.18.0";
1262
+
1263
+ // src/utils/otlp/content.ts
1264
+ init_content();
1265
+
1266
+ // src/utils/otlp/semconv.ts
1267
+ var GENAI_SEMCONV_COMMIT = "547934a";
1268
+ var ATTR = {
1269
+ operationName: "gen_ai.operation.name",
1270
+ providerName: "gen_ai.provider.name",
1271
+ requestModel: "gen_ai.request.model",
1272
+ responseModel: "gen_ai.response.model",
1273
+ responseId: "gen_ai.response.id",
1274
+ finishReasons: "gen_ai.response.finish_reasons",
1275
+ requestStream: "gen_ai.request.stream",
1276
+ outputType: "gen_ai.output.type",
1277
+ conversationId: "gen_ai.conversation.id",
1278
+ agentName: "gen_ai.agent.name",
1279
+ agentVersion: "gen_ai.agent.version",
1280
+ toolName: "gen_ai.tool.name",
1281
+ toolCallId: "gen_ai.tool.call.id",
1282
+ toolType: "gen_ai.tool.type",
1283
+ usageInput: "gen_ai.usage.input_tokens",
1284
+ usageOutput: "gen_ai.usage.output_tokens",
1285
+ usageCacheRead: "gen_ai.usage.cache_read.input_tokens",
1286
+ usageCacheWrite: "gen_ai.usage.cache_write.input_tokens",
1287
+ usageReasoning: "gen_ai.usage.reasoning.output_tokens",
1288
+ errorType: "error.type",
1289
+ // Content (opt-in).
1290
+ systemInstructions: "gen_ai.system_instructions",
1291
+ inputMessages: "gen_ai.input.messages",
1292
+ outputMessages: "gen_ai.output.messages",
1293
+ toolDefinitions: "gen_ai.tool.definitions",
1294
+ toolCallArguments: "gen_ai.tool.call.arguments",
1295
+ toolCallResult: "gen_ai.tool.call.result"
1296
+ };
1297
+ var OPERATION = {
1298
+ chat: "chat",
1299
+ executeTool: "execute_tool",
1300
+ invokeAgent: "invoke_agent"
1301
+ };
1302
+ var PROVIDERS = {
1303
+ openai: "openai",
1304
+ chatopenai: "openai",
1305
+ azure: "azure.ai.openai",
1306
+ azureopenai: "azure.ai.openai",
1307
+ azurechatopenai: "azure.ai.openai",
1308
+ azureaiopenai: "azure.ai.openai",
1309
+ azureaiinference: "azure.ai.inference",
1310
+ anthropic: "anthropic",
1311
+ chatanthropic: "anthropic",
1312
+ bedrock: "aws.bedrock",
1313
+ awsbedrock: "aws.bedrock",
1314
+ chatbedrock: "aws.bedrock",
1315
+ chatbedrockconverse: "aws.bedrock",
1316
+ vertex: "gcp.vertex_ai",
1317
+ vertexai: "gcp.vertex_ai",
1318
+ gcpvertexai: "gcp.vertex_ai",
1319
+ chatvertexai: "gcp.vertex_ai",
1320
+ gemini: "gcp.gemini",
1321
+ gcpgemini: "gcp.gemini",
1322
+ chatgooglegenerativeai: "gcp.gemini",
1323
+ // Gemini API or Vertex: the name alone does not say which.
1324
+ google: "gcp.gen_ai",
1325
+ gcpgenai: "gcp.gen_ai",
1326
+ mistral: "mistral",
1327
+ mistralai: "mistral",
1328
+ chatmistralai: "mistral",
1329
+ groq: "groq",
1330
+ chatgroq: "groq",
1331
+ deepseek: "deepseek",
1332
+ chatdeepseek: "deepseek",
1333
+ cohere: "cohere",
1334
+ chatcohere: "cohere",
1335
+ xai: "x_ai",
1336
+ chatxai: "x_ai",
1337
+ perplexity: "perplexity",
1338
+ chatperplexity: "perplexity",
1339
+ watsonx: "ibm.watsonx.ai",
1340
+ ibmwatsonxai: "ibm.watsonx.ai"
1341
+ };
1342
+ function genAiProviderName(hint) {
1343
+ if (!hint) return void 0;
1344
+ const key = hint.toLowerCase().replace(/[^a-z0-9]/g, "");
1345
+ return key ? PROVIDERS[key] : void 0;
1346
+ }
1347
+ function errorTypeOf(error) {
1348
+ if (!error) return "_OTHER";
1349
+ if (typeof error.type === "string" && error.type.length > 0) return error.type;
1350
+ if (typeof error.stack === "string") {
1351
+ const match = /^\s*([A-Za-z_$][\w$.]*)\s*(?::|$)/m.exec(error.stack.split("\n", 1)[0] ?? "");
1352
+ if (match) return match[1];
1353
+ }
1354
+ return "_OTHER";
1355
+ }
1356
+ function genAiUsageOf(event) {
1357
+ const num2 = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
1358
+ const input = num2(event.inputTokens);
1359
+ const output = num2(event.outputTokens);
1360
+ const cacheRead = num2(event.cachedInputTokens);
1361
+ const cacheWrite = num2(event.cacheWriteTokens);
1362
+ const reasoning = num2(event.reasoningTokens);
1363
+ if (input + output + cacheRead + cacheWrite + reasoning + num2(event.totalTokens) === 0) return void 0;
1364
+ const basis = event.usageBasis ?? {};
1365
+ return {
1366
+ input: basis.inputExcludesCache ? input + cacheRead + cacheWrite : input,
1367
+ output: basis.outputExcludesReasoning ? output + reasoning : output,
1368
+ ...cacheRead > 0 ? { cacheRead } : {},
1369
+ ...cacheWrite > 0 ? { cacheWrite } : {},
1370
+ ...reasoning > 0 ? { reasoning } : {}
1371
+ };
1372
+ }
1373
+
1374
+ // src/utils/otlp/content.ts
1375
+ var CAPTURE = Symbol.for("cognipeer.agent-sdk.traceCapture");
1376
+ var DEFAULTS = {
1377
+ maxStringChars: 4096,
1378
+ maxMessages: 32,
1379
+ maxAttributeBytes: 32768
1380
+ };
1381
+ var FIELDS = ["system", "input", "output", "tools", "toolArgs", "toolResults", "sections"];
1382
+ function resolveContentOptions(content) {
1383
+ const given = typeof content === "object" && content !== null ? content : {};
1384
+ const enabled = typeof content === "boolean" ? content : given.enabled === true;
1385
+ const positive = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;
1386
+ return {
1387
+ enabled,
1388
+ include: Array.isArray(given.include) ? given.include.filter((field) => FIELDS.includes(field)) : [...FIELDS],
1389
+ maxStringChars: positive(given.maxStringChars, DEFAULTS.maxStringChars),
1390
+ maxMessages: positive(given.maxMessages, DEFAULTS.maxMessages),
1391
+ maxAttributeBytes: positive(given.maxAttributeBytes, DEFAULTS.maxAttributeBytes),
1392
+ redact: typeof given.redact === "function" ? given.redact : void 0,
1393
+ encoding: given.encoding === "structured" ? "structured" : "json"
1394
+ };
1395
+ }
1396
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1397
+ function plain(value) {
1398
+ if (value === void 0) return void 0;
1399
+ try {
1400
+ const text = JSON.stringify(value);
1401
+ return text === void 0 ? void 0 : JSON.parse(text);
1402
+ } catch {
1403
+ return void 0;
1404
+ }
1405
+ }
1406
+ var TRUNCATED_MARKER = /\.\.\.\[truncated (\d+) chars\]$/;
1407
+ function truncateText(text, max) {
1408
+ const earlier = TRUNCATED_MARKER.exec(text);
1409
+ const body = earlier ? text.slice(0, earlier.index) : text;
1410
+ if (body.length <= max) return text;
1411
+ const lost = body.length - max + (earlier ? Number(earlier[1]) : 0);
1412
+ return `${body.slice(0, max)}...[truncated ${lost} chars]`;
1413
+ }
1414
+ function capStrings(value, max) {
1415
+ if (typeof value === "string") return truncateText(value, max);
1416
+ if (Array.isArray(value)) return value.map((item) => capStrings(item, max));
1417
+ if (isRecord2(value)) {
1418
+ const out = {};
1419
+ for (const [key, item] of Object.entries(value)) out[key] = capStrings(item, max);
1420
+ return out;
1421
+ }
1422
+ return value;
1423
+ }
1424
+ function asObject(value) {
1425
+ let parsed = value;
1426
+ if (typeof value === "string") {
1427
+ try {
1428
+ parsed = JSON.parse(value);
1429
+ } catch {
1430
+ parsed = value;
1431
+ }
1432
+ }
1433
+ const copy = plain(parsed);
1434
+ if (copy === void 0) return void 0;
1435
+ return isRecord2(copy) ? copy : { value: copy };
1436
+ }
1437
+ var REASONING_PART_TYPES = /* @__PURE__ */ new Set(["thinking", "redacted_thinking", "reasoning", "reasoning_content"]);
1438
+ function textOf(content) {
1439
+ if (content == null) return "";
1440
+ if (typeof content === "string") return content;
1441
+ if (!Array.isArray(content)) return contentPartToText(content, () => "");
1442
+ return content.filter((part) => !(isRecord2(part) && REASONING_PART_TYPES.has(String(part.type)))).map((part) => contentPartToText(part, () => "")).filter((text) => text.length > 0).join("\n");
1443
+ }
1444
+ function toolCallPartsOf(message) {
1445
+ const calls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
1446
+ const parts = [];
1447
+ for (const call of calls) {
1448
+ if (!isRecord2(call)) continue;
1449
+ const name = call.name ?? call.function?.name;
1450
+ if (typeof name !== "string" || !name) continue;
1451
+ const args = call.args ?? call.arguments ?? call.function?.arguments;
1452
+ const coerced = asObject(args ?? {});
1453
+ const id = typeof call.id === "string" && call.id && !call.idSynthesized ? call.id : void 0;
1454
+ parts.push({ type: "tool_call", ...id ? { id } : {}, name, arguments: coerced ?? {} });
1455
+ }
1456
+ return parts;
1457
+ }
1458
+ function messageOf(raw) {
1459
+ if (!isRecord2(raw)) return void 0;
1460
+ const role = typeof raw.role === "string" ? raw.role : "user";
1461
+ const parts = [];
1462
+ if (role === "tool") {
1463
+ const text2 = textOf(raw.content);
1464
+ const parsed = (() => {
1465
+ try {
1466
+ return JSON.parse(text2);
1467
+ } catch {
1468
+ return text2;
1469
+ }
1470
+ })();
1471
+ parts.push({
1472
+ type: "tool_call_response",
1473
+ ...typeof raw.tool_call_id === "string" && raw.tool_call_id ? { id: raw.tool_call_id } : {},
1474
+ response: plain(parsed) ?? text2
1475
+ });
1476
+ return { role, parts, ...typeof raw.name === "string" && raw.name ? { name: raw.name } : {} };
1477
+ }
1478
+ const text = textOf(raw.content);
1479
+ if (text) parts.push({ type: "text", content: text });
1480
+ if (role === "assistant") parts.push(...toolCallPartsOf(raw));
1481
+ if (parts.length === 0 && role !== "assistant") parts.push({ type: "text", content: "" });
1482
+ return { role, parts };
1483
+ }
1484
+ function buildCapturedContent(source, limits) {
1485
+ const out = {};
1486
+ if (Array.isArray(source.input)) {
1487
+ const system = [];
1488
+ const messages = [];
1489
+ for (const raw of source.input) {
1490
+ const message = messageOf(raw);
1491
+ if (!message) continue;
1492
+ if (message.role === "system") {
1493
+ const content = message.parts.map((part) => part.type === "text" ? part.content : "").join("\n");
1494
+ if (content) system.push({ type: "text", content });
1495
+ } else {
1496
+ messages.push(message);
1497
+ }
1498
+ }
1499
+ if (system.length > 0) out.system = capStrings(system, limits.maxStringChars);
1500
+ const recent = messages.slice(-limits.maxMessages);
1501
+ out.input = capStrings(recent, limits.maxStringChars);
1502
+ }
1503
+ if (source.output !== void 0 && source.output !== null) {
1504
+ const message = messageOf({ ...isRecord2(source.output) ? source.output : { content: String(source.output) }, role: "assistant" });
1505
+ if (message) out.output = capStrings(message, limits.maxStringChars);
1506
+ }
1507
+ if (Array.isArray(source.toolDefinitions) && source.toolDefinitions.length > 0) {
1508
+ out.tools = capStrings(
1509
+ source.toolDefinitions.filter((tool) => tool && typeof tool.name === "string").map((tool) => ({
1510
+ type: "function",
1511
+ name: tool.name,
1512
+ ...tool.description ? { description: tool.description } : {},
1513
+ ...tool.parameters !== void 0 ? { parameters: plain(tool.parameters) } : {}
1514
+ })),
1515
+ limits.maxStringChars
1516
+ );
1517
+ }
1518
+ if (source.toolArguments !== void 0) {
1519
+ const args = asObject(source.toolArguments);
1520
+ if (args !== void 0) out.toolArgs = capStrings(args, limits.maxStringChars);
1521
+ }
1522
+ if (source.hasToolResult || source.toolResult !== void 0) {
1523
+ const result = asObject(source.toolResult);
1524
+ if (result !== void 0) out.toolResults = capStrings(result, limits.maxStringChars);
1525
+ }
1526
+ return out;
1527
+ }
1528
+ function capturedContentOf(event) {
1529
+ return event?.[CAPTURE];
1530
+ }
1531
+ function attachCapturedContent(record, content) {
1532
+ Object.defineProperty(record, CAPTURE, { value: content, enumerable: false, configurable: true, writable: true });
1533
+ }
1534
+ var SEPARATE_SYSTEM = /* @__PURE__ */ new Set(["anthropic", "aws.bedrock", "gcp.vertex_ai", "gcp.gemini"]);
1535
+ function toAnyValue(value) {
1536
+ if (value === null || value === void 0) return void 0;
1537
+ if (typeof value === "string") return { stringValue: value };
1538
+ if (typeof value === "boolean") return { boolValue: value };
1539
+ if (typeof value === "number") {
1540
+ if (!Number.isFinite(value)) return void 0;
1541
+ return Number.isInteger(value) && Number.isSafeInteger(value) ? { intValue: String(value) } : { doubleValue: value };
1542
+ }
1543
+ if (Array.isArray(value)) {
1544
+ return { arrayValue: { values: value.map((item) => toAnyValue(item) ?? { stringValue: "" }) } };
1545
+ }
1546
+ if (isRecord2(value)) {
1547
+ const values = [];
1548
+ for (const [key, item] of Object.entries(value)) {
1549
+ const any = toAnyValue(item);
1550
+ if (any) values.push({ key, value: any });
1551
+ }
1552
+ return { kvlistValue: { values } };
1553
+ }
1554
+ return void 0;
1555
+ }
1556
+ var byteLength = (text) => buffer.Buffer.byteLength(text, "utf8");
1557
+ function render(value, field, options, info) {
1558
+ let working = plain(value);
1559
+ if (working === void 0) return void 0;
1560
+ if (options.redact) {
1561
+ try {
1562
+ working = options.redact(plain(working), { field, ...info });
1563
+ } catch {
1564
+ return void 0;
1565
+ }
1566
+ working = plain(working);
1567
+ if (working === void 0 || working === null) return void 0;
1568
+ }
1569
+ working = capStrings(working, options.maxStringChars);
1570
+ if ((field === "input" || field === "system" || field === "sections") && Array.isArray(working) && working.length > options.maxMessages) {
1571
+ working = working.slice(-options.maxMessages);
1572
+ }
1573
+ let text = JSON.stringify(working);
1574
+ if (text === void 0) return void 0;
1575
+ if (byteLength(text) > options.maxAttributeBytes) {
1576
+ if (field === "input" && Array.isArray(working)) {
1577
+ const messages = [...working];
1578
+ while (messages.length > 1 && byteLength(JSON.stringify(messages)) > options.maxAttributeBytes) messages.shift();
1579
+ working = messages;
1580
+ text = JSON.stringify(working);
1581
+ }
1582
+ if (byteLength(text) > options.maxAttributeBytes) {
1583
+ working = { truncated: true };
1584
+ text = JSON.stringify(working);
1585
+ }
1586
+ }
1587
+ return options.encoding === "structured" ? toAnyValue(working) : { stringValue: text };
1588
+ }
1589
+ function contentAttributes(kind, event, provider, options) {
1590
+ if (!options?.enabled) return [];
1591
+ const captured = capturedContentOf(event);
1592
+ if (!captured) return [];
1593
+ const include = new Set(options.include);
1594
+ const info = {
1595
+ eventType: event.type,
1596
+ ...event.spanId ? { spanId: event.spanId } : {},
1597
+ ...kind === "execute_tool" && event.actor?.name ? { toolName: event.actor.name } : {},
1598
+ ...event.model ? { model: event.model } : {}
1599
+ };
1600
+ const attrs = [];
1601
+ const add = (key, value) => {
1602
+ if (value) attrs.push({ key, value });
1603
+ };
1604
+ if (kind === "chat") {
1605
+ const separate = provider !== void 0 && SEPARATE_SYSTEM.has(provider);
1606
+ const system = captured.system ?? [];
1607
+ if (separate) {
1608
+ if (include.has("system") && system.length > 0) add(ATTR.systemInstructions, render(system, "system", options, info));
1609
+ if (include.has("input") && captured.input) add(ATTR.inputMessages, render(captured.input, "input", options, info));
1610
+ } else if (include.has("input") && (captured.input || system.length > 0)) {
1611
+ const messages = captured.input ?? [];
1612
+ const capped = messages.slice(-options.maxMessages);
1613
+ const withSystem = system.length > 0 ? [{ role: "system", parts: system }, ...capped] : capped;
1614
+ add(ATTR.inputMessages, render(withSystem, "input", { ...options, maxMessages: options.maxMessages + 1 }, info));
1615
+ }
1616
+ if (include.has("output") && captured.output) {
1617
+ const reason = event.rawFinishReason ?? event.finishReason;
1618
+ const finish = reason === "tool_calls" ? "tool_call" : reason;
1619
+ add(ATTR.outputMessages, render([{ ...captured.output, ...finish ? { finish_reason: finish } : {} }], "output", options, info));
1620
+ }
1621
+ if (include.has("tools") && captured.tools) add(ATTR.toolDefinitions, render(captured.tools, "tools", options, info));
1622
+ } else {
1623
+ if (include.has("toolArgs") && captured.toolArgs !== void 0) add(ATTR.toolCallArguments, render(captured.toolArgs, "toolArgs", options, info));
1624
+ if (include.has("toolResults") && captured.toolResults !== void 0) add(ATTR.toolCallResult, render(captured.toolResults, "toolResults", options, info));
1625
+ }
1626
+ return attrs;
1627
+ }
1628
+ function sectionsAttribute(sections, event, options) {
1629
+ if (!sections || sections.length === 0) return void 0;
1630
+ const identity2 = sections.filter((section) => section.identity === true);
1631
+ const payload = sections.filter((section) => section.identity !== true);
1632
+ let kept = [];
1633
+ if (options?.enabled && options.include.includes("sections") && payload.length > 0) {
1634
+ kept = redactedSections(payload, options, event);
1635
+ }
1636
+ const max = options?.maxAttributeBytes ?? DEFAULTS.maxAttributeBytes;
1637
+ const encode = (list) => {
1638
+ try {
1639
+ return JSON.stringify(list);
1640
+ } catch {
1641
+ return void 0;
1642
+ }
1643
+ };
1644
+ let text = encode([...identity2, ...kept]);
1645
+ while (text !== void 0 && kept.length > 0 && byteLength(text) > max) {
1646
+ kept.shift();
1647
+ text = encode([...identity2, ...kept]);
1648
+ }
1649
+ if (text === void 0) {
1650
+ text = encode(identity2);
1651
+ }
1652
+ if (text === void 0 || text === "[]") return void 0;
1653
+ return { key: "cognipeer.sections", value: { stringValue: text } };
1654
+ }
1655
+ function redactedSections(payload, options, event) {
1656
+ let working = plain(payload);
1657
+ if (working === void 0) return [];
1658
+ if (options.redact) {
1659
+ try {
1660
+ working = plain(options.redact(plain(working), {
1661
+ field: "sections",
1662
+ eventType: event.type,
1663
+ ...event.spanId ? { spanId: event.spanId } : {},
1664
+ ...event.model ? { model: event.model } : {}
1665
+ }));
1666
+ } catch {
1667
+ return [];
1668
+ }
1669
+ if (!Array.isArray(working)) return [];
1670
+ }
1671
+ const capped = capStrings(working, options.maxStringChars);
1672
+ return Array.isArray(capped) ? capped.slice(-options.maxMessages) : [];
1673
+ }
1674
+
1675
+ // src/utils/otlp/convert.ts
1676
+ var SCOPE_NAME = "cognipeer-agent-sdk";
1677
+ var SPAN_KIND_INTERNAL = 1;
1678
+ var SPAN_KIND_CLIENT = 3;
1679
+ var FLAG_HAS_PARENT = 256;
1680
+ var FLAG_REMOTE_PARENT = 512;
1681
+ var MAX_STATUS_MESSAGE = 1024;
1682
+ var str = (key, value) => value != null && value !== "" ? { key, value: { stringValue: value } } : null;
1683
+ var strAllowEmpty = (key, value) => value != null ? { key, value: { stringValue: value } } : null;
1684
+ var int = (key, value) => typeof value === "number" && Number.isFinite(value) ? { key, value: { intValue: String(Math.trunc(value)) } } : null;
1685
+ var dbl = (key, value) => typeof value === "number" && Number.isFinite(value) ? { key, value: { doubleValue: value } } : null;
1686
+ var bool = (key, value) => typeof value === "boolean" ? { key, value: { boolValue: value } } : null;
1687
+ var strArray = (key, values) => ({
1688
+ key,
1689
+ value: { arrayValue: { values: values.map((value) => ({ stringValue: value })) } }
1690
+ });
1691
+ var compact = (list) => list.filter((entry) => Boolean(entry));
1692
+ function msToNs(ms) {
1693
+ const whole = Math.floor(ms);
1694
+ return BigInt(whole) * 1000000n + BigInt(Math.round((ms - whole) * 1e6));
1695
+ }
1696
+ function parseMs(iso) {
1697
+ if (!iso) return void 0;
1698
+ const value = Date.parse(iso);
1699
+ return Number.isNaN(value) ? void 0 : value;
1700
+ }
1701
+ function durationNs(durationMs) {
1702
+ return typeof durationMs === "number" && Number.isFinite(durationMs) && durationMs > 0 ? msToNs(durationMs) : 0n;
1703
+ }
1704
+ function classify(event) {
1705
+ if (event.type === "ai_call" || event.type === "summarization") {
1706
+ if (event.skipReason === "cancelled") return "chat";
1707
+ if (event.skipReason || event.status === "skipped") return "plain";
1708
+ return "chat";
1709
+ }
1710
+ if (event.type === "tool_call") {
1711
+ const source = event.debug?.shortCircuitSource;
1712
+ if (event.skipReason || event.status === "skipped" || source === "cache" || source === "plugin") return "plain";
1713
+ if (event.status === "pending") return "plain";
1714
+ return "execute_tool";
1715
+ }
1716
+ if (event.type === "span" && event.actor?.role === "subagent") return "invoke_agent";
1717
+ return "plain";
1718
+ }
1719
+ var knownModel = (model) => model && model !== "unknown-model" && model !== "unknown_model" ? model : void 0;
1720
+ function toolNameOf(event) {
1721
+ if (event.actor?.name) return event.actor.name;
1722
+ const label = event.label.replace(/\s#\d+$/, "");
1723
+ const dash = label.indexOf(" - ");
1724
+ return dash >= 0 ? label.slice(dash + 3) : void 0;
1725
+ }
1726
+ var stripSequence = (label) => label.replace(/\s#\d+$/, "");
1727
+ function cappedMessage(message) {
1728
+ const text = message && message.length > 0 ? message : "Unknown error";
1729
+ return text.length > MAX_STATUS_MESSAGE ? text.slice(0, MAX_STATUS_MESSAGE) : text;
1730
+ }
1731
+ function exceptionEvent(timeNs, error) {
1732
+ return {
1733
+ timeUnixNano: timeNs.toString(),
1734
+ name: "exception",
1735
+ attributes: compact([
1736
+ str("exception.type", errorTypeOf(error)),
1737
+ strAllowEmpty("exception.message", error.message ?? "Unknown error"),
1738
+ str("exception.stacktrace", error.stack)
1739
+ ])
1740
+ };
1741
+ }
1742
+ function sessionToOtlp(file, options) {
1743
+ const useCognipeer = options.semconv !== "gen_ai";
1744
+ const useGenAi = options.semconv !== "cognipeer";
1745
+ const traceId = file.traceId || generateTraceId();
1746
+ const rootSpanId = file.rootSpanId || generateSpanId();
1747
+ const parent = options.parent;
1748
+ const traceState = parent?.traceState || void 0;
1749
+ const traceFlags = (typeof parent?.flags === "number" ? parent.flags : 1) & 255;
1750
+ const flags = traceFlags | FLAG_HAS_PARENT;
1751
+ const rootFlags = parent?.remote ? flags | FLAG_REMOTE_PARENT : flags;
1752
+ const agentName = file.agent?.name;
1753
+ const everyEvent = file.events;
1754
+ const exportedEvents = foldSupersededSpans(everyEvent).filter(
1755
+ (event) => options.terminal || !(event.type === "span" && event.status === "pending")
1756
+ );
1757
+ const startMs = parseMs(file.startedAt);
1758
+ const nodes = exportedEvents.map((event) => {
1759
+ const endMs = parseMs(event.timestamp) ?? startMs ?? Date.now();
1760
+ const endNs = msToNs(endMs);
1761
+ let startNs = endNs - durationNs(event.durationMs);
1762
+ if (startNs < 0n) startNs = 0n;
1763
+ return {
1764
+ event,
1765
+ spanId: event.spanId || generateSpanId(),
1766
+ parentId: event.parentSpanId || rootSpanId,
1767
+ startNs,
1768
+ endNs
1769
+ };
1770
+ });
1771
+ const childrenOf = /* @__PURE__ */ new Map();
1772
+ for (const node of nodes) {
1773
+ const list = childrenOf.get(node.parentId);
1774
+ if (list) list.push(node);
1775
+ else childrenOf.set(node.parentId, [node]);
1776
+ }
1777
+ const settled = /* @__PURE__ */ new Set();
1778
+ const inProgress = /* @__PURE__ */ new Set();
1779
+ const widen = (node) => {
1780
+ if (settled.has(node) || inProgress.has(node)) return;
1781
+ inProgress.add(node);
1782
+ for (const child of childrenOf.get(node.spanId) ?? []) {
1783
+ if (child === node) continue;
1784
+ widen(child);
1785
+ if (child.startNs < node.startNs) node.startNs = child.startNs;
1786
+ if (child.endNs > node.endNs) node.endNs = child.endNs;
1787
+ }
1788
+ inProgress.delete(node);
1789
+ settled.add(node);
1790
+ };
1791
+ for (const node of nodes) widen(node);
1792
+ const byId = /* @__PURE__ */ new Map();
1793
+ for (const event of everyEvent) if (event.spanId) byId.set(event.spanId, event);
1794
+ const agentOf = (event) => {
1795
+ let cursor = event;
1796
+ for (let hops = 0; cursor && hops < 64; hops++) {
1797
+ if (cursor !== event && cursor.type === "span" && cursor.actor?.role === "subagent") return cursor.actor.name;
1798
+ cursor = cursor.parentSpanId ? byId.get(cursor.parentSpanId) : void 0;
1799
+ }
1800
+ return agentName;
1801
+ };
1802
+ const spans = [];
1803
+ const sessionErrors = (file.errors ?? []).filter((error) => error.eventId === "session");
1804
+ if (options.terminal) {
1805
+ const earliestChild = nodes.reduce(
1806
+ (earliest, node) => earliest === void 0 || node.startNs < earliest ? node.startNs : earliest,
1807
+ void 0
1808
+ );
1809
+ let rootStart = startMs !== void 0 ? msToNs(startMs) : earliestChild ?? msToNs(Date.now());
1810
+ let rootEnd = msToNs(parseMs(file.endedAt) ?? (startMs !== void 0 ? startMs + (file.durationMs ?? 0) : Date.now()));
1811
+ for (const node of childrenOf.get(rootSpanId) ?? []) {
1812
+ if (node.startNs < rootStart) rootStart = node.startNs;
1813
+ if (node.endNs > rootEnd) rootEnd = node.endNs;
1814
+ }
1815
+ if (rootEnd < rootStart) rootEnd = rootStart;
1816
+ const rootName = useGenAi ? agentName ? `${OPERATION.invokeAgent} ${agentName}` : OPERATION.invokeAgent : `agent_session: ${agentName || "agent"}`;
1817
+ const summary = file.summary;
1818
+ const cumulativeEvents = summary?.eventCounts ? Object.values(summary.eventCounts).reduce((total, count) => total + (Number(count) || 0), 0) : file.events.length;
1819
+ const attributes = [];
1820
+ if (useCognipeer) {
1821
+ attributes.push(
1822
+ ...compact([
1823
+ strAllowEmpty("cognipeer.session.status", options.cancelled ? "partial" : file.status),
1824
+ dbl("cognipeer.session.duration_ms", file.durationMs),
1825
+ int("cognipeer.session.total_input_tokens", summary?.totalInputTokens),
1826
+ int("cognipeer.session.total_output_tokens", summary?.totalOutputTokens),
1827
+ int("cognipeer.session.total_cached_input_tokens", summary?.totalCachedInputTokens),
1828
+ int("cognipeer.session.total_bytes_in", summary?.totalBytesIn),
1829
+ int("cognipeer.session.total_bytes_out", summary?.totalBytesOut),
1830
+ int("cognipeer.session.event_count", cumulativeEvents)
1831
+ ])
1832
+ );
1833
+ for (const [key, count] of Object.entries(summary?.eventCounts ?? {})) {
1834
+ attributes.push({ key: `cognipeer.session.event_count.${key}`, value: { intValue: String(count) } });
1835
+ }
1836
+ }
1837
+ if (useGenAi) {
1838
+ attributes.push(
1839
+ ...compact([
1840
+ str(ATTR.operationName, OPERATION.invokeAgent),
1841
+ str(ATTR.agentName, agentName),
1842
+ str(ATTR.agentVersion, file.agent?.version),
1843
+ str(ATTR.requestModel, knownModel(file.agent?.model)),
1844
+ str(ATTR.conversationId, file.threadId)
1845
+ ])
1846
+ );
1847
+ }
1848
+ const root = {
1849
+ traceId,
1850
+ spanId: rootSpanId,
1851
+ parentSpanId: parent?.spanId ?? "",
1852
+ ...traceState ? { traceState } : {},
1853
+ flags: rootFlags,
1854
+ name: rootName,
1855
+ kind: SPAN_KIND_INTERNAL,
1856
+ startTimeUnixNano: rootStart.toString(),
1857
+ endTimeUnixNano: rootEnd.toString(),
1858
+ attributes,
1859
+ status: { code: 0 }
1860
+ };
1861
+ if (sessionErrors.length > 0) {
1862
+ root.status = {
1863
+ code: 2,
1864
+ message: cappedMessage(sessionErrors.map((error) => error.message).join("; "))
1865
+ };
1866
+ if (useGenAi) root.attributes.push({ key: ATTR.errorType, value: { stringValue: errorTypeOf({ type: sessionErrors[0].errorName, stack: sessionErrors[0].stack }) } });
1867
+ root.events = sessionErrors.map((error) => {
1868
+ const at = parseMs(error.timestamp);
1869
+ return exceptionEvent(at !== void 0 ? msToNs(at) : rootEnd, {
1870
+ message: error.message,
1871
+ stack: error.stack,
1872
+ type: error.errorName
1873
+ });
1874
+ });
1875
+ }
1876
+ spans.push(root);
1877
+ }
1878
+ for (const node of nodes) {
1879
+ const event = node.event;
1880
+ const kind = classify(event);
1881
+ const failed = event.status === "error";
1882
+ const cancelledChat = kind === "chat" && event.skipReason === "cancelled";
1883
+ const attributes = [];
1884
+ if (useCognipeer) {
1885
+ attributes.push(
1886
+ ...compact([
1887
+ strAllowEmpty("cognipeer.event.type", event.type),
1888
+ strAllowEmpty("cognipeer.event.label", event.label),
1889
+ int("cognipeer.event.sequence", event.sequence),
1890
+ strAllowEmpty("cognipeer.actor.scope", event.actor?.scope),
1891
+ strAllowEmpty("cognipeer.actor.name", event.actor?.name),
1892
+ strAllowEmpty("cognipeer.actor.role", event.actor?.role),
1893
+ strAllowEmpty("cognipeer.model", event.model),
1894
+ int("cognipeer.tokens.reasoning", event.reasoningTokens),
1895
+ strAllowEmpty("cognipeer.finish_reason", event.finishReason),
1896
+ strAllowEmpty("cognipeer.provider", event.provider),
1897
+ strAllowEmpty("cognipeer.tool.details", event.toolDetails ? JSON.stringify(event.toolDetails) : void 0),
1898
+ int("cognipeer.tokens.input", event.inputTokens),
1899
+ int("cognipeer.tokens.output", event.outputTokens),
1900
+ int("cognipeer.tokens.total", event.totalTokens),
1901
+ int("cognipeer.tokens.cached_input", event.cachedInputTokens),
1902
+ int("cognipeer.bytes.request", event.requestBytes),
1903
+ int("cognipeer.bytes.response", event.responseBytes),
1904
+ strAllowEmpty("cognipeer.tool.execution_id", event.toolExecutionId),
1905
+ strAllowEmpty("cognipeer.retry_of", event.retryOf),
1906
+ strAllowEmpty("cognipeer.event.id", event.id)
1907
+ ])
1908
+ );
1909
+ const sectionsAttr = sectionsAttribute(event.data?.sections, event, options.content);
1910
+ if (sectionsAttr) attributes.push(sectionsAttr);
1911
+ attributes.push({ key: "cognipeer.event.status", value: { stringValue: event.status } });
1912
+ }
1913
+ let name = event.label || event.type;
1914
+ let spanKind = SPAN_KIND_INTERNAL;
1915
+ if (kind === "chat") spanKind = SPAN_KIND_CLIENT;
1916
+ if (useGenAi) {
1917
+ const conversation = str(ATTR.conversationId, file.threadId);
1918
+ if (kind === "chat") {
1919
+ const model = knownModel(event.model);
1920
+ name = model ? `${OPERATION.chat} ${model}` : OPERATION.chat;
1921
+ attributes.push(
1922
+ ...compact([
1923
+ str(ATTR.operationName, OPERATION.chat),
1924
+ str(ATTR.providerName, genAiProviderName(event.provider)),
1925
+ str(ATTR.requestModel, model),
1926
+ str(ATTR.responseModel, event.responseModel),
1927
+ str(ATTR.responseId, event.responseId),
1928
+ bool(ATTR.requestStream, event.streaming),
1929
+ str(ATTR.outputType, event.outputType)
1930
+ ])
1931
+ );
1932
+ if (failed || cancelledChat) {
1933
+ attributes.push(strArray(ATTR.finishReasons, ["error"]));
1934
+ } else {
1935
+ const reason = event.rawFinishReason ?? event.finishReason;
1936
+ if (reason) attributes.push(strArray(ATTR.finishReasons, [reason]));
1937
+ }
1938
+ const usageAllowed = !failed && !cancelledChat && (event.type !== "summarization" || event.debug?.usageFromModel === true);
1939
+ const usage = usageAllowed ? genAiUsageOf(event) : void 0;
1940
+ if (usage) {
1941
+ attributes.push(
1942
+ ...compact([
1943
+ int(ATTR.usageInput, usage.input),
1944
+ int(ATTR.usageOutput, usage.output),
1945
+ int(ATTR.usageCacheRead, usage.cacheRead),
1946
+ int(ATTR.usageCacheWrite, usage.cacheWrite),
1947
+ int(ATTR.usageReasoning, usage.reasoning)
1948
+ ])
1949
+ );
1950
+ }
1951
+ if (conversation) attributes.push(conversation);
1952
+ attributes.push(...contentAttributes("chat", event, genAiProviderName(event.provider), options.content));
1953
+ } else if (kind === "execute_tool") {
1954
+ const tool = toolNameOf(event);
1955
+ name = tool ? `${OPERATION.executeTool} ${tool}` : OPERATION.executeTool;
1956
+ attributes.push(
1957
+ ...compact([
1958
+ str(ATTR.operationName, OPERATION.executeTool),
1959
+ str(ATTR.toolName, tool),
1960
+ str(ATTR.toolCallId, event.toolCallId),
1961
+ str(ATTR.toolType, "function"),
1962
+ str(ATTR.agentName, agentOf(event)),
1963
+ conversation
1964
+ ])
1965
+ );
1966
+ attributes.push(...contentAttributes("execute_tool", event, void 0, options.content));
1967
+ } else if (kind === "invoke_agent") {
1968
+ const child = event.actor?.name;
1969
+ name = child ? `${OPERATION.invokeAgent} ${child}` : OPERATION.invokeAgent;
1970
+ attributes.push(...compact([str(ATTR.operationName, OPERATION.invokeAgent), str(ATTR.agentName, child), conversation]));
1971
+ } else {
1972
+ name = stripSequence(name);
1973
+ }
1974
+ }
1975
+ const span = {
1976
+ traceId: event.traceId || traceId,
1977
+ spanId: node.spanId,
1978
+ parentSpanId: node.parentId,
1979
+ ...traceState ? { traceState } : {},
1980
+ flags,
1981
+ name,
1982
+ kind: spanKind,
1983
+ startTimeUnixNano: node.startNs.toString(),
1984
+ endTimeUnixNano: node.endNs.toString(),
1985
+ attributes,
1986
+ status: { code: 0 }
1987
+ };
1988
+ if (failed) {
1989
+ const error = event.error ?? { message: "Unknown error" };
1990
+ span.status = { code: 2, message: cappedMessage(error.message) };
1991
+ if (useGenAi) attributes.push({ key: ATTR.errorType, value: { stringValue: errorTypeOf(error) } });
1992
+ span.events = [exceptionEvent(node.endNs, error)];
1993
+ }
1994
+ spans.push(span);
1995
+ }
1996
+ return {
1997
+ resourceSpans: [
1998
+ {
1999
+ resource: { attributes: resourceAttributesOf(file, options, useCognipeer) },
2000
+ scopeSpans: [{ scope: { name: SCOPE_NAME, version: SDK_VERSION }, spans }]
2001
+ }
2002
+ ]
2003
+ };
2004
+ }
2005
+ function resourceAttributesOf(file, options, useCognipeer) {
2006
+ const custom = options.resourceAttributes ?? {};
2007
+ const serviceName = options.serviceName || custom["service.name"] || file.agent?.name || "cognipeer-agent";
2008
+ const attributes = compact([
2009
+ str("service.name", serviceName),
2010
+ str("service.version", file.agent?.version)
2011
+ ]);
2012
+ if (useCognipeer) {
2013
+ attributes.push(
2014
+ ...compact([
2015
+ str("cognipeer.session.id", file.sessionId),
2016
+ str("cognipeer.thread.id", file.threadId),
2017
+ str("cognipeer.agent.model", file.agent?.model),
2018
+ str("cognipeer.agent.provider", file.agent?.provider),
2019
+ ...Object.entries(file.metadata ?? {}).map(([key, value]) => str(`cognipeer.metadata.${key}`, value))
2020
+ ])
2021
+ );
2022
+ }
2023
+ attributes.push(
2024
+ ...compact([
2025
+ str("telemetry.sdk.name", SCOPE_NAME),
2026
+ str("telemetry.sdk.language", "nodejs"),
2027
+ str("telemetry.sdk.version", SDK_VERSION)
2028
+ ])
2029
+ );
2030
+ for (const [key, value] of Object.entries(custom)) {
2031
+ if (key === "service.name") continue;
2032
+ const index = attributes.findIndex((attr) => attr.key === key);
2033
+ const entry = str(key, value);
2034
+ if (!entry) continue;
2035
+ if (index >= 0) attributes[index] = entry;
2036
+ else attributes.push(entry);
2037
+ }
2038
+ return attributes;
2039
+ }
2040
+ function countSpans(request) {
2041
+ let total = 0;
2042
+ for (const rs of request.resourceSpans) for (const ss of rs.scopeSpans) total += ss.spans.length;
2043
+ return total;
2044
+ }
2045
+
2046
+ // src/utils/otlp/env.ts
2047
+ var warned = /* @__PURE__ */ new Set();
2048
+ function warnOnce(message) {
2049
+ if (warned.has(message)) return;
2050
+ warned.add(message);
2051
+ if (typeof console !== "undefined" && typeof console.warn === "function") console.warn(message);
2052
+ }
2053
+ function pick(env, ...names) {
2054
+ for (const name of names) {
2055
+ const value = env[name];
2056
+ if (typeof value === "string" && value.trim().length > 0) return value.trim();
2057
+ }
2058
+ return void 0;
2059
+ }
2060
+ function decode(value) {
2061
+ try {
2062
+ return decodeURIComponent(value);
2063
+ } catch {
2064
+ return value;
2065
+ }
2066
+ }
2067
+ function parseKeyValueList(raw) {
2068
+ const out = {};
2069
+ if (!raw) return out;
2070
+ for (const part of raw.split(",")) {
2071
+ const index = part.indexOf("=");
2072
+ if (index <= 0) continue;
2073
+ const key = part.slice(0, index).trim();
2074
+ if (!key) continue;
2075
+ out[key] = decode(part.slice(index + 1).trim());
2076
+ }
2077
+ return out;
2078
+ }
2079
+ function tracesEndpointFrom(base) {
2080
+ return `${base.replace(/\/+$/, "")}/v1/traces`;
2081
+ }
2082
+ function protocolFrom(raw, fallback) {
2083
+ if (!raw) return fallback;
2084
+ const value = raw.toLowerCase();
2085
+ if (value === "http/protobuf" || value === "http/json") return value;
2086
+ warnOnce(
2087
+ 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}.`
2088
+ );
2089
+ return fallback;
2090
+ }
2091
+ function resolveOtlpEnv(env, explicit) {
2092
+ const explicitEndpoint = typeof explicit.endpoint === "string" ? explicit.endpoint.trim() : "";
2093
+ const envDriven = explicitEndpoint.length === 0;
2094
+ const resourceAttributes = parseKeyValueList(pick(env, "OTEL_RESOURCE_ATTRIBUTES"));
2095
+ const serviceName = pick(env, "OTEL_SERVICE_NAME");
2096
+ if (!envDriven) {
2097
+ return {
2098
+ envDriven,
2099
+ endpoint: explicitEndpoint,
2100
+ headers: { ...explicit.headers ?? {} },
2101
+ protocol: explicit.protocol ?? "http/json",
2102
+ compression: explicit.compression ?? "none",
2103
+ timeoutMs: explicit.timeoutMs,
2104
+ serviceName,
2105
+ resourceAttributes,
2106
+ disabled: false
2107
+ };
2108
+ }
2109
+ const tracesEndpoint = pick(env, "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT");
2110
+ const baseEndpoint = pick(env, "OTEL_EXPORTER_OTLP_ENDPOINT");
2111
+ const endpoint = tracesEndpoint ?? (baseEndpoint ? tracesEndpointFrom(baseEndpoint) : void 0);
2112
+ const envHeaders = {
2113
+ ...parseKeyValueList(pick(env, "OTEL_EXPORTER_OTLP_HEADERS")),
2114
+ ...parseKeyValueList(pick(env, "OTEL_EXPORTER_OTLP_TRACES_HEADERS"))
2115
+ };
2116
+ const timeoutRaw = pick(env, "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT", "OTEL_EXPORTER_OTLP_TIMEOUT");
2117
+ const timeout = timeoutRaw !== void 0 ? Number(timeoutRaw) : void 0;
2118
+ const compressionRaw = pick(env, "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION", "OTEL_EXPORTER_OTLP_COMPRESSION")?.toLowerCase();
2119
+ return {
2120
+ envDriven,
2121
+ endpoint,
2122
+ headers: { ...envHeaders, ...explicit.headers ?? {} },
2123
+ protocol: explicit.protocol ?? protocolFrom(pick(env, "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "OTEL_EXPORTER_OTLP_PROTOCOL"), "http/protobuf"),
2124
+ compression: explicit.compression ?? (compressionRaw === "gzip" ? "gzip" : "none"),
2125
+ timeoutMs: explicit.timeoutMs ?? (timeout !== void 0 && Number.isFinite(timeout) && timeout > 0 ? timeout : void 0),
2126
+ serviceName,
2127
+ resourceAttributes,
2128
+ disabled: pick(env, "OTEL_SDK_DISABLED")?.toLowerCase() === "true" || pick(env, "OTEL_TRACES_EXPORTER")?.toLowerCase() === "none"
2129
+ };
2130
+ }
2131
+ function currentEnv() {
2132
+ return typeof process !== "undefined" && process.env ? process.env : {};
2133
+ }
2134
+ var WIRE_VARINT = 0;
2135
+ var WIRE_FIXED64 = 1;
2136
+ var WIRE_LEN = 2;
2137
+ var WIRE_FIXED32 = 5;
2138
+ var textEncoder = new TextEncoder();
2139
+ var Writer = class {
2140
+ constructor() {
2141
+ this.buf = new Uint8Array(128);
2142
+ this.len = 0;
2143
+ this.view = new DataView(this.buf.buffer);
2144
+ }
2145
+ ensure(extra) {
2146
+ if (this.len + extra <= this.buf.length) return;
2147
+ let size = this.buf.length * 2;
2148
+ while (size < this.len + extra) size *= 2;
2149
+ const next = new Uint8Array(size);
2150
+ next.set(this.buf.subarray(0, this.len));
2151
+ this.buf = next;
2152
+ this.view = new DataView(next.buffer);
2153
+ }
2154
+ byte(value) {
2155
+ this.ensure(1);
2156
+ this.buf[this.len++] = value;
2157
+ }
2158
+ varint(value) {
2159
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
2160
+ let n2 = value;
2161
+ while (n2 >= 128) {
2162
+ this.byte(n2 % 128 | 128);
2163
+ n2 = Math.floor(n2 / 128);
2164
+ }
2165
+ this.byte(n2);
2166
+ return;
2167
+ }
2168
+ let n = BigInt.asUintN(64, BigInt(value));
2169
+ while (n >= 128n) {
2170
+ this.byte(Number(n & 127n) | 128);
2171
+ n >>= 7n;
2172
+ }
2173
+ this.byte(Number(n));
2174
+ }
2175
+ tag(field, wire) {
2176
+ this.varint(field * 8 + wire);
2177
+ }
2178
+ raw(bytes) {
2179
+ this.ensure(bytes.length);
2180
+ this.buf.set(bytes, this.len);
2181
+ this.len += bytes.length;
2182
+ }
2183
+ fixed64(value) {
2184
+ this.ensure(8);
2185
+ this.view.setBigUint64(this.len, BigInt.asUintN(64, value), true);
2186
+ this.len += 8;
2187
+ }
2188
+ fixed32(value) {
2189
+ this.ensure(4);
2190
+ this.view.setUint32(this.len, value >>> 0, true);
2191
+ this.len += 4;
2192
+ }
2193
+ double(value) {
2194
+ this.ensure(8);
2195
+ this.view.setFloat64(this.len, value, true);
2196
+ this.len += 8;
2197
+ }
2198
+ finish() {
2199
+ return this.buf.slice(0, this.len);
2200
+ }
2201
+ };
2202
+ function lenField(w, field, bytes) {
2203
+ w.tag(field, WIRE_LEN);
2204
+ w.varint(bytes.length);
2205
+ w.raw(bytes);
2206
+ }
2207
+ function stringField(w, field, value) {
2208
+ if (!value) return;
2209
+ lenField(w, field, textEncoder.encode(value));
2210
+ }
2211
+ function hexBytes(hex, bytes) {
2212
+ if (!hex) return void 0;
2213
+ const out = new Uint8Array(bytes);
2214
+ for (let i = 0; i < bytes; i++) {
2215
+ const pair = hex.slice(i * 2, i * 2 + 2);
2216
+ const value = /^[0-9a-fA-F]{2}$/.test(pair) ? parseInt(pair, 16) : 0;
2217
+ out[i] = value;
2218
+ }
2219
+ return out;
2220
+ }
2221
+ function base64Bytes(value) {
2222
+ return new Uint8Array(buffer.Buffer.from(value, "base64"));
2223
+ }
2224
+ function encodeAnyValue(value) {
2225
+ const w = new Writer();
2226
+ if (value.stringValue !== void 0) {
2227
+ lenField(w, 1, textEncoder.encode(value.stringValue));
2228
+ } else if (value.boolValue !== void 0) {
2229
+ w.tag(2, WIRE_VARINT);
2230
+ w.varint(value.boolValue ? 1 : 0);
2231
+ } else if (value.intValue !== void 0) {
2232
+ w.tag(3, WIRE_VARINT);
2233
+ w.varint(BigInt(value.intValue));
2234
+ } else if (value.doubleValue !== void 0) {
2235
+ w.tag(4, WIRE_FIXED64);
2236
+ w.double(value.doubleValue);
2237
+ } else if (value.arrayValue !== void 0) {
2238
+ const inner = new Writer();
2239
+ for (const item of value.arrayValue.values) lenField(inner, 1, encodeAnyValue(item));
2240
+ lenField(w, 5, inner.finish());
2241
+ } else if (value.kvlistValue !== void 0) {
2242
+ const inner = new Writer();
2243
+ for (const kv of value.kvlistValue.values) lenField(inner, 1, encodeKeyValue(kv));
2244
+ lenField(w, 6, inner.finish());
2245
+ } else if (value.bytesValue !== void 0) {
2246
+ lenField(w, 7, base64Bytes(value.bytesValue));
2247
+ }
2248
+ return w.finish();
2249
+ }
2250
+ function encodeKeyValue(kv) {
2251
+ const w = new Writer();
2252
+ stringField(w, 1, kv.key);
2253
+ lenField(w, 2, encodeAnyValue(kv.value));
2254
+ return w.finish();
2255
+ }
2256
+ function encodeSpanEvent(event) {
2257
+ const w = new Writer();
2258
+ w.tag(1, WIRE_FIXED64);
2259
+ w.fixed64(BigInt(event.timeUnixNano));
2260
+ stringField(w, 2, event.name);
2261
+ for (const attr of event.attributes) lenField(w, 3, encodeKeyValue(attr));
2262
+ return w.finish();
2263
+ }
2264
+ function encodeSpan(span) {
2265
+ const w = new Writer();
2266
+ const traceId = hexBytes(span.traceId, 16);
2267
+ if (traceId) lenField(w, 1, traceId);
2268
+ const spanId = hexBytes(span.spanId, 8);
2269
+ if (spanId) lenField(w, 2, spanId);
2270
+ stringField(w, 3, span.traceState);
2271
+ const parent = hexBytes(span.parentSpanId, 8);
2272
+ if (parent) lenField(w, 4, parent);
2273
+ stringField(w, 5, span.name);
2274
+ if (span.kind) {
2275
+ w.tag(6, WIRE_VARINT);
2276
+ w.varint(span.kind);
2277
+ }
2278
+ w.tag(7, WIRE_FIXED64);
2279
+ w.fixed64(BigInt(span.startTimeUnixNano));
2280
+ w.tag(8, WIRE_FIXED64);
2281
+ w.fixed64(BigInt(span.endTimeUnixNano));
2282
+ for (const attr of span.attributes) lenField(w, 9, encodeKeyValue(attr));
2283
+ for (const event of span.events ?? []) lenField(w, 11, encodeSpanEvent(event));
2284
+ const status = new Writer();
2285
+ stringField(status, 2, span.status.message);
2286
+ if (span.status.code) {
2287
+ status.tag(3, WIRE_VARINT);
2288
+ status.varint(span.status.code);
2289
+ }
2290
+ lenField(w, 15, status.finish());
2291
+ if (span.flags) {
2292
+ w.tag(16, WIRE_FIXED32);
2293
+ w.fixed32(span.flags);
2294
+ }
2295
+ return w.finish();
2296
+ }
2297
+ function encodeExportTraceServiceRequest(request) {
2298
+ const w = new Writer();
2299
+ for (const rs of request.resourceSpans) {
2300
+ const resourceSpans = new Writer();
2301
+ const resource = new Writer();
2302
+ for (const attr of rs.resource.attributes) lenField(resource, 1, encodeKeyValue(attr));
2303
+ lenField(resourceSpans, 1, resource.finish());
2304
+ for (const ss of rs.scopeSpans) {
2305
+ const scopeSpans = new Writer();
2306
+ const scope = new Writer();
2307
+ stringField(scope, 1, ss.scope.name);
2308
+ stringField(scope, 2, ss.scope.version);
2309
+ lenField(scopeSpans, 1, scope.finish());
2310
+ for (const span of ss.spans) lenField(scopeSpans, 2, encodeSpan(span));
2311
+ lenField(resourceSpans, 2, scopeSpans.finish());
2312
+ }
2313
+ stringField(resourceSpans, 3, rs.schemaUrl);
2314
+ lenField(w, 1, resourceSpans.finish());
2315
+ }
2316
+ return w.finish();
2317
+ }
2318
+ var Reader = class {
2319
+ constructor(bytes) {
2320
+ this.bytes = bytes;
2321
+ this.pos = 0;
2322
+ }
2323
+ get done() {
2324
+ return this.pos >= this.bytes.length;
2325
+ }
2326
+ varint() {
2327
+ let result = 0n;
2328
+ let shift = 0n;
2329
+ for (; ; ) {
2330
+ if (this.pos >= this.bytes.length) throw new Error("truncated varint");
2331
+ const byte = this.bytes[this.pos++];
2332
+ result |= BigInt(byte & 127) << shift;
2333
+ if ((byte & 128) === 0) return result;
2334
+ shift += 7n;
2335
+ if (shift > 70n) throw new Error("varint too long");
2336
+ }
2337
+ }
2338
+ slice(length) {
2339
+ if (this.pos + length > this.bytes.length) throw new Error("truncated field");
2340
+ const out = this.bytes.subarray(this.pos, this.pos + length);
2341
+ this.pos += length;
2342
+ return out;
2343
+ }
2344
+ skip(wire) {
2345
+ if (wire === WIRE_VARINT) this.varint();
2346
+ else if (wire === WIRE_FIXED64) this.slice(8);
2347
+ else if (wire === WIRE_FIXED32) this.slice(4);
2348
+ else if (wire === WIRE_LEN) this.slice(Number(this.varint()));
2349
+ else throw new Error(`unsupported wire type ${wire}`);
2350
+ }
2351
+ };
2352
+ function decodeExportTraceServiceResponse(bytes) {
2353
+ const top = new Reader(bytes);
2354
+ let result;
2355
+ while (!top.done) {
2356
+ const key = Number(top.varint());
2357
+ const field = key >>> 3;
2358
+ const wire = key & 7;
2359
+ if (field === 1 && wire === WIRE_LEN) {
2360
+ const inner = new Reader(top.slice(Number(top.varint())));
2361
+ let rejected = 0n;
2362
+ let message;
2363
+ while (!inner.done) {
2364
+ const innerKey = Number(inner.varint());
2365
+ const innerField = innerKey >>> 3;
2366
+ const innerWire = innerKey & 7;
2367
+ if (innerField === 1 && innerWire === WIRE_VARINT) rejected = BigInt.asIntN(64, inner.varint());
2368
+ else if (innerField === 2 && innerWire === WIRE_LEN) message = new TextDecoder().decode(inner.slice(Number(inner.varint())));
2369
+ else inner.skip(innerWire);
2370
+ }
2371
+ result = { rejectedSpans: Number(rejected), ...message ? { message } : {} };
2372
+ } else {
2373
+ top.skip(wire);
2374
+ }
2375
+ }
2376
+ return result;
2377
+ }
2378
+
2379
+ // src/utils/otlp/exporter.ts
2380
+ var gzipAsync = util.promisify(zlib.gzip);
2381
+ var DEFAULT_TIMEOUT_MS = 1e4;
2382
+ var RETRY_DEFAULTS = {
2383
+ maxAttempts: 3,
2384
+ initialDelayMs: 250,
2385
+ maxDelayMs: 4e3,
2386
+ maxElapsedMs: 25e3
2387
+ };
2388
+ var RETRYABLE_STATUS = /* @__PURE__ */ new Set([429, 502, 503, 504]);
2389
+ function retryPolicy(retry) {
2390
+ if (retry === false) return { ...RETRY_DEFAULTS, maxAttempts: 1 };
2391
+ const merged = { ...RETRY_DEFAULTS, ...retry ?? {} };
2392
+ return { ...merged, maxAttempts: Math.max(1, Math.floor(merged.maxAttempts)) };
2393
+ }
2394
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2395
+ function retryAfterMs(response) {
2396
+ let raw;
2397
+ try {
2398
+ raw = response?.headers?.get?.("retry-after");
2399
+ } catch {
2400
+ return void 0;
2401
+ }
2402
+ if (typeof raw !== "string" || raw.trim() === "") return void 0;
2403
+ const seconds = Number(raw);
2404
+ if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
2405
+ const date = Date.parse(raw);
2406
+ return Number.isNaN(date) ? void 0 : Math.max(0, date - Date.now());
2407
+ }
2408
+ async function attemptOnce(fetchFn, url, init, timeoutMs, protocol) {
2409
+ const controller = new AbortController();
2410
+ let timer;
2411
+ const timeout = new Promise((_, reject) => {
2412
+ timer = setTimeout(() => {
2413
+ controller.abort();
2414
+ reject(new Error(`timed out after ${timeoutMs} ms`));
2415
+ }, timeoutMs);
2416
+ });
2417
+ try {
2418
+ const pending = fetchFn(url, { ...init, signal: controller.signal });
2419
+ Promise.resolve(pending).catch(() => void 0);
2420
+ const response = await Promise.race([pending, timeout]);
2421
+ const status = typeof response?.status === "number" ? response.status : response?.ok ? 200 : 0;
2422
+ const ok = typeof response?.ok === "boolean" ? response.ok : status >= 200 && status < 300;
2423
+ if (ok) {
2424
+ const lateBody = timeout.catch(() => void 0);
2425
+ const partialSuccess = await Promise.race([readPartialSuccess(response, protocol), lateBody]);
2426
+ return { kind: "ok", status, ...partialSuccess ? { partialSuccess } : {} };
2427
+ }
2428
+ let body = "";
2429
+ try {
2430
+ if (typeof response?.text === "function") body = String(await response.text());
2431
+ } catch {
2432
+ }
2433
+ const statusText = typeof response?.statusText === "string" && response.statusText ? ` ${response.statusText}` : "";
2434
+ return {
2435
+ kind: "http",
2436
+ status,
2437
+ message: `HTTP ${status}${statusText}${body ? ` - ${body.slice(0, 200)}` : ""}`,
2438
+ retryable: RETRYABLE_STATUS.has(status),
2439
+ retryAfter: retryAfterMs(response)
2440
+ };
2441
+ } catch (err) {
2442
+ return { kind: "network", message: err instanceof Error ? err.message : String(err) };
2443
+ } finally {
2444
+ if (timer !== void 0) clearTimeout(timer);
2445
+ }
2446
+ }
2447
+ async function readPartialSuccess(response, protocol) {
2448
+ try {
2449
+ if (protocol === "http/protobuf") {
2450
+ if (typeof response?.arrayBuffer !== "function") return void 0;
2451
+ const bytes = new Uint8Array(await response.arrayBuffer());
2452
+ if (bytes.length === 0) return void 0;
2453
+ const decoded = decodeExportTraceServiceResponse(bytes);
2454
+ return decoded && (decoded.rejectedSpans > 0 || decoded.message) ? decoded : void 0;
2455
+ }
2456
+ if (typeof response?.text !== "function") return void 0;
2457
+ const text = String(await response.text());
2458
+ if (!text.trim()) return void 0;
2459
+ const partial = JSON.parse(text)?.partialSuccess;
2460
+ if (!partial || typeof partial !== "object") return void 0;
2461
+ const rejectedSpans = Number(partial.rejectedSpans ?? 0);
2462
+ const message = typeof partial.errorMessage === "string" && partial.errorMessage ? partial.errorMessage : void 0;
2463
+ if (!(rejectedSpans > 0) && !message) return void 0;
2464
+ return { rejectedSpans: Number.isFinite(rejectedSpans) ? rejectedSpans : 0, ...message ? { message } : {} };
2465
+ } catch {
2466
+ return void 0;
2467
+ }
2468
+ }
2469
+ function createOtlpExporter(options = {}) {
2470
+ const env = resolveOtlpEnv(currentEnv(), options);
2471
+ if (!env.endpoint && !env.disabled) {
2472
+ throw new Error(
2473
+ "[agent-sdk] OTLP export needs an `endpoint` (or OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_TRACES_ENDPOINT in the environment)."
2474
+ );
2475
+ }
2476
+ const semconv = options.semconv ?? "both";
2477
+ const protocol = env.protocol;
2478
+ const compression = env.compression;
2479
+ const timeoutMs = env.timeoutMs ?? DEFAULT_TIMEOUT_MS;
2480
+ const policy = retryPolicy(options.retry);
2481
+ const serviceName = options.serviceName ?? env.serviceName;
2482
+ const resourceAttributes = { ...env.resourceAttributes, ...options.resourceAttributes ?? {} };
2483
+ const endpoint = env.endpoint ?? "";
2484
+ const content = resolveContentOptions(options.content);
2485
+ return {
2486
+ name: options.name ?? "otlp",
2487
+ endpoint,
2488
+ semconv,
2489
+ protocol,
2490
+ wantsContent: content.enabled,
2491
+ contentOptions: content,
2492
+ async exportSession(file, run) {
2493
+ try {
2494
+ if (env.disabled) {
2495
+ return { ok: true, skipped: true, reason: "disabled by the environment (OTEL_SDK_DISABLED / OTEL_TRACES_EXPORTER)", attempts: 0, spans: 0, bytes: 0 };
2496
+ }
2497
+ const convertOptions = {
2498
+ semconv,
2499
+ serviceName,
2500
+ resourceAttributes,
2501
+ terminal: run.terminal,
2502
+ cancelled: run.cancelled,
2503
+ parent: run.parent,
2504
+ content
2505
+ };
2506
+ const request = sessionToOtlp(file, convertOptions);
2507
+ const spans = countSpans(request);
2508
+ if (spans === 0) return { ok: true, skipped: true, reason: "no spans to export", attempts: 0, spans: 0, bytes: 0 };
2509
+ const fetchFn = options.fetch ?? (typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0);
2510
+ if (!fetchFn) return { ok: false, attempts: 0, spans, bytes: 0, error: "OTLP export requires fetch to be available in this runtime." };
2511
+ let body = protocol === "http/protobuf" ? encodeExportTraceServiceRequest(request) : JSON.stringify(request);
2512
+ const headers = {
2513
+ "content-type": protocol === "http/protobuf" ? "application/x-protobuf" : "application/json"
2514
+ };
2515
+ if (compression === "gzip") {
2516
+ body = await gzipAsync(typeof body === "string" ? buffer.Buffer.from(body, "utf8") : body);
2517
+ headers["content-encoding"] = "gzip";
2518
+ }
2519
+ Object.assign(headers, env.headers);
2520
+ const bytes = typeof body === "string" ? buffer.Buffer.byteLength(body, "utf8") : body.length;
2521
+ const started = Date.now();
2522
+ let attempts = 0;
2523
+ let lastError = "export failed";
2524
+ let lastStatus;
2525
+ for (; ; ) {
2526
+ attempts += 1;
2527
+ const remaining = policy.maxElapsedMs - (Date.now() - started);
2528
+ const outcome = await attemptOnce(
2529
+ fetchFn,
2530
+ env.endpoint,
2531
+ { method: "POST", headers, body },
2532
+ Math.max(1, Math.min(timeoutMs, remaining)),
2533
+ protocol
2534
+ );
2535
+ if (outcome.kind === "ok") {
2536
+ return { ok: true, attempts, status: outcome.status, spans, bytes, ...outcome.partialSuccess ? { partialSuccess: outcome.partialSuccess } : {} };
2537
+ }
2538
+ lastError = outcome.message;
2539
+ lastStatus = outcome.kind === "http" ? outcome.status : void 0;
2540
+ const retryable = outcome.kind === "network" || outcome.retryable;
2541
+ if (!retryable || attempts >= policy.maxAttempts) break;
2542
+ const ceiling = Math.min(policy.maxDelayMs, policy.initialDelayMs * 2 ** (attempts - 1));
2543
+ const wait = outcome.kind === "http" && outcome.retryAfter !== void 0 ? Math.min(outcome.retryAfter, policy.maxDelayMs) : Math.random() * ceiling;
2544
+ if (Date.now() - started + wait >= policy.maxElapsedMs) break;
2545
+ await sleep(wait);
2546
+ }
2547
+ return { ok: false, attempts, ...lastStatus !== void 0 ? { status: lastStatus } : {}, spans, bytes, error: lastError };
2548
+ } catch (err) {
2549
+ return { ok: false, attempts: 0, spans: 0, bytes: 0, error: err instanceof Error ? err.message : String(err) };
2550
+ }
2551
+ }
2552
+ };
2553
+ }
2554
+
2555
+ // src/utils/otlp/context.ts
2556
+ var TRACEPARENT = /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})(-.*)?$/;
2557
+ var ALL_ZERO_TRACE = /^0{32}$/;
2558
+ var ALL_ZERO_SPAN = /^0{16}$/;
2559
+ var MAX_TRACESTATE = 512;
2560
+ function parseTraceparent(header) {
2561
+ if (typeof header !== "string") return void 0;
2562
+ const match = TRACEPARENT.exec(header.trim());
2563
+ if (!match) return void 0;
2564
+ const [, version, traceId, spanId, flagsHex, rest] = match;
2565
+ if (version === "ff") return void 0;
2566
+ if (version === "00" && rest) return void 0;
2567
+ if (ALL_ZERO_TRACE.test(traceId) || ALL_ZERO_SPAN.test(spanId)) return void 0;
2568
+ const flags = parseInt(flagsHex, 16);
2569
+ return { traceId, spanId, flags, sampled: (flags & 1) === 1 };
2570
+ }
2571
+ function formatTraceparent(parts) {
2572
+ const flags = typeof parts.flags === "number" ? parts.flags & 255 : parts.sampled === false ? 0 : 1;
2573
+ return `00-${parts.traceId}-${parts.spanId}-${flags.toString(16).padStart(2, "0")}`;
2574
+ }
2575
+ function traceparentOf(ctx) {
2576
+ if (!ctx?.traceId || !ctx.traceSpanId) return void 0;
2577
+ return formatTraceparent({ traceId: ctx.traceId, spanId: ctx.traceSpanId, flags: ctx.traceFlags ?? 1 });
2578
+ }
2579
+ function cleanTraceState(value) {
2580
+ if (typeof value !== "string") return void 0;
2581
+ const trimmed = value.trim();
2582
+ if (!trimmed || trimmed.length > MAX_TRACESTATE || !/^[\x20-\x7e]+$/.test(trimmed)) return void 0;
2583
+ return trimmed;
2584
+ }
2585
+ function resolveTraceParent(input) {
2586
+ if (input === void 0 || input === null) return void 0;
2587
+ const header = typeof input === "string" ? input : input?.traceparent;
2588
+ const parsed = parseTraceparent(header);
2589
+ if (!parsed) {
2590
+ warnOnce("[agent-sdk] Ignoring an invalid W3C traceparent; the trace starts a new root.");
2591
+ return void 0;
2592
+ }
2593
+ const traceState = typeof input === "object" ? cleanTraceState(input.tracestate) : void 0;
2594
+ return {
2595
+ traceId: parsed.traceId,
2596
+ spanId: parsed.spanId,
2597
+ flags: parsed.flags,
2598
+ sampled: parsed.sampled,
2599
+ remote: true,
2600
+ ...traceState ? { traceState } : {}
2601
+ };
2602
+ }
2603
+ function persistedParentOf(parent) {
2604
+ if (!parent) return void 0;
2605
+ return { spanId: parent.spanId, flags: parent.flags, ...parent.traceState ? { traceState: parent.traceState } : {} };
2606
+ }
2607
+ function readPersistedParent(value) {
2608
+ if (!value || typeof value !== "object") return void 0;
2609
+ const raw = value;
2610
+ if (typeof raw.spanId !== "string" || !/^[0-9a-f]{16}$/.test(raw.spanId) || ALL_ZERO_SPAN.test(raw.spanId)) return void 0;
2611
+ const flags = Number(raw.flags);
2612
+ if (!Number.isInteger(flags) || flags < 0 || flags > 255) return void 0;
2613
+ const traceState = cleanTraceState(raw.traceState);
2614
+ return { spanId: raw.spanId, flags, ...traceState ? { traceState } : {} };
2615
+ }
2616
+ function restoreParent(persisted, traceId) {
2617
+ return {
2618
+ traceId,
2619
+ spanId: persisted.spanId,
2620
+ flags: persisted.flags,
2621
+ sampled: (persisted.flags & 1) === 1,
2622
+ remote: true,
2623
+ ...persisted.traceState ? { traceState: persisted.traceState } : {}
2624
+ };
2625
+ }
2626
+
2627
+ // src/utils/tracing.ts
1237
2628
  var DEFAULT_COGNIPEER_URL = "https://console.cognipeer.com/api/client/v1/tracing/sessions";
1238
2629
  function fileSink(path2) {
1239
2630
  return { type: "file", path: path2 };
@@ -1259,8 +2650,9 @@ function cognipeerSink(first, second) {
1259
2650
  function httpSink(url, headers) {
1260
2651
  return { type: "http", url, headers };
1261
2652
  }
1262
- function otlpSink(endpoint, headers) {
1263
- return { type: "otlp", endpoint, headers };
2653
+ function otlpSink(first, headers, options) {
2654
+ if (first !== null && typeof first === "object") return { type: "otlp", ...first };
2655
+ return { type: "otlp", endpoint: first, headers, ...options ?? {} };
1264
2656
  }
1265
2657
  function resolveLogsBaseDir(customPath, ensureDirectory = true) {
1266
2658
  const root = process.cwd();
@@ -1333,23 +2725,23 @@ function extractMetadata(model, paths) {
1333
2725
  if (!model) return void 0;
1334
2726
  for (const path2 of paths) {
1335
2727
  const value = getNestedValue2(model, path2);
1336
- const str = coerceToString(value);
1337
- if (str) return str;
2728
+ const str2 = coerceToString(value);
2729
+ if (str2) return str2;
1338
2730
  }
1339
2731
  const maybeLc = model?._lc;
1340
2732
  if (maybeLc) {
1341
2733
  for (const path2 of paths) {
1342
2734
  const value = getNestedValue2(maybeLc, path2);
1343
- const str = coerceToString(value);
1344
- if (str) return str;
2735
+ const str2 = coerceToString(value);
2736
+ if (str2) return str2;
1345
2737
  }
1346
2738
  }
1347
2739
  const maybeClient = model?.client || model?.api || model?.service;
1348
2740
  if (maybeClient) {
1349
2741
  for (const path2 of paths) {
1350
2742
  const value = getNestedValue2(maybeClient, path2);
1351
- const str = coerceToString(value);
1352
- if (str) return str;
2743
+ const str2 = coerceToString(value);
2744
+ if (str2) return str2;
1353
2745
  }
1354
2746
  }
1355
2747
  const constructorName = model?.constructor?.name;
@@ -1380,8 +2772,8 @@ function inferModelFromMessages(messageList) {
1380
2772
  if (!message) continue;
1381
2773
  for (const path2 of messagePaths) {
1382
2774
  const value = getNestedValue2(message, path2);
1383
- const str = coerceToString(value);
1384
- if (str) return str;
2775
+ const str2 = coerceToString(value);
2776
+ if (str2) return str2;
1385
2777
  }
1386
2778
  }
1387
2779
  return void 0;
@@ -1399,8 +2791,8 @@ function inferProviderFromMessages(messageList) {
1399
2791
  if (!message) continue;
1400
2792
  for (const path2 of messagePaths) {
1401
2793
  const value = getNestedValue2(message, path2);
1402
- const str = coerceToString(value);
1403
- if (str) return str;
2794
+ const str2 = coerceToString(value);
2795
+ if (str2) return str2;
1404
2796
  }
1405
2797
  }
1406
2798
  return void 0;
@@ -1462,12 +2854,18 @@ function resolveSink(sink) {
1462
2854
  return headers ? { type: "http", url, headers } : { type: "http", url };
1463
2855
  }
1464
2856
  case "otlp": {
1465
- const endpoint = typeof candidate.endpoint === "string" ? candidate.endpoint.trim() : "";
1466
- if (!endpoint) {
2857
+ const given = candidate.endpoint;
2858
+ if (given !== void 0 && (typeof given !== "string" || given.trim().length === 0)) {
2859
+ throw new Error("otlp sink requires a non-empty endpoint");
2860
+ }
2861
+ let exporter;
2862
+ try {
2863
+ exporter = createOtlpExporter({ ...candidate, endpoint: given?.trim() });
2864
+ } catch {
1467
2865
  throw new Error("otlp sink requires a non-empty endpoint");
1468
2866
  }
1469
2867
  const headers = candidate.headers ? { ...candidate.headers } : void 0;
1470
- return headers ? { type: "otlp", endpoint, headers } : { type: "otlp", endpoint };
2868
+ return headers ? { type: "otlp", endpoint: exporter.endpoint, headers, exporter } : { type: "otlp", endpoint: exporter.endpoint, exporter };
1471
2869
  }
1472
2870
  default: {
1473
2871
  if (typeof console !== "undefined" && typeof console.warn === "function") {
@@ -1477,6 +2875,17 @@ function resolveSink(sink) {
1477
2875
  }
1478
2876
  }
1479
2877
  }
2878
+ function withoutUserinfo(endpoint) {
2879
+ try {
2880
+ const url = new URL(endpoint);
2881
+ if (!url.username && !url.password) return endpoint;
2882
+ url.username = "";
2883
+ url.password = "";
2884
+ return url.toString();
2885
+ } catch {
2886
+ return endpoint;
2887
+ }
2888
+ }
1480
2889
  function snapshotSink(runtime) {
1481
2890
  const sink = runtime.resolvedConfig.sink;
1482
2891
  switch (sink.type) {
@@ -1489,7 +2898,7 @@ function snapshotSink(runtime) {
1489
2898
  case "http":
1490
2899
  return { type: "http", url: sink.url };
1491
2900
  case "otlp":
1492
- return { type: "otlp", endpoint: sink.endpoint };
2901
+ return { type: "otlp", endpoint: withoutUserinfo(sink.endpoint) };
1493
2902
  default:
1494
2903
  return { type: "custom" };
1495
2904
  }
@@ -1507,11 +2916,11 @@ var TRACE_HTTP_RETRYABLE_STATUS = /* @__PURE__ */ new Set([404, 408, 425, 429, 5
1507
2916
  var TRACE_HTTP_RETRY_BASE_MS = 250;
1508
2917
  var TRACE_HTTP_RETRY_MAX_MS = 4e3;
1509
2918
  var RetryableHttpError = class extends Error {
1510
- constructor(status, message, retryAfterMs) {
2919
+ constructor(status, message, retryAfterMs2) {
1511
2920
  super(message);
1512
2921
  this.name = "RetryableHttpError";
1513
2922
  this.status = status;
1514
- this.retryAfterMs = retryAfterMs;
2923
+ this.retryAfterMs = retryAfterMs2;
1515
2924
  }
1516
2925
  };
1517
2926
  function traceSleep(ms) {
@@ -1604,206 +3013,23 @@ async function postStreamingSessionEnd(baseUrl, headers, payload) {
1604
3013
  const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/end`;
1605
3014
  await postJsonReliable(url, headers, payload, { retry: true });
1606
3015
  }
1607
- function isoToUnixNano(iso) {
1608
- const ms = new Date(iso).getTime();
1609
- return `${ms}000000`;
1610
- }
1611
- function toOtlpStatusCode(status) {
1612
- if (status === "error") return 2;
1613
- if (status === "success" || status === "completed") return 1;
1614
- return 0;
1615
- }
1616
- function toOtlpSpanKind(type) {
1617
- switch (type) {
1618
- case "ai_call":
1619
- case "summarization":
1620
- return 3;
1621
- // CLIENT — outgoing LLM request (the summarizer is one too)
1622
- case "tool_call":
1623
- return 1;
1624
- // INTERNAL
1625
- case "agent_iteration":
1626
- return 1;
1627
- // INTERNAL
1628
- default:
1629
- return 1;
1630
- }
1631
- }
1632
- function stringAttr(key, val) {
1633
- return val != null ? { key, value: { stringValue: val } } : null;
1634
- }
1635
- function intAttr(key, val) {
1636
- return val != null && !Number.isNaN(val) ? { key, value: { intValue: String(val) } } : null;
1637
- }
1638
- function doubleAttr(key, val) {
1639
- return val != null && !Number.isNaN(val) ? { key, value: { doubleValue: val } } : null;
1640
- }
1641
- function eventToOtlpSpan(event) {
1642
- const startNano = isoToUnixNano(event.timestamp);
1643
- const endNano = event.durationMs != null ? `${new Date(new Date(event.timestamp).getTime() + event.durationMs).getTime()}000000` : startNano;
1644
- const attrs = [
1645
- stringAttr("cognipeer.event.type", event.type),
1646
- stringAttr("cognipeer.event.label", event.label),
1647
- intAttr("cognipeer.event.sequence", event.sequence),
1648
- stringAttr("cognipeer.actor.scope", event.actor?.scope),
1649
- stringAttr("cognipeer.actor.name", event.actor?.name),
1650
- stringAttr("cognipeer.actor.role", event.actor?.role),
1651
- stringAttr("cognipeer.model", event.model),
1652
- intAttr("cognipeer.tokens.reasoning", event.reasoningTokens),
1653
- stringAttr("cognipeer.finish_reason", event.finishReason),
1654
- stringAttr("cognipeer.provider", event.provider),
1655
- stringAttr("cognipeer.tool.details", event.toolDetails ? JSON.stringify(event.toolDetails) : void 0),
1656
- intAttr("cognipeer.tokens.input", event.inputTokens),
1657
- intAttr("cognipeer.tokens.output", event.outputTokens),
1658
- intAttr("cognipeer.tokens.total", event.totalTokens),
1659
- intAttr("cognipeer.tokens.cached_input", event.cachedInputTokens),
1660
- intAttr("cognipeer.bytes.request", event.requestBytes),
1661
- intAttr("cognipeer.bytes.response", event.responseBytes),
1662
- stringAttr("cognipeer.tool.execution_id", event.toolExecutionId),
1663
- stringAttr("cognipeer.retry_of", event.retryOf),
1664
- stringAttr("cognipeer.event.id", event.id)
1665
- ].filter(Boolean);
1666
- if (event.data?.sections && event.data.sections.length > 0) {
1667
- try {
1668
- attrs.push({ key: "cognipeer.sections", value: { stringValue: JSON.stringify(event.data.sections) } });
1669
- } catch {
1670
- }
1671
- }
1672
- const span = {
1673
- traceId: event.traceId,
1674
- spanId: event.spanId,
1675
- parentSpanId: event.parentSpanId || "",
1676
- name: event.label || event.type,
1677
- kind: toOtlpSpanKind(event.type),
1678
- startTimeUnixNano: startNano,
1679
- endTimeUnixNano: endNano,
1680
- attributes: attrs,
1681
- status: {
1682
- code: toOtlpStatusCode(event.status),
1683
- ...event.status === "error" && event.error?.message ? { message: event.error.message } : {}
1684
- }
1685
- };
1686
- if (event.error) {
1687
- span.events = [{
1688
- timeUnixNano: startNano,
1689
- name: "exception",
1690
- attributes: [
1691
- { key: "exception.message", value: { stringValue: event.error.message } },
1692
- ...event.error.stack ? [{ key: "exception.stacktrace", value: { stringValue: event.error.stack } }] : []
1693
- ]
1694
- }];
1695
- }
1696
- return span;
1697
- }
1698
- function traceSessionToOtlp(session) {
1699
- const traceId = session.traceId || generateTraceId();
1700
- const rootSpanId = session.rootSpanId || generateSpanId();
1701
- const startNano = isoToUnixNano(session.startedAt);
1702
- const endNano = session.endedAt ? isoToUnixNano(session.endedAt) : startNano;
1703
- const resourceAttrs = [
1704
- { key: "service.name", value: { stringValue: session.agent?.name || "cognipeer-agent" } },
1705
- stringAttr("service.version", session.agent?.version),
1706
- stringAttr("cognipeer.session.id", session.sessionId),
1707
- stringAttr("cognipeer.thread.id", session.threadId),
1708
- stringAttr("cognipeer.agent.model", session.agent?.model),
1709
- stringAttr("cognipeer.agent.provider", session.agent?.provider),
1710
- ...Object.entries(session.metadata || {}).map(([key, value]) => stringAttr(`cognipeer.metadata.${key}`, value))
1711
- ].filter(Boolean);
1712
- const rootAttrs = [
1713
- stringAttr("cognipeer.session.status", session.status),
1714
- doubleAttr("cognipeer.session.duration_ms", session.durationMs),
1715
- intAttr("cognipeer.session.total_input_tokens", session.summary.totalInputTokens),
1716
- intAttr("cognipeer.session.total_output_tokens", session.summary.totalOutputTokens),
1717
- intAttr("cognipeer.session.total_cached_input_tokens", session.summary.totalCachedInputTokens),
1718
- intAttr("cognipeer.session.total_bytes_in", session.summary.totalBytesIn),
1719
- intAttr("cognipeer.session.total_bytes_out", session.summary.totalBytesOut),
1720
- intAttr("cognipeer.session.event_count", session.events.length)
1721
- ].filter(Boolean);
1722
- if (session.summary.eventCounts) {
1723
- for (const [key, count] of Object.entries(session.summary.eventCounts)) {
1724
- rootAttrs.push({ key: `cognipeer.session.event_count.${key}`, value: { intValue: String(count) } });
1725
- }
1726
- }
1727
- const rootSpan = {
1728
- traceId,
1729
- spanId: rootSpanId,
1730
- parentSpanId: "",
1731
- name: `agent_session: ${session.agent?.name || "agent"}`,
1732
- kind: 1,
1733
- // INTERNAL
1734
- startTimeUnixNano: startNano,
1735
- endTimeUnixNano: endNano,
1736
- attributes: rootAttrs,
1737
- status: {
1738
- code: toOtlpStatusCode(session.status),
1739
- ...session.status === "error" && session.errors.length > 0 ? { message: session.errors.map((e) => e.message).join("; ") } : {}
1740
- }
1741
- };
1742
- if (session.errors.length > 0) {
1743
- rootSpan.events = session.errors.map((err) => ({
1744
- timeUnixNano: err.timestamp ? isoToUnixNano(err.timestamp) : startNano,
1745
- name: "exception",
1746
- attributes: [
1747
- { key: "exception.message", value: { stringValue: err.message } },
1748
- ...err.stack ? [{ key: "exception.stacktrace", value: { stringValue: err.stack } }] : [],
1749
- ...err.type ? [{ key: "exception.type", value: { stringValue: err.type } }] : []
1750
- ]
1751
- }));
1752
- }
1753
- const childSpans = session.events.map((event) => {
1754
- const span = eventToOtlpSpan({
1755
- ...event,
1756
- traceId: event.traceId || traceId,
1757
- spanId: event.spanId || generateSpanId(),
1758
- parentSpanId: event.parentSpanId || rootSpanId
1759
- });
1760
- return span;
3016
+ function traceSessionToOtlp(session, options = {}) {
3017
+ return sessionToOtlp(session, {
3018
+ semconv: "both",
3019
+ terminal: session.status !== "paused" && session.status !== "in_progress",
3020
+ ...options,
3021
+ content: resolveContentOptions(options.content)
1761
3022
  });
1762
- return {
1763
- resourceSpans: [{
1764
- resource: { attributes: resourceAttrs },
1765
- scopeSpans: [{
1766
- scope: {
1767
- name: "cognipeer-agent-sdk",
1768
- version: "1.0.0"
1769
- },
1770
- spans: [rootSpan, ...childSpans]
1771
- }]
1772
- }]
1773
- };
1774
3023
  }
1775
- async function postOtlpTraces(endpoint, headers, payload) {
1776
- const fetchFn = typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0;
1777
- if (!fetchFn) {
1778
- throw new Error("OTLP sink requires fetch to be available in this runtime.");
1779
- }
1780
- const finalHeaders = {
1781
- "content-type": "application/json",
1782
- ...headers || {}
3024
+ function traceErrorOf(err) {
3025
+ const e = err;
3026
+ const message = typeof e?.message === "string" && e.message ? e.message : String(err);
3027
+ const type = err instanceof Error && typeof err.name === "string" && err.name ? err.name : void 0;
3028
+ return {
3029
+ message,
3030
+ ...typeof e?.stack === "string" ? { stack: e.stack } : {},
3031
+ ...type ? { type } : {}
1783
3032
  };
1784
- try {
1785
- const response = await fetchFn(endpoint, {
1786
- method: "POST",
1787
- headers: finalHeaders,
1788
- body: JSON.stringify(payload)
1789
- });
1790
- if (!response.ok) {
1791
- let responseText = "";
1792
- try {
1793
- responseText = await response.text();
1794
- } catch {
1795
- }
1796
- const statusLine = `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
1797
- const bodyPreview = responseText ? ` - ${responseText.slice(0, 200)}` : "";
1798
- throw new Error(`${statusLine}${bodyPreview}`);
1799
- }
1800
- } catch (err) {
1801
- const errMsg = err instanceof Error ? err.message : String(err);
1802
- if (typeof console !== "undefined" && typeof console.error === "function") {
1803
- console.error("[Tracing] OTLP export failed:", errMsg);
1804
- }
1805
- throw err;
1806
- }
1807
3033
  }
1808
3034
  function createEmptySummary() {
1809
3035
  return {
@@ -1823,10 +3049,16 @@ function generateEventId(sequence) {
1823
3049
  return `evt_${String(sequence).padStart(4, "0")}_${nanoid.nanoid(4)}`;
1824
3050
  }
1825
3051
  function generateTraceId() {
1826
- return crypto__default.default.randomBytes(16).toString("hex");
3052
+ for (; ; ) {
3053
+ const id = crypto__default.default.randomBytes(16).toString("hex");
3054
+ if (/[1-9a-f]/.test(id)) return id;
3055
+ }
1827
3056
  }
1828
3057
  function generateSpanId() {
1829
- return crypto__default.default.randomBytes(8).toString("hex");
3058
+ for (; ; ) {
3059
+ const id = crypto__default.default.randomBytes(8).toString("hex");
3060
+ if (/[1-9a-f]/.test(id)) return id;
3061
+ }
1830
3062
  }
1831
3063
  function defaultEventLabel(type) {
1832
3064
  switch (type) {
@@ -2103,9 +3335,64 @@ function readTraceContinuation(value) {
2103
3335
  nextSequence,
2104
3336
  part,
2105
3337
  summary,
2106
- errors: Array.isArray(raw.errors) ? raw.errors : []
3338
+ errors: Array.isArray(raw.errors) ? raw.errors : [],
3339
+ ...(() => {
3340
+ const parent = readPersistedParent(raw.parent);
3341
+ return parent ? { parent } : {};
3342
+ })(),
3343
+ ...(() => {
3344
+ const pendingSpans = readPendingSpans(raw.pendingSpans);
3345
+ return pendingSpans.length > 0 ? { pendingSpans } : {};
3346
+ })()
3347
+ };
3348
+ }
3349
+ var MAX_CARRIED_SPANS = 64;
3350
+ var isSubagentSpanRecord = (event) => event.type === "span" && event.actor?.role === "subagent";
3351
+ function carriedSpanOf(record) {
3352
+ const identity2 = (record.data?.sections ?? []).filter(
3353
+ (section) => section.kind === "metadata" && section.identity === true
3354
+ );
3355
+ return {
3356
+ sessionId: record.sessionId,
3357
+ traceId: record.traceId,
3358
+ spanId: record.spanId,
3359
+ parentSpanId: record.parentSpanId,
3360
+ id: record.id,
3361
+ type: record.type,
3362
+ label: record.label,
3363
+ sequence: record.sequence,
3364
+ timestamp: record.timestamp,
3365
+ actor: record.actor,
3366
+ status: record.status,
3367
+ durationMs: record.durationMs,
3368
+ ...identity2.length > 0 ? { data: { sections: identity2 } } : {}
2107
3369
  };
2108
3370
  }
3371
+ function readPendingSpans(value) {
3372
+ if (!Array.isArray(value)) return [];
3373
+ const out = [];
3374
+ for (const item of value.slice(0, MAX_CARRIED_SPANS)) {
3375
+ if (!item || typeof item !== "object") continue;
3376
+ const raw = item;
3377
+ if (typeof raw.spanId !== "string" || raw.spanId.length === 0) continue;
3378
+ if (raw.status !== "pending" || !isSubagentSpanRecord(raw)) continue;
3379
+ if (typeof raw.sequence !== "number" || !Number.isInteger(raw.sequence) || raw.sequence < 1) continue;
3380
+ if (typeof raw.timestamp !== "string" || Number.isNaN(Date.parse(raw.timestamp))) continue;
3381
+ if (typeof raw.label !== "string" || typeof raw.id !== "string" || typeof raw.sessionId !== "string") continue;
3382
+ if (raw.parentSpanId !== void 0 && typeof raw.parentSpanId !== "string") continue;
3383
+ if (raw.durationMs !== void 0 && (typeof raw.durationMs !== "number" || !Number.isFinite(raw.durationMs))) continue;
3384
+ out.push(carriedSpanOf(raw));
3385
+ }
3386
+ return out;
3387
+ }
3388
+ function pendingSpansOf(session) {
3389
+ const candidates = [
3390
+ ...session.carriedSpans ?? [],
3391
+ ...session.events.filter(isSubagentSpanRecord)
3392
+ ];
3393
+ if (candidates.length === 0) return [];
3394
+ return foldSupersededSpans(candidates).filter((event) => event.status === "pending").slice(-MAX_CARRIED_SPANS).map(carriedSpanOf);
3395
+ }
2109
3396
  function traceContinuationOf(session) {
2110
3397
  return {
2111
3398
  v: 1,
@@ -2119,15 +3406,32 @@ function traceContinuationOf(session) {
2119
3406
  summary: JSON.parse(JSON.stringify(session.summary)),
2120
3407
  // Sink failures belong to the part that hit them; carrying them on would
2121
3408
  // mark every later part `partial`.
2122
- errors: session.errors.filter((error) => error.type !== "sink")
3409
+ errors: session.errors.filter((error) => error.type !== "sink"),
3410
+ // Where the root hangs, so the leg that ends the run exports it under the same remote parent.
3411
+ ...session.parent ? { parent: persistedParentOf(session.parent) } : {},
3412
+ ...(() => {
3413
+ const pendingSpans = pendingSpansOf(session);
3414
+ return pendingSpans.length > 0 ? { pendingSpans } : {};
3415
+ })()
2123
3416
  };
2124
3417
  }
2125
- function createTraceSession(opts, continuation) {
3418
+ function createTraceSession(opts, continuation, extras) {
2126
3419
  const cfg = withDefaults(opts.tracing);
2127
3420
  if (!cfg.enabled) return void 0;
3421
+ let parent;
3422
+ if (continuation) {
3423
+ if (continuation.parent && continuation.traceId) parent = restoreParent(continuation.parent, continuation.traceId);
3424
+ } else {
3425
+ parent = resolveTraceParent(extras?.traceParent ?? opts.tracing?.parent);
3426
+ }
3427
+ const exporters = [...extras?.exporters ?? []];
3428
+ const contentExporters = [
3429
+ ...cfg.sink.type === "otlp" ? [cfg.sink.exporter] : [],
3430
+ ...exporters
3431
+ ].filter((exporter) => exporter.wantsContent);
2128
3432
  const providedSessionId = opts.tracing?.sessionId?.trim();
2129
3433
  const sessionId = continuation?.sessionId || providedSessionId || generateSessionId();
2130
- const traceId = continuation?.traceId || generateTraceId();
3434
+ const traceId = continuation?.traceId || parent?.traceId || generateTraceId();
2131
3435
  const rootSpanId = continuation?.rootSpanId || generateSpanId();
2132
3436
  const runtime = {
2133
3437
  sessionId,
@@ -2146,7 +3450,20 @@ function createTraceSession(opts, continuation) {
2146
3450
  // again would reset a streaming receiver's copy.
2147
3451
  sessionStarted: Boolean(continuation),
2148
3452
  sequenceOffset: continuation ? continuation.nextSequence - 1 : 0,
2149
- part: continuation ? continuation.part + 1 : 1
3453
+ part: continuation ? continuation.part + 1 : 1,
3454
+ ...continuation?.pendingSpans?.length ? { carriedSpans: continuation.pendingSpans } : {},
3455
+ ...exporters.length ? { exporters } : {},
3456
+ exportReports: [],
3457
+ ...parent ? { parent } : {},
3458
+ ...contentExporters.length > 0 ? {
3459
+ captureContent: true,
3460
+ captureLimits: {
3461
+ // Headroom over the export cap: a redact hook runs before the cap and must see a
3462
+ // secret whole, even one that straddles the point where the export cuts.
3463
+ maxStringChars: 4 * Math.max(...contentExporters.map((exporter) => exporter.contentOptions?.maxStringChars ?? 4096)),
3464
+ maxMessages: Math.max(...contentExporters.map((exporter) => exporter.contentOptions?.maxMessages ?? 32))
3465
+ }
3466
+ } : {}
2150
3467
  };
2151
3468
  if (cfg.sink.type === "file") {
2152
3469
  const baseDir = cfg.sink.baseDir;
@@ -2262,8 +3579,15 @@ function recordTraceEvent(session, event) {
2262
3579
  }
2263
3580
  }
2264
3581
  }
3582
+ if (!session.resolvedConfig.logData && event.sections?.length) {
3583
+ const identity2 = event.sections.filter((section) => section.kind === "metadata" && section.identity === true);
3584
+ if (identity2.length > 0) sections = ensureUniqueSections(id, identity2);
3585
+ }
2265
3586
  if (event.alwaysSections?.length) {
2266
- sections = ensureUniqueSections(id, [...event.alwaysSections, ...sections ?? []]);
3587
+ const identity2 = event.alwaysSections.map(
3588
+ (section) => section.kind === "metadata" ? { ...section, identity: true } : section
3589
+ );
3590
+ sections = ensureUniqueSections(id, [...identity2, ...sections ?? []]);
2267
3591
  }
2268
3592
  const resolvedModel = event.model ?? inferModelFromMessages(event.messageList);
2269
3593
  const resolvedProvider = event.provider ?? inferProviderFromMessages(event.messageList);
@@ -2299,6 +3623,16 @@ function recordTraceEvent(session, event) {
2299
3623
  // different facts, and a zero would erase the difference.
2300
3624
  ...reasoningTokens !== void 0 && !Number.isNaN(reasoningTokens) ? { reasoningTokens } : {},
2301
3625
  ...event.finishReason ? { finishReason: event.finishReason } : {},
3626
+ // Provider facts: absent when the provider did not say, never zero or empty.
3627
+ ...event.responseId ? { responseId: event.responseId } : {},
3628
+ ...event.responseModel ? { responseModel: event.responseModel } : {},
3629
+ ...event.rawFinishReason ? { rawFinishReason: event.rawFinishReason } : {},
3630
+ ...typeof event.cacheWriteTokens === "number" && event.cacheWriteTokens > 0 ? { cacheWriteTokens: event.cacheWriteTokens } : {},
3631
+ ...event.usageBasis && (event.usageBasis.inputExcludesCache || event.usageBasis.outputExcludesReasoning) ? { usageBasis: { ...event.usageBasis } } : {},
3632
+ ...event.streaming ? { streaming: true } : {},
3633
+ ...event.outputType ? { outputType: event.outputType } : {},
3634
+ ...event.toolCallId ? { toolCallId: event.toolCallId } : {},
3635
+ ...event.skipReason ? { skipReason: event.skipReason } : {},
2302
3636
  requestBytes,
2303
3637
  responseBytes,
2304
3638
  model: resolvedModel,
@@ -2320,6 +3654,15 @@ function recordTraceEvent(session, event) {
2320
3654
  timestamp: timestampIso
2321
3655
  });
2322
3656
  }
3657
+ if (session.captureContent && event.capture) {
3658
+ try {
3659
+ attachCapturedContent(
3660
+ record,
3661
+ buildCapturedContent(event.capture, session.captureLimits ?? { maxStringChars: 4096, maxMessages: 32 })
3662
+ );
3663
+ } catch {
3664
+ }
3665
+ }
2323
3666
  session.events.push(record);
2324
3667
  const sink = session.resolvedConfig.sink;
2325
3668
  if (sink.type === "custom" && typeof sink.onEvent === "function") {
@@ -2414,6 +3757,17 @@ function recordSubagentSpan(session, span) {
2414
3757
  sections
2415
3758
  });
2416
3759
  }
3760
+ function foldSupersededSpans(events) {
3761
+ const rank = (event, index) => typeof event.sequence === "number" && Number.isFinite(event.sequence) ? event.sequence : index;
3762
+ const winner = /* @__PURE__ */ new Map();
3763
+ for (let i = 0; i < events.length; i++) {
3764
+ const id = events[i].spanId;
3765
+ if (!id) continue;
3766
+ const current = winner.get(id);
3767
+ if (current === void 0 || rank(events[i], i) >= rank(events[current], current)) winner.set(id, i);
3768
+ }
3769
+ return events.filter((event, i) => !(event.spanId && event.status === "pending" && winner.get(event.spanId) !== i));
3770
+ }
2417
3771
  function recordOrDeferTraceEvent(ctx, event, options) {
2418
3772
  const session = ctx?.__traceSession;
2419
3773
  if (isTraceSessionOpen(session)) {
@@ -2424,7 +3778,8 @@ function recordOrDeferTraceEvent(ctx, event, options) {
2424
3778
  const held = Array.isArray(ctx?.[DEFERRED_TRACE_EVENTS_KEY]) ? ctx[DEFERRED_TRACE_EVENTS_KEY] : [];
2425
3779
  return {
2426
3780
  ...ctx || {},
2427
- [DEFERRED_TRACE_EVENTS_KEY]: [...held, { ...event, timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString() }]
3781
+ // `capture` (content for exporters) is never parked on ctx, which callers persist.
3782
+ [DEFERRED_TRACE_EVENTS_KEY]: [...held, { ...event, capture: void 0, timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString() }]
2428
3783
  };
2429
3784
  }
2430
3785
  function replayDeferredTraceEvents(session, deferred) {
@@ -2458,6 +3813,7 @@ async function finalizeTraceSession(session, params = {}) {
2458
3813
  message: params.error.message || "Unknown error",
2459
3814
  stack: params.error.stack,
2460
3815
  type: "session",
3816
+ ...params.error.name ? { errorName: params.error.name } : {},
2461
3817
  timestamp: endedAtIso
2462
3818
  });
2463
3819
  }
@@ -2481,24 +3837,62 @@ async function finalizeTraceSession(session, params = {}) {
2481
3837
  ...(session.part ?? 1) > 1 ? { continuation: { part: session.part, firstSequence: (session.sequenceOffset ?? 0) + 1 } } : {}
2482
3838
  });
2483
3839
  const payloadForSink = buildPayload(initialStatus);
3840
+ const carried = session.carriedSpans ?? [];
3841
+ const exportPayload = carried.length > 0 ? { ...payloadForSink, events: [...carried, ...payloadForSink.events] } : payloadForSink;
2484
3842
  let sinkFailed = false;
2485
3843
  const sink = session.resolvedConfig.sink;
2486
3844
  const isStreamingMode = session.resolvedConfig.mode === "streaming";
2487
- if (sink.type === "otlp") {
2488
- try {
2489
- const otlpPayload = traceSessionToOtlp(payloadForSink);
2490
- await postOtlpTraces(sink.endpoint, sink.headers, otlpPayload);
2491
- } catch (err) {
2492
- sinkFailed = true;
2493
- const message = err instanceof Error ? err.message : String(err);
2494
- session.errors.push({
2495
- eventId: "sink",
2496
- message,
2497
- type: "sink",
2498
- timestamp: endedAtIso
2499
- });
2500
- }
2501
- } else if (sink.type === "cognipeer" || sink.type === "http") {
3845
+ const terminal = initialStatus !== "paused" && initialStatus !== "in_progress";
3846
+ const exportTargets = [];
3847
+ if (sink.type === "otlp") exportTargets.push({ exporter: sink.exporter, isSink: true });
3848
+ if (!isSubagentTraceScope(session)) {
3849
+ for (const exporter of session.exporters ?? []) exportTargets.push({ exporter, isSink: false });
3850
+ }
3851
+ const unsampled = session.parent !== void 0 && !session.parent.sampled;
3852
+ if (exportTargets.length > 0) {
3853
+ const results = await Promise.all(
3854
+ exportTargets.map(async ({ exporter }) => {
3855
+ if (unsampled) {
3856
+ return { ok: true, skipped: true, reason: "the upstream traceparent is not sampled (sampled=0)", attempts: 0, spans: 0, bytes: 0 };
3857
+ }
3858
+ try {
3859
+ return await exporter.exportSession(exportPayload, {
3860
+ terminal,
3861
+ cancelled: params.cancelled,
3862
+ parent: session.parent
3863
+ });
3864
+ } catch (err) {
3865
+ return { ok: false, attempts: 0, spans: 0, bytes: 0, error: err instanceof Error ? err.message : String(err) };
3866
+ }
3867
+ })
3868
+ );
3869
+ results.forEach((result, index) => {
3870
+ const { exporter, isSink } = exportTargets[index];
3871
+ (session.exportReports ?? (session.exportReports = [])).push({ exporter: exporter.name, endpoint: exporter.endpoint, sink: isSink, terminal, result });
3872
+ if (result.ok) {
3873
+ const rejected = result.partialSuccess?.rejectedSpans ?? 0;
3874
+ if ((rejected > 0 || result.partialSuccess?.message) && typeof console !== "undefined" && typeof console.warn === "function") {
3875
+ const detail = result.partialSuccess?.message ? `: ${result.partialSuccess.message}` : "";
3876
+ console.warn(`[Tracing] OTLP exporter "${exporter.name}": the collector rejected ${rejected} span(s)${detail}`);
3877
+ }
3878
+ return;
3879
+ }
3880
+ const message = result.error ?? "OTLP export failed";
3881
+ if (isSink) {
3882
+ sinkFailed = true;
3883
+ session.errors.push({ eventId: "sink", message, type: "sink", timestamp: endedAtIso });
3884
+ if (typeof console !== "undefined" && typeof console.error === "function") {
3885
+ console.error("[Tracing] OTLP export failed:", message);
3886
+ }
3887
+ } else if (typeof console !== "undefined" && typeof console.warn === "function") {
3888
+ console.warn(`[Tracing] OTLP exporter "${exporter.name}" failed:`, message);
3889
+ }
3890
+ });
3891
+ }
3892
+ if (params.exportOnly) {
3893
+ return buildPayload(payloadForSink.status);
3894
+ }
3895
+ if (sink.type === "cognipeer" || sink.type === "http") {
2502
3896
  try {
2503
3897
  const headers = sink.type === "cognipeer" ? { Authorization: `Bearer ${sink.apiKey}` } : sink.headers;
2504
3898
  if (isStreamingMode && session.sessionStarted) {
@@ -2594,6 +3988,23 @@ async function finalizeTraceSession(session, params = {}) {
2594
3988
  }
2595
3989
  return finalPayload;
2596
3990
  }
3991
+ async function closeTraceContinuation(continuation, params = {}) {
3992
+ const parsed = readTraceContinuation(continuation);
3993
+ if (!parsed) return void 0;
3994
+ const tracing = { ...params.tracing ?? {}, enabled: true };
3995
+ const hasOtlpSink = withDefaults(tracing).sink.type === "otlp";
3996
+ if (!hasOtlpSink && !params.exporters?.length) return void 0;
3997
+ const session = createTraceSession({ tracing }, parsed, { exporters: params.exporters });
3998
+ if (!session) return void 0;
3999
+ replayDeferredTraceEvents(session, params.events);
4000
+ const status = params.status ?? "partial";
4001
+ return finalizeTraceSession(session, {
4002
+ agentRuntime: params.agentRuntime,
4003
+ status,
4004
+ error: status === "error" ? params.error ?? { message: "The run ended in an error before it could be resumed." } : null,
4005
+ exportOnly: true
4006
+ });
4007
+ }
2597
4008
  function sanitizeTracePayload(value) {
2598
4009
  if (value === void 0) return void 0;
2599
4010
  try {
@@ -2633,6 +4044,72 @@ function estimatePayloadBytes(value) {
2633
4044
  }
2634
4045
  }
2635
4046
  }
4047
+
4048
+ // src/providers/wireInfo.ts
4049
+ var WIRE_INFO = Symbol.for("cognipeer.agent-sdk.wireInfo");
4050
+ function usageBasisOf(provider) {
4051
+ switch (provider) {
4052
+ case "anthropic":
4053
+ case "bedrock":
4054
+ return { inputExcludesCache: true };
4055
+ case "vertex":
4056
+ return { outputExcludesReasoning: true };
4057
+ default:
4058
+ return void 0;
4059
+ }
4060
+ }
4061
+ function attachWireInfo(message, info) {
4062
+ const clean = {};
4063
+ if (info.provider) clean.provider = info.provider;
4064
+ if (info.responseId) clean.responseId = info.responseId;
4065
+ if (info.responseModel) clean.responseModel = info.responseModel;
4066
+ if (info.rawFinishReason) clean.rawFinishReason = info.rawFinishReason;
4067
+ if (info.streaming) clean.streaming = true;
4068
+ const basis = info.usageBasis ?? usageBasisOf(info.provider);
4069
+ if (basis) clean.usageBasis = basis;
4070
+ message[WIRE_INFO] = clean;
4071
+ return message;
4072
+ }
4073
+ function wireInfoOf(message) {
4074
+ if (!message || typeof message !== "object") return void 0;
4075
+ return message[WIRE_INFO];
4076
+ }
4077
+
4078
+ // src/utils/traceFacts.ts
4079
+ var nonEmpty2 = (value) => typeof value === "string" && value.trim().length > 0 ? value : void 0;
4080
+ var isRunId = (id) => /^(run-|lc_run)/i.test(id);
4081
+ function providerHintOf(model, response) {
4082
+ const named = getProviderName(model);
4083
+ if (named) return named;
4084
+ const fromWire = wireInfoOf(response)?.provider;
4085
+ if (fromWire) return fromWire;
4086
+ try {
4087
+ return nonEmpty2(getModelCapabilities(model).provider);
4088
+ } catch {
4089
+ return void 0;
4090
+ }
4091
+ }
4092
+ function traceResponseFacts(model, response, rawUsage, streaming) {
4093
+ const wire = wireInfoOf(response);
4094
+ const meta = response?.response_metadata ?? {};
4095
+ const message = response;
4096
+ const idCandidate = nonEmpty2(wire?.responseId) ?? nonEmpty2(meta.id) ?? nonEmpty2(message?.id);
4097
+ const responseId = idCandidate && !isRunId(idCandidate) ? idCandidate : void 0;
4098
+ const responseModel = nonEmpty2(wire?.responseModel) ?? nonEmpty2(meta.model_name) ?? nonEmpty2(meta.model) ?? nonEmpty2(meta.modelName);
4099
+ const rawFinishReason = nonEmpty2(wire?.rawFinishReason) ?? nonEmpty2(meta.stop_reason) ?? nonEmpty2(meta.finish_reason) ?? nonEmpty2(meta.finishReason);
4100
+ const cacheWriteTokens = cacheWriteTokensOf(rawUsage);
4101
+ const provider = providerHintOf(model, response);
4102
+ const isStreaming = streaming ?? wire?.streaming;
4103
+ return {
4104
+ ...provider ? { provider } : {},
4105
+ ...responseId ? { responseId } : {},
4106
+ ...responseModel ? { responseModel } : {},
4107
+ ...rawFinishReason ? { rawFinishReason } : {},
4108
+ ...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {},
4109
+ ...wire?.usageBasis ? { usageBasis: { ...wire.usageBasis } } : {},
4110
+ ...isStreaming ? { streaming: true } : {}
4111
+ };
4112
+ }
2636
4113
  function toMessageUsage(u) {
2637
4114
  return {
2638
4115
  prompt_tokens: u.inputTokens,
@@ -2655,7 +4132,12 @@ function fromNativeProvider(provider, options) {
2655
4132
  if (link.signal) request.signal = link.signal;
2656
4133
  request = await applyTransform(request);
2657
4134
  const response = await provider.complete(request);
2658
- return toBaseChatMessage(response);
4135
+ return attachWireInfo(toBaseChatMessage(response), {
4136
+ provider: provider.providerName,
4137
+ responseId: response.id,
4138
+ responseModel: response.model,
4139
+ rawFinishReason: response.rawFinishReason
4140
+ });
2659
4141
  } finally {
2660
4142
  link.dispose();
2661
4143
  }
@@ -2674,6 +4156,8 @@ function fromNativeProvider(provider, options) {
2674
4156
  let reasoningText = "";
2675
4157
  let finishReason;
2676
4158
  let responseModel;
4159
+ let responseId;
4160
+ let rawFinishReason;
2677
4161
  const toolCallBuffers = /* @__PURE__ */ new Map();
2678
4162
  for await (const chunk of provider.completeStream(request)) {
2679
4163
  if (chunk.delta.content) {
@@ -2681,6 +4165,8 @@ function fromNativeProvider(provider, options) {
2681
4165
  yield chunk.delta.content;
2682
4166
  }
2683
4167
  if (chunk.model) responseModel = chunk.model;
4168
+ if (chunk.id) responseId = chunk.id;
4169
+ if (chunk.rawFinishReason) rawFinishReason = chunk.rawFinishReason;
2684
4170
  if (chunk.finishReason) finishReason = chunk.finishReason;
2685
4171
  if (chunk.delta.reasoning?.blocks?.length) {
2686
4172
  reasoningBlocks = chunk.delta.reasoning.blocks;
@@ -2702,7 +4188,8 @@ function fromNativeProvider(provider, options) {
2702
4188
  id: tc.id,
2703
4189
  name: tc.name ?? "",
2704
4190
  arguments: tc.arguments ?? "",
2705
- ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
4191
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
4192
+ ...tc.idSynthesized ? { idSynthesized: true } : {}
2706
4193
  });
2707
4194
  }
2708
4195
  }
@@ -2726,7 +4213,13 @@ function fromNativeProvider(provider, options) {
2726
4213
  ...responseModel ? { model_name: responseModel } : {}
2727
4214
  };
2728
4215
  }
2729
- yield finalMessage;
4216
+ yield attachWireInfo(finalMessage, {
4217
+ provider: provider.providerName,
4218
+ responseId,
4219
+ responseModel,
4220
+ rawFinishReason,
4221
+ streaming: true
4222
+ });
2730
4223
  } finally {
2731
4224
  link.dispose();
2732
4225
  }
@@ -3100,7 +4593,8 @@ function toBaseChatMessage(response) {
3100
4593
  id: tc.id,
3101
4594
  type: "function",
3102
4595
  function: { name: tc.name, arguments: tc.arguments },
3103
- ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
4596
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
4597
+ ...tc.idSynthesized ? { idSynthesized: true } : {}
3104
4598
  }));
3105
4599
  }
3106
4600
  if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
@@ -3122,7 +4616,8 @@ function assembleMessage(content, toolCalls, usage) {
3122
4616
  id: tc.id,
3123
4617
  type: "function",
3124
4618
  function: { name: tc.name, arguments: tc.arguments },
3125
- ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
4619
+ ...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
4620
+ ...tc.idSynthesized ? { idSynthesized: true } : {}
3126
4621
  }));
3127
4622
  }
3128
4623
  return msg;
@@ -4016,7 +5511,7 @@ var CCRStore = class _CCRStore {
4016
5511
  }
4017
5512
  static hashOf(value) {
4018
5513
  const serialized = typeof value === "string" ? value : JSON.stringify(value);
4019
- return crypto.createHash("sha1").update(serialized).digest("hex").slice(0, 16);
5514
+ return crypto.createHash("sha256").update(serialized).digest("hex").slice(0, 16);
4020
5515
  }
4021
5516
  };
4022
5517
  var DedupTracker = class {
@@ -4029,7 +5524,7 @@ var DedupTracker = class {
4029
5524
  * first time it has been seen.
4030
5525
  */
4031
5526
  checkAndRegister(content, executionId, toolName) {
4032
- const hash = crypto.createHash("sha1").update(content).digest("hex");
5527
+ const hash = crypto.createHash("sha256").update(content).digest("hex");
4033
5528
  const existing = this.seen.get(hash);
4034
5529
  if (!existing) {
4035
5530
  this.seen.set(hash, { executionId, toolName });
@@ -4566,7 +6061,7 @@ function createAgentCoreNode(opts) {
4566
6061
  const actorVersion = runtime.version ?? opts.version;
4567
6062
  let traceToolDefinitions;
4568
6063
  const computeTraceToolDefinitions = (menu) => {
4569
- if (!traceSession || !traceSession.resolvedConfig.logData || menu.length === 0) return void 0;
6064
+ if (!traceSession || !(traceSession.resolvedConfig.logData || traceSession.captureContent) || menu.length === 0) return void 0;
4570
6065
  try {
4571
6066
  const wire = shouldUseStrictToolCalling ? prepareStrictToolMenu(menu).menu : menu;
4572
6067
  return wire.map((tool) => {
@@ -4779,8 +6274,9 @@ ${append}`;
4779
6274
  // outcome, and an "error" status would flip the whole trace session
4780
6275
  // status to error for a run that behaved exactly as configured.
4781
6276
  status: "skipped",
6277
+ skipReason: "blocked",
4782
6278
  model: getModelName(runtime.model || opts.model),
4783
- provider: getProviderName(runtime.model || opts.model),
6279
+ provider: providerHintOf(runtime.model || opts.model),
4784
6280
  messageList: state.messages
4785
6281
  });
4786
6282
  return {
@@ -4809,9 +6305,12 @@ ${append}`;
4809
6305
  for (const key of ["usage", "usage_metadata", "response_metadata"]) {
4810
6306
  if (merged[key] === void 0 && original?.[key] !== void 0) merged[key] = original[key];
4811
6307
  }
6308
+ if (wireInfoOf(merged) === void 0 && wireInfoOf(original) !== void 0) merged[WIRE_INFO] = wireInfoOf(original);
4812
6309
  return merged;
4813
6310
  };
4814
6311
  let response;
6312
+ let sentMessages;
6313
+ let streamedCall = false;
4815
6314
  let modelAttempt = 0;
4816
6315
  const maxModelRetries = host?.maxModelRetries ?? 0;
4817
6316
  const finishCancelledTurn = (partialText) => {
@@ -4825,12 +6324,16 @@ ${append}`;
4825
6324
  // "skipped", not "error": the call did not fail, the caller ended it —
4826
6325
  // and an "error" would flip the whole session to error.
4827
6326
  status: "skipped",
6327
+ // The call reached the provider and was hung up on: still a model call, not a skipped one.
6328
+ skipReason: "cancelled",
6329
+ ...streamedCall ? { streaming: true } : {},
4828
6330
  durationMs: Date.now() - start,
4829
6331
  requestBytes: promptBytes,
4830
6332
  model: getModelName(runtime.model || opts.model),
4831
- provider: getProviderName(runtime.model || opts.model),
6333
+ provider: providerHintOf(runtime.model || opts.model),
4832
6334
  messageList: state.messages,
4833
- toolDefinitions: traceToolDefinitions
6335
+ toolDefinitions: traceToolDefinitions,
6336
+ capture: { input: sentMessages ?? wireMessages, toolDefinitions: traceToolDefinitions }
4834
6337
  });
4835
6338
  onEvent?.({ type: "cancelled", stage: "agent", reason });
4836
6339
  onProgress?.({ stage: "agent", message: "Cancelled", detail: { reason } });
@@ -4846,8 +6349,9 @@ ${append}`;
4846
6349
  label: "Assistant (plugin short-circuit)",
4847
6350
  actor: { scope: "agent", name: actorName, role: "assistant", version: actorVersion },
4848
6351
  status: "skipped",
6352
+ skipReason: "short_circuit",
4849
6353
  model: getModelName(runtime.model || opts.model),
4850
- provider: getProviderName(runtime.model || opts.model),
6354
+ provider: providerHintOf(runtime.model || opts.model),
4851
6355
  messageList: state.messages,
4852
6356
  toolDefinitions: traceToolDefinitions
4853
6357
  });
@@ -4855,8 +6359,10 @@ ${append}`;
4855
6359
  let streamedText = "";
4856
6360
  try {
4857
6361
  const normalizedMessages = normalizeBedrockToolPairing([...wireMessages]);
6362
+ sentMessages = normalizedMessages;
4858
6363
  debugToolPairing(normalizedMessages);
4859
6364
  if (streamingEnabled && typeof modelWithTools.stream === "function") {
6365
+ streamedCall = true;
4860
6366
  let streamedMessage;
4861
6367
  let cutByCancel = false;
4862
6368
  for await (const chunk of modelWithTools.stream(normalizedMessages, invokeParams)) {
@@ -4902,12 +6408,14 @@ ${append}`;
4902
6408
  durationMs: durationMs2,
4903
6409
  requestBytes: promptBytes,
4904
6410
  model: getModelName(runtime.model || opts.model),
4905
- provider: getProviderName(runtime.model || opts.model),
4906
- error: { message: err?.message || String(err), stack: err?.stack },
6411
+ provider: providerHintOf(runtime.model || opts.model),
6412
+ error: traceErrorOf(err),
6413
+ ...streamedCall ? { streaming: true } : {},
4907
6414
  messageList: state.messages,
4908
6415
  toolDefinitions: traceToolDefinitions,
4909
6416
  responseFormat: traceResponseFormat,
4910
- responseFormatStrategy: traceResponseFormatStrategy
6417
+ responseFormatStrategy: traceResponseFormatStrategy,
6418
+ capture: { input: sentMessages ?? wireMessages, toolDefinitions: traceToolDefinitions }
4911
6419
  });
4912
6420
  throw err;
4913
6421
  }
@@ -4960,6 +6468,8 @@ ${append}`;
4960
6468
  const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
4961
6469
  const responseBytes = responsePayload !== void 0 ? estimatePayloadBytes(responsePayload) : void 0;
4962
6470
  const finishReason = response?.response_metadata?.finish_reason ?? response?.response_metadata?.finishReason ?? response?.finishReason;
6471
+ const facts = traceResponseFacts(runtime.model || opts.model, response, rawUsage, streamedCall);
6472
+ const jsonOutput = Boolean(responseFormat) && responseFormat?.response_format?.type !== "text" && responseFormat?.type !== "text";
4963
6473
  recordTraceEvent(traceSession, {
4964
6474
  type: "ai_call",
4965
6475
  label: "Assistant Response",
@@ -4976,11 +6486,13 @@ ${append}`;
4976
6486
  requestBytes: promptBytes,
4977
6487
  responseBytes,
4978
6488
  model: modelName,
4979
- provider: getProviderName(runtime.model || opts.model),
6489
+ ...facts,
6490
+ outputType: jsonOutput ? "json" : "text",
4980
6491
  messageList: messagesWithResponse,
4981
6492
  toolDefinitions: traceToolDefinitions,
4982
6493
  responseFormat: traceResponseFormat,
4983
- responseFormatStrategy: traceResponseFormatStrategy
6494
+ responseFormatStrategy: traceResponseFormatStrategy,
6495
+ capture: { input: sentMessages ?? wireMessages, output: response, toolDefinitions: traceToolDefinitions }
4984
6496
  });
4985
6497
  if (normalized) {
4986
6498
  recordUsage(state, modelName, normalized);
@@ -5006,6 +6518,12 @@ function sameJson(a, b) {
5006
6518
  return false;
5007
6519
  }
5008
6520
  }
6521
+ var idSection = (label, data) => ({
6522
+ kind: "metadata",
6523
+ label,
6524
+ data,
6525
+ identity: true
6526
+ });
5009
6527
  function recordApprovalRequested(session, entry) {
5010
6528
  if (!session || surfacedFromSubagent(entry) || !canPauseForHuman(session)) return;
5011
6529
  const logData = session.resolvedConfig.logData;
@@ -5031,7 +6549,7 @@ function recordApprovalRequested(session, entry) {
5031
6549
  timestamp: entry.requestedAt,
5032
6550
  status: "pending",
5033
6551
  actor: { scope: "agent", name: entry.toolName, role: "approval_request" },
5034
- sections
6552
+ sections: [...sections, idSection("Approval ids", { approvalId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt })]
5035
6553
  });
5036
6554
  }
5037
6555
  function recordHumanDecisions(session, state) {
@@ -5072,7 +6590,14 @@ function recordHumanDecisions(session, state) {
5072
6590
  durationMs: waitedMs(entry.requestedAt, entry.decidedAt),
5073
6591
  status: "success",
5074
6592
  actor: { scope: "human", name: entry.decidedBy || "reviewer", role: "approver" },
5075
- sections
6593
+ sections: [...sections, idSection("Decision ids", {
6594
+ approvalId: entry.id,
6595
+ toolCallId: entry.toolCallId,
6596
+ decision: entry.status,
6597
+ requestedAt: entry.requestedAt,
6598
+ decidedAt: entry.decidedAt,
6599
+ ...waitedMs(entry.requestedAt, entry.decidedAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.decidedAt) } : {}
6600
+ })]
5076
6601
  });
5077
6602
  entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
5078
6603
  }
@@ -5117,7 +6642,14 @@ function recordHumanDecisions(session, state) {
5117
6642
  durationMs: waitedMs(entry.requestedAt, entry.answeredAt),
5118
6643
  status: cancelled ? "skipped" : "success",
5119
6644
  actor: { scope: "human", name: entry.answeredBy || "user", role: "user" },
5120
- sections
6645
+ sections: [...sections, idSection("Answer ids", {
6646
+ questionId: entry.id,
6647
+ toolCallId: entry.toolCallId,
6648
+ status: entry.status,
6649
+ requestedAt: entry.requestedAt,
6650
+ answeredAt: entry.answeredAt,
6651
+ ...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
6652
+ })]
5121
6653
  });
5122
6654
  entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
5123
6655
  }
@@ -5142,7 +6674,7 @@ function recordClientToolRequested(session, entry) {
5142
6674
  timestamp: entry.requestedAt,
5143
6675
  status: "pending",
5144
6676
  actor: { scope: "client", name: clientTool.name, role: "tool" },
5145
- sections
6677
+ sections: [...sections, idSection("Client tool ids", { questionId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt })]
5146
6678
  });
5147
6679
  }
5148
6680
  function readClientTool(entry) {
@@ -5189,7 +6721,14 @@ function recordClientToolResult(session, entry, clientTool, toolHistory) {
5189
6721
  durationMs: waitedMs(entry.requestedAt, entry.answeredAt) ?? ranMs,
5190
6722
  status: failed ? "error" : "success",
5191
6723
  actor: { scope: "client", name: clientTool.name, role: "tool" },
5192
- sections
6724
+ sections: [...sections, idSection("Client tool ids", {
6725
+ questionId: entry.id,
6726
+ toolCallId: entry.toolCallId,
6727
+ status: failed ? "error" : "answered",
6728
+ requestedAt: entry.requestedAt,
6729
+ answeredAt: entry.answeredAt,
6730
+ ...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
6731
+ })]
5193
6732
  });
5194
6733
  }
5195
6734
 
@@ -5295,9 +6834,11 @@ function normalizeToolCall(call) {
5295
6834
  return {
5296
6835
  id: call.id,
5297
6836
  name,
5298
- args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments
6837
+ args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments,
6838
+ ...call.idSynthesized === true ? { idSynthesized: true } : {}
5299
6839
  };
5300
6840
  }
6841
+ var providerToolCallId = (tc) => tc.id && !tc.idSynthesized ? tc.id : void 0;
5301
6842
  function normalizeToolSchema(tool, toolName) {
5302
6843
  const schema = tool.schema;
5303
6844
  if (!schema) return void 0;
@@ -5555,6 +7096,8 @@ function createToolsNode(initialTools, opts) {
5555
7096
  label: `Tool Denied - ${toolName}`,
5556
7097
  actor: { scope: "tool", name: toolName, role: "tool" },
5557
7098
  status: "skipped",
7099
+ skipReason: "denied",
7100
+ toolCallId: providerToolCallId(tc),
5558
7101
  toolDetails,
5559
7102
  toolExecutionId: toolCallId,
5560
7103
  sections: buildToolTraceSections({
@@ -5626,6 +7169,8 @@ function createToolsNode(initialTools, opts) {
5626
7169
  label: `Tool Skipped - ${toolName}`,
5627
7170
  actor: { scope: "tool", name: toolName, role: "tool" },
5628
7171
  status: "skipped",
7172
+ skipReason: "skipped",
7173
+ toolCallId: providerToolCallId(tc),
5629
7174
  toolDetails,
5630
7175
  toolExecutionId: tc.id,
5631
7176
  sections: buildToolTraceSections({
@@ -5762,10 +7307,13 @@ function createToolsNode(initialTools, opts) {
5762
7307
  label: `Tool Error - ${toolName}`,
5763
7308
  actor: { scope: "tool", name: toolName, role: "tool" },
5764
7309
  status: "error",
7310
+ // The tool was not run: an open breaker refused the call.
7311
+ skipReason: "skipped",
7312
+ toolCallId: providerToolCallId(tc),
5765
7313
  requestBytes: inputBytes,
5766
7314
  toolDetails,
5767
7315
  toolExecutionId: toolCallId,
5768
- error: { message: breakerMsg },
7316
+ error: { message: breakerMsg, type: "circuit_breaker_open" },
5769
7317
  sections: buildToolTraceSections({
5770
7318
  args,
5771
7319
  executionId: toolCallId,
@@ -5825,6 +7373,9 @@ function createToolsNode(initialTools, opts) {
5825
7373
  type: "tool_call",
5826
7374
  label: shortCircuitSource === "plugin" ? `Tool Short-Circuited - ${toolName}` : `Tool Execution - ${toolName}`,
5827
7375
  actor: { scope: "tool", name: toolName, role: "tool" },
7376
+ // Answered from the cache or by a plugin: nothing executed.
7377
+ skipReason: "short_circuit",
7378
+ toolCallId: providerToolCallId(tc),
5828
7379
  durationMs: 0,
5829
7380
  requestBytes: inputBytes,
5830
7381
  responseBytes: outputBytes2,
@@ -5860,7 +7411,15 @@ function createToolsNode(initialTools, opts) {
5860
7411
  onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
5861
7412
  const anyTool = tool;
5862
7413
  traceSpanId = traceSession ? generateSpanId() : void 0;
5863
- const callOptions = { cancellationToken, signal: abortSignal, toolCallId, ...traceSpanId ? { traceSpanId } : {} };
7414
+ const callOptions = {
7415
+ cancellationToken,
7416
+ signal: abortSignal,
7417
+ toolCallId,
7418
+ ...traceSpanId ? { traceSpanId } : {},
7419
+ // So the tool can propagate the trace to what it calls (traceparentOf).
7420
+ ...traceSpanId && traceSession?.traceId ? { traceId: traceSession.traceId } : {},
7421
+ ...traceSpanId && traceSession?.parent ? { traceFlags: traceSession.parent.flags } : {}
7422
+ };
5864
7423
  const invokeOnce = async () => {
5865
7424
  if (typeof anyTool.func === "function") return anyTool.func(args, callOptions);
5866
7425
  if (typeof anyTool.invoke === "function") return anyTool.invoke(args, callOptions);
@@ -6046,7 +7605,10 @@ function createToolsNode(initialTools, opts) {
6046
7605
  spanId: traceSpanId,
6047
7606
  label: `Tool Execution - ${toolName}`,
6048
7607
  actor: { scope: "tool", name: toolName, role: "tool" },
6049
- ...reportedFailure ? { status: "error", error: { message: reportedFailure } } : {},
7608
+ ...reportedFailure ? { status: "error", error: { message: reportedFailure, type: "tool_error" } } : {},
7609
+ toolCallId: providerToolCallId(tc),
7610
+ // `output` is already past postToolUse, so a redaction plugin has applied.
7611
+ capture: reportedFailure ? { toolArguments: args } : { toolArguments: args, toolResult: output, hasToolResult: true },
6050
7612
  durationMs,
6051
7613
  requestBytes: inputBytes,
6052
7614
  responseBytes: outputBytes,
@@ -6110,12 +7672,14 @@ function createToolsNode(initialTools, opts) {
6110
7672
  label: `Tool Error - ${toolName}`,
6111
7673
  actor: { scope: "tool", name: toolName, role: "tool" },
6112
7674
  status: "error",
7675
+ toolCallId: providerToolCallId(tc),
7676
+ capture: { toolArguments: args },
6113
7677
  durationMs,
6114
7678
  requestBytes: inputBytes,
6115
7679
  responseBytes: traceSession?.resolvedConfig.logData ? estimatePayloadBytes(errorOutput) : void 0,
6116
7680
  toolDetails,
6117
7681
  toolExecutionId: executionId,
6118
- error: { message, stack: host?.has("postToolUse") ? void 0 : error?.stack },
7682
+ error: { ...traceErrorOf(error), message, stack: host?.has("postToolUse") ? void 0 : error?.stack },
6119
7683
  sections: buildToolTraceSections({
6120
7684
  args: sanitizedArgs,
6121
7685
  durationMs,
@@ -6230,6 +7794,8 @@ function createToolsNode(initialTools, opts) {
6230
7794
  label: `Tool Skipped - ${tc.name}`,
6231
7795
  actor: { scope: "tool", name: tc.name, role: "tool" },
6232
7796
  status: "skipped",
7797
+ skipReason: "skipped",
7798
+ toolCallId: providerToolCallId(tc),
6233
7799
  toolDetails,
6234
7800
  toolExecutionId: tc.id,
6235
7801
  sections: buildToolTraceSections({
@@ -6396,7 +7962,7 @@ function createReflectionNode(opts, resolved) {
6396
7962
  label: "Reflection error",
6397
7963
  actor: { scope: "agent", name: opts.name || "agent", role: "reflection" },
6398
7964
  status: "error",
6399
- error: { message: err?.message || String(err) }
7965
+ error: traceErrorOf(err)
6400
7966
  });
6401
7967
  return {};
6402
7968
  }
@@ -7407,7 +8973,7 @@ function buildSubagentCatalogBlock(subagents, policy, toolNames, opts) {
7407
8973
  // src/plugins/host.ts
7408
8974
  init_content();
7409
8975
  var DEFAULT_PRIORITY = 100;
7410
- var DEFAULT_TIMEOUT_MS = 1e4;
8976
+ var DEFAULT_TIMEOUT_MS2 = 1e4;
7411
8977
  var HOOK_SPECS = {
7412
8978
  sessionStart: { kind: "gate", mutable: ["messages"], collect: ["systemPromptAppend"] },
7413
8979
  userPromptSubmit: {
@@ -7512,7 +9078,7 @@ function collectRegistrations(plugin, registrations, into, orderRef) {
7512
9078
  plugin: plugin.name,
7513
9079
  priority: plugin.priority ?? DEFAULT_PRIORITY,
7514
9080
  failureMode: plugin.failureMode ?? "open",
7515
- timeoutMs: plugin.timeoutMs ?? DEFAULT_TIMEOUT_MS,
9081
+ timeoutMs: plugin.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
7516
9082
  order: orderRef.value++,
7517
9083
  handler
7518
9084
  });
@@ -7567,6 +9133,7 @@ function createPluginHost(plugins = [], options = {}) {
7567
9133
  let contributions = {
7568
9134
  tools: [],
7569
9135
  toolDescriptions: {},
9136
+ traceExporters: [],
7570
9137
  guardrails: [],
7571
9138
  applySystemPrompt: (base) => base,
7572
9139
  applyModelWrappers: (model) => model
@@ -7575,6 +9142,7 @@ function createPluginHost(plugins = [], options = {}) {
7575
9142
  async function runSetup(setupInput) {
7576
9143
  const tools = [];
7577
9144
  const toolDescriptions = {};
9145
+ const traceExporters = [];
7578
9146
  const guardrails = [];
7579
9147
  const promptSteps = [];
7580
9148
  const modelWrappers = [];
@@ -7612,6 +9180,7 @@ function createPluginHost(plugins = [], options = {}) {
7612
9180
  );
7613
9181
  }
7614
9182
  if (plugin.toolDescriptions) Object.assign(toolDescriptions, plugin.toolDescriptions);
9183
+ if (plugin.traceExporters?.length) traceExporters.push(...plugin.traceExporters.filter(Boolean));
7615
9184
  if (plugin.guardrails?.length) guardrails.push(...plugin.guardrails);
7616
9185
  if (typeof plugin.wrapModel === "function") {
7617
9186
  modelWrappers.push({ plugin: plugin.name, wrap: plugin.wrapModel });
@@ -7627,6 +9196,7 @@ function createPluginHost(plugins = [], options = {}) {
7627
9196
  contributions = {
7628
9197
  tools,
7629
9198
  toolDescriptions,
9199
+ traceExporters,
7630
9200
  guardrails,
7631
9201
  applySystemPrompt: (base) => promptSteps.reduce((current, step) => {
7632
9202
  try {
@@ -8650,7 +10220,10 @@ function createAgent(opts) {
8650
10220
  }
8651
10221
  emit({ type: "progress", ...progress });
8652
10222
  };
8653
- const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation));
10223
+ const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation), {
10224
+ exporters: pluginHost.contributions.traceExporters,
10225
+ traceParent: config?.traceParent
10226
+ });
8654
10227
  const ctx = {
8655
10228
  ...input.ctx || {},
8656
10229
  __onEvent: onEvent,
@@ -8802,7 +10375,7 @@ function createAgent(opts) {
8802
10375
  await finalizeTraceSession(traceSession, {
8803
10376
  agentRuntime: runtime,
8804
10377
  status: "error",
8805
- error: { message: err?.message, stack: err?.stack }
10378
+ error: { message: err?.message, stack: err?.stack, name: err?.name }
8806
10379
  });
8807
10380
  await endSession("error", { error: err instanceof Error ? err : new Error(String(err)), state: stateHolder.value });
8808
10381
  if (userTokenCounter) {
@@ -8823,7 +10396,10 @@ function createAgent(opts) {
8823
10396
  const midTurn = pausedForHuman || Boolean(res.ctx?.__needsSummarization);
8824
10397
  await finalizeTraceSession(traceSession, {
8825
10398
  agentRuntime: res.agent || runtime,
8826
- status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success"
10399
+ status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success",
10400
+ // The file says `success` for a cancelled run (it did not fail); the
10401
+ // exported root says `partial`, the old plugin mapping.
10402
+ cancelled: statusFor(res) === "cancelled"
8827
10403
  });
8828
10404
  if (traceSession && midTurn) {
8829
10405
  res.ctx = { ...res.ctx || {}, __traceContinuation: traceContinuationOf(traceSession) };
@@ -9079,9 +10655,10 @@ function createAgentNode(opts) {
9079
10655
  durationMs: durationMs2,
9080
10656
  requestBytes: promptBytes,
9081
10657
  model: getModelName(runtime.model || opts.model),
9082
- provider: getProviderName(runtime.model || opts.model),
9083
- error: { message: err?.message || String(err), stack: err?.stack },
9084
- messageList: promptMessages
10658
+ provider: providerHintOf(runtime.model || opts.model),
10659
+ error: traceErrorOf(err),
10660
+ messageList: promptMessages,
10661
+ capture: { input: promptMessages }
9085
10662
  });
9086
10663
  throw err;
9087
10664
  }
@@ -9092,7 +10669,7 @@ function createAgentNode(opts) {
9092
10669
  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;
9093
10670
  const normalized = normalizeUsage(rawUsage);
9094
10671
  const modelName = getModelName(runtime.model || opts.model) || "unknown_model";
9095
- const providerName = getProviderName(runtime.model || opts.model);
10672
+ const facts = traceResponseFacts(runtime.model || opts.model, response, rawUsage);
9096
10673
  const durationMs = Date.now() - start;
9097
10674
  const shouldLogResponse = !!traceSession && traceSession.resolvedConfig.logData;
9098
10675
  const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
@@ -9109,8 +10686,9 @@ function createAgentNode(opts) {
9109
10686
  requestBytes: promptBytes,
9110
10687
  responseBytes,
9111
10688
  model: modelName,
9112
- provider: providerName,
9113
- messageList: messagesWithResponse
10689
+ ...facts,
10690
+ messageList: messagesWithResponse,
10691
+ capture: { input: promptMessages, output: response }
9114
10692
  });
9115
10693
  if (normalized) {
9116
10694
  recordUsage(state, modelName, normalized);
@@ -9761,7 +11339,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9761
11339
  ];
9762
11340
  const inputTokensEstimate = countApproxTokens(summaryPrompt.map((m) => m.content).join("\n"));
9763
11341
  const modelName = getModelName(model);
9764
- const providerName = getProviderName(model);
11342
+ const providerName = providerHintOf(model);
9765
11343
  const tracingEnabled = Boolean(opts.tracing?.enabled);
9766
11344
  let ctxWithDeferredTrace;
9767
11345
  const traceSummarization = (event) => {
@@ -9792,6 +11370,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9792
11370
  let reasoningTokensActual;
9793
11371
  let fallback = false;
9794
11372
  let summarizerError;
11373
+ let responseFacts;
9795
11374
  const directivesSection = () => ({
9796
11375
  kind: "metadata",
9797
11376
  label: "User directives",
@@ -9833,6 +11412,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9833
11412
  summaryText = renderStructuredSummary(structuredSummary);
9834
11413
  const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
9835
11414
  const normalized = normalizeUsage(rawUsage);
11415
+ responseFacts = traceResponseFacts(model, response, rawUsage);
9836
11416
  if (normalized) {
9837
11417
  inputTokensActual = normalized.prompt_tokens;
9838
11418
  outputTokensActual = normalized.completion_tokens;
@@ -9869,7 +11449,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
9869
11449
  ...droppedDirectives.length > 0 ? { droppedDirectives } : {}
9870
11450
  };
9871
11451
  onEvent?.(errorEvent);
9872
- summarizerError = { message: err?.message || String(err), stack: err?.stack };
11452
+ summarizerError = traceErrorOf(err);
9873
11453
  }
9874
11454
  const toolCallIdToAssistantIdx = /* @__PURE__ */ new Map();
9875
11455
  messages.forEach((m, idx) => {
@@ -10025,10 +11605,16 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
10025
11605
  outputTokens: outputTokensActual ?? outputTokensEstimate,
10026
11606
  cachedInputTokens,
10027
11607
  totalTokens: totalTokensActual,
10028
- ...reasoningTokensActual !== void 0 ? { reasoningTokens: reasoningTokensActual } : {}
11608
+ ...reasoningTokensActual !== void 0 ? { reasoningTokens: reasoningTokensActual } : {},
11609
+ // Which counting rules the usage above follows (only when the provider reported it).
11610
+ ...inputTokensActual !== void 0 && responseFacts?.usageBasis ? { usageBasis: responseFacts.usageBasis } : {},
11611
+ ...inputTokensActual !== void 0 && responseFacts?.cacheWriteTokens ? { cacheWriteTokens: responseFacts.cacheWriteTokens } : {}
10029
11612
  },
11613
+ ...responseFacts?.responseId ? { responseId: responseFacts.responseId } : {},
11614
+ ...responseFacts?.responseModel ? { responseModel: responseFacts.responseModel } : {},
11615
+ ...responseFacts?.rawFinishReason ? { rawFinishReason: responseFacts.rawFinishReason } : {},
10030
11616
  ...modelName ? { model: modelName } : {},
10031
- ...providerName ? { provider: providerName } : {},
11617
+ ...responseFacts?.provider ?? providerName ? { provider: responseFacts?.provider ?? providerName } : {},
10032
11618
  ...summarizerError ? { error: summarizerError } : {},
10033
11619
  sections: [
10034
11620
  ...promptAndOutputSections(),
@@ -11172,7 +12758,15 @@ async function runChild(spec, input, deps, ref, opts) {
11172
12758
  const childDepth = (Number(parentCtx.__delegationDepth) || 0) + 1;
11173
12759
  const parentSession = parentCtx.__traceSession;
11174
12760
  const traced = isTraceSessionOpen(parentSession);
11175
- const agentSpanId = generateSpanId();
12761
+ const sessionStart = traced ? parentSession.startedAt : void 0;
12762
+ const persistedId = opts.record?.agentSpanId;
12763
+ const agentSpanId = typeof persistedId === "string" && /^[0-9a-f]{16}$/.test(persistedId) ? persistedId : generateSpanId();
12764
+ const persistedStart = opts.record?.startedAt;
12765
+ const startValid = typeof persistedStart === "number" && Number.isFinite(persistedStart) && persistedStart > 0 && persistedStart <= start;
12766
+ const runStartedAt = startValid ? Math.min(start, Math.max(persistedStart, sessionStart ?? persistedStart)) : start;
12767
+ const persistedSegments = opts.record?.segments;
12768
+ const segment = (typeof persistedSegments === "number" && Number.isInteger(persistedSegments) && persistedSegments >= 1 && persistedSegments <= 1e3 ? persistedSegments : 0) + 1;
12769
+ const elapsedMs = () => Math.max(0, Date.now() - runStartedAt);
11176
12770
  const parentIterationSpanId = traced ? parentSession.currentIterationSpanId : void 0;
11177
12771
  const traceScope = traced ? createSubagentTraceScope(parentSession, { agentSpanId, name: spec.name, spawnId, mode: spec.mode, hitl: opts.allowHITL, iterations: opts.record?.iterations }) : void 0;
11178
12772
  const recordSegment = (status, info) => {
@@ -11184,7 +12778,7 @@ async function runChild(spec, input, deps, ref, opts) {
11184
12778
  parentSpanId: status === "pending" ? parentIterationSpanId : opts.parentSpanId ?? parentIterationSpanId,
11185
12779
  name: spec.name,
11186
12780
  status,
11187
- durationMs: Date.now() - start,
12781
+ durationMs: elapsedMs(),
11188
12782
  error: info.error,
11189
12783
  info: {
11190
12784
  id: spawnId,
@@ -11194,6 +12788,8 @@ async function runChild(spec, input, deps, ref, opts) {
11194
12788
  depth: childDepth,
11195
12789
  parentToolCallId: opts.parentToolCallId,
11196
12790
  status: info.subagentStatus,
12791
+ // Only a run that paused has more than one segment to tell about.
12792
+ ...segment > 1 || status === "pending" ? { segments: segment } : {},
11197
12793
  ...info.note ? { note: info.note } : {},
11198
12794
  ...spec.metadata ? { metadata: spec.metadata } : {}
11199
12795
  },
@@ -11358,7 +12954,10 @@ async function runChild(spec, input, deps, ref, opts) {
11358
12954
  pendingKind: "approval",
11359
12955
  pendingId: childEntry.id,
11360
12956
  spawnId,
11361
- iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
12957
+ iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0,
12958
+ agentSpanId,
12959
+ startedAt: runStartedAt,
12960
+ segments: segment
11362
12961
  };
11363
12962
  recordSegment("pending", { subagentStatus: "paused", input });
11364
12963
  parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
@@ -11384,7 +12983,10 @@ async function runChild(spec, input, deps, ref, opts) {
11384
12983
  pendingKind: "user_question",
11385
12984
  pendingId: childEntry.id,
11386
12985
  spawnId,
11387
- iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
12986
+ iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0,
12987
+ agentSpanId,
12988
+ startedAt: runStartedAt,
12989
+ segments: segment
11388
12990
  };
11389
12991
  recordSegment("pending", { subagentStatus: "paused", input });
11390
12992
  parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
@@ -12071,6 +13673,30 @@ ${pluginAppend}`;
12071
13673
  };
12072
13674
  }
12073
13675
  }
13676
+ const traceHandoff = {};
13677
+ const noteTraceHandoff = (current) => {
13678
+ traceHandoff.continuation = current.ctx?.__traceContinuation;
13679
+ traceHandoff.events = current.ctx?.[DEFERRED_TRACE_EVENTS_KEY];
13680
+ };
13681
+ const closeDanglingTrace = async (status, error) => {
13682
+ const continuation = traceHandoff.continuation;
13683
+ const events = traceHandoff.events;
13684
+ traceHandoff.continuation = void 0;
13685
+ traceHandoff.events = void 0;
13686
+ if (!continuation) return;
13687
+ try {
13688
+ await closeTraceContinuation(continuation, {
13689
+ tracing: opts.tracing,
13690
+ exporters: pluginHost?.contributions.traceExporters,
13691
+ status,
13692
+ error,
13693
+ agentRuntime: base.__runtime,
13694
+ events
13695
+ });
13696
+ } catch (closeError) {
13697
+ console.warn("[agent-sdk] closing the trace failed:", closeError);
13698
+ }
13699
+ };
12074
13700
  try {
12075
13701
  const toolSet = buildInvokeToolSet();
12076
13702
  const stateRef = toolSet.stateRef;
@@ -12149,11 +13775,15 @@ ${pluginAppend}`;
12149
13775
  const result = await trySummarize(state, rawMessages, stateRef);
12150
13776
  state = result.state;
12151
13777
  rawMessages = result.rawMessages;
13778
+ noteTraceHandoff(state);
12152
13779
  if (result.compressed) continue;
12153
13780
  }
12154
13781
  const modelMessages = buildModelMessages(state, resolved);
13782
+ traceHandoff.continuation = void 0;
13783
+ traceHandoff.events = void 0;
12155
13784
  const res = await base.invoke({ ...state, messages: modelMessages }, turnConfig);
12156
13785
  lastResult = res;
13786
+ noteTraceHandoff(res.state ?? state);
12157
13787
  const currentSummaries = state.summaries;
12158
13788
  const currentSummaryRecords = state.summaryRecords;
12159
13789
  const currentPlan = state.plan;
@@ -12180,6 +13810,7 @@ ${pluginAppend}`;
12180
13810
  const result = await trySummarize(state, rawMessages, stateRef);
12181
13811
  state = result.state;
12182
13812
  rawMessages = result.rawMessages;
13813
+ noteTraceHandoff(state);
12183
13814
  continue;
12184
13815
  }
12185
13816
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
@@ -12191,6 +13822,7 @@ ${pluginAppend}`;
12191
13822
  const result = await trySummarize(state, rawMessages, stateRef);
12192
13823
  state = result.state;
12193
13824
  rawMessages = result.rawMessages;
13825
+ noteTraceHandoff(state);
12194
13826
  if (result.compressed) continue;
12195
13827
  }
12196
13828
  }
@@ -12201,6 +13833,7 @@ ${pluginAppend}`;
12201
13833
  lastResult = res;
12202
13834
  }
12203
13835
  if (state.ctx?.[DEFERRED_TRACE_EVENTS_KEY]) {
13836
+ traceHandoff.events = state.ctx[DEFERRED_TRACE_EVENTS_KEY];
12204
13837
  const ctx = { ...state.ctx || {} };
12205
13838
  delete ctx[DEFERRED_TRACE_EVENTS_KEY];
12206
13839
  state = { ...state, ctx };
@@ -12220,8 +13853,12 @@ ${pluginAppend}`;
12220
13853
  const strippedCtx = { ...endCtx };
12221
13854
  delete strippedCtx.__traceContinuation;
12222
13855
  lastResult = { ...lastResult, state: { ...lastResult.state, ctx: strippedCtx } };
13856
+ traceHandoff.continuation = endCtx.__traceContinuation;
13857
+ await closeDanglingTrace("success");
12223
13858
  }
12224
13859
  }
13860
+ traceHandoff.continuation = void 0;
13861
+ traceHandoff.events = void 0;
12225
13862
  if (skillsEnabled && lastResult.state) {
12226
13863
  const persisted = skillStateFromRegistry(toolSet.skillRegistryRef);
12227
13864
  if (persisted) {
@@ -12267,6 +13904,11 @@ ${pluginAppend}`;
12267
13904
  await endSession(endStatus, { result: lastResult });
12268
13905
  return lastResult;
12269
13906
  } catch (err) {
13907
+ await closeDanglingTrace("error", {
13908
+ message: err instanceof Error ? err.message : String(err),
13909
+ stack: err instanceof Error ? err.stack : void 0,
13910
+ name: err instanceof Error ? err.name : void 0
13911
+ });
12270
13912
  await endSession("error", { error: err instanceof Error ? err : new Error(String(err)) });
12271
13913
  throw err;
12272
13914
  }
@@ -13183,7 +14825,7 @@ function isHookImplemented(hook) {
13183
14825
  // src/plugins/builtin/guardrail.ts
13184
14826
  init_content();
13185
14827
  var ALLOW = { action: "allow" };
13186
- var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
14828
+ var RETRYABLE_STATUS2 = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
13187
14829
  var RetryableGuardrailError = class extends Error {
13188
14830
  constructor(message) {
13189
14831
  super(message);
@@ -13281,7 +14923,7 @@ function httpGuardrail(options) {
13281
14923
  } catch {
13282
14924
  }
13283
14925
  const message = `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ""}${text ? ` - ${text.slice(0, 200)}` : ""}`;
13284
- if (RETRYABLE_STATUS.has(response.status)) throw new RetryableGuardrailError(message);
14926
+ if (RETRYABLE_STATUS2.has(response.status)) throw new RetryableGuardrailError(message);
13285
14927
  throw new Error(message);
13286
14928
  }
13287
14929
  return response.json();
@@ -13388,9 +15030,9 @@ function createGuardrailPlugin(options) {
13388
15030
  });
13389
15031
  const resolved = verdict ?? ALLOW;
13390
15032
  if (resolved.raw?.disabled === true) {
13391
- const warned = (_b = ctx.store).__disabledWarned ?? (_b.__disabledWarned = /* @__PURE__ */ new Set());
13392
- if (!warned.has(request.phase)) {
13393
- warned.add(request.phase);
15033
+ const warned2 = (_b = ctx.store).__disabledWarned ?? (_b.__disabledWarned = /* @__PURE__ */ new Set());
15034
+ if (!warned2.has(request.phase)) {
15035
+ warned2.add(request.phase);
13394
15036
  ctx.logger.warn(
13395
15037
  `guardrail reports it is not active for the "${request.phase}" surface; nothing is being enforced there`
13396
15038
  );
@@ -13887,7 +15529,7 @@ function safeJson(value) {
13887
15529
  function matches(pattern, toolName) {
13888
15530
  return typeof pattern === "string" ? pattern === toolName : pattern.test(toolName);
13889
15531
  }
13890
- function asObject(args) {
15532
+ function asObject2(args) {
13891
15533
  return args && typeof args === "object" ? args : {};
13892
15534
  }
13893
15535
  function toolPolicy(config = {}) {
@@ -13908,7 +15550,7 @@ function toolPolicy(config = {}) {
13908
15550
  hooks: {
13909
15551
  preToolUse: ({ toolName, args }, ctx) => {
13910
15552
  var _a;
13911
- const argObject = asObject(args);
15553
+ const argObject = asObject2(args);
13912
15554
  const isControlPlane = CONTROL_PLANE_TOOL_NAMES.includes(toolName);
13913
15555
  const allowListApplies = !isControlPlane || config.governControlPlaneTools === true;
13914
15556
  if (config.allowOnly && allowListApplies && !config.allowOnly.some((pattern) => matches(pattern, toolName))) {
@@ -13970,7 +15612,7 @@ function pathSandbox(config) {
13970
15612
  hooks: {
13971
15613
  preToolUse: ({ toolName, args }) => {
13972
15614
  if (config.tools && !config.tools.some((pattern) => matches(pattern, toolName))) return void 0;
13973
- const argObject = asObject(args);
15615
+ const argObject = asObject2(args);
13974
15616
  for (const key of argNames) {
13975
15617
  const value = argObject[key];
13976
15618
  if (typeof value !== "string" || value.length === 0) continue;
@@ -14738,7 +16380,7 @@ function mcp(config) {
14738
16380
  }
14739
16381
 
14740
16382
  // src/plugins/builtin/rateLimit.ts
14741
- function sleep(ms, signal) {
16383
+ function sleep2(ms, signal) {
14742
16384
  return new Promise((resolve) => {
14743
16385
  let timer;
14744
16386
  const done = () => {
@@ -14795,7 +16437,7 @@ function rateLimit(config = {}) {
14795
16437
  while (!attempt.ok) {
14796
16438
  const remaining = deadline - Date.now();
14797
16439
  if (!Number.isFinite(attempt.waitMs) || attempt.waitMs > remaining) break;
14798
- await sleep(Math.max(1, attempt.waitMs), ctx.signal);
16440
+ await sleep2(Math.max(1, attempt.waitMs), ctx.signal);
14799
16441
  if (ctx.signal?.aborted) break;
14800
16442
  attempt = consume(applicable);
14801
16443
  }
@@ -15891,18 +17533,21 @@ function langfuseTracing(config = {}) {
15891
17533
  }
15892
17534
 
15893
17535
  // src/plugins/builtin/otel.ts
15894
- function toSessionStatus(status) {
15895
- if (status === "success") return "success";
15896
- if (status === "error") return "error";
15897
- return status === "paused" ? "in_progress" : "partial";
15898
- }
15899
- function otelTracing(config) {
15900
- const endpoint = config.endpoint?.trim();
15901
- if (!endpoint) {
17536
+ function otelTracing(config = {}) {
17537
+ if (config.endpoint !== void 0 && !config.endpoint.trim()) {
15902
17538
  throw new Error("[agent-sdk] otelTracing requires a non-empty `endpoint`.");
15903
17539
  }
17540
+ const name = config.name ?? "otel-tracing";
17541
+ let exporter;
17542
+ try {
17543
+ exporter = createOtlpExporter({ ...config, endpoint: config.endpoint?.trim(), name });
17544
+ } catch {
17545
+ throw new Error(
17546
+ "[agent-sdk] otelTracing requires a non-empty `endpoint` (or OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_TRACES_ENDPOINT in the environment)."
17547
+ );
17548
+ }
15904
17549
  return {
15905
- name: config.name ?? "otel-tracing",
17550
+ name,
15906
17551
  // Registers only the `sessionEnd` observer, and observers run concurrently,
15907
17552
  // so this number orders nothing at runtime. It is set above checkpointing
15908
17553
  // (900) to record intent: this plugin is the last thing interested in the
@@ -15910,8 +17555,9 @@ function otelTracing(config) {
15910
17555
  priority: 950,
15911
17556
  // Observability. A dropped export is a reporting gap, never a safety hole.
15912
17557
  failureMode: "open",
17558
+ traceExporters: [exporter],
15913
17559
  hooks: {
15914
- sessionEnd: async ({ status, durationMs, error }, ctx) => {
17560
+ sessionEnd: async (_event, ctx) => {
15915
17561
  const state = ctx.state;
15916
17562
  const session = state.ctx?.__traceSession;
15917
17563
  if (isSubagentTraceScope(session)) return;
@@ -15921,57 +17567,29 @@ function otelTracing(config) {
15921
17567
  ctx.emit({ type: "metadata", otelTracing: { exported: false, reason: message } });
15922
17568
  return;
15923
17569
  }
15924
- const endedAtMs = Date.now();
15925
- const startedAtIso = new Date(session.startedAt).toISOString();
15926
- const errors = error ? [...session.errors, { eventId: "session", message: error.message, stack: error.stack, type: "session" }] : session.errors;
15927
- const payload = {
15928
- sessionId: session.sessionId,
15929
- traceId: session.traceId,
15930
- rootSpanId: session.rootSpanId,
15931
- threadId: session.threadId,
15932
- startedAt: startedAtIso,
15933
- endedAt: new Date(endedAtMs).toISOString(),
15934
- durationMs: durationMs ?? endedAtMs - session.startedAt,
15935
- // `service.name` is read off `agent.name` inside the conversion, so
15936
- // the override is applied here rather than by editing spans after.
15937
- agent: {
15938
- ...session.agentInfo ?? {},
15939
- name: config.serviceName ?? session.agentInfo?.name ?? session.configAgentName ?? ctx.agentName
15940
- },
15941
- metadata: session.configMetadata,
15942
- // Carried only to satisfy the type: `traceSessionToOtlp` reads the
15943
- // events, summary and identifiers, never the sink snapshot.
15944
- config: { enabled: true, logData: session.resolvedConfig.logData, sink: { type: "otlp", endpoint } },
15945
- summary: session.summary,
15946
- events: session.events,
15947
- status: toSessionStatus(status),
15948
- errors
15949
- };
15950
- try {
15951
- const fetchFn = typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0;
15952
- if (!fetchFn) {
15953
- ctx.logger.warn("otelTracing needs fetch to be available in this runtime; export skipped.");
15954
- return;
15955
- }
15956
- const response = await fetchFn(endpoint, {
15957
- method: "POST",
15958
- headers: { "content-type": "application/json", ...config.headers ?? {} },
15959
- body: JSON.stringify(traceSessionToOtlp(payload)),
15960
- // The run is over, but a host that cancelled it should not be made
15961
- // to wait on a collector that is refusing to answer.
15962
- signal: ctx.signal
15963
- });
15964
- if (!response.ok) {
15965
- ctx.logger.warn(`otelTracing export returned HTTP ${response.status}.`);
15966
- return;
15967
- }
15968
- ctx.emit({
15969
- type: "metadata",
15970
- otelTracing: { exported: true, endpoint, spans: session.events.length + 1 }
15971
- });
15972
- } catch (err) {
15973
- ctx.logger.warn("otelTracing export failed:", err instanceof Error ? err.message : err);
17570
+ const reports = (session.exportReports ?? []).filter((report2) => !report2.sink && report2.exporter === name);
17571
+ const report = reports[reports.length - 1];
17572
+ if (!report) return;
17573
+ const { result } = report;
17574
+ if (!result.ok) {
17575
+ ctx.logger.warn(`otelTracing export failed: ${result.error ?? "unknown error"}`);
17576
+ return;
17577
+ }
17578
+ if (result.skipped) {
17579
+ ctx.emit({ type: "metadata", otelTracing: { exported: false, reason: result.reason ?? "nothing to export" } });
17580
+ return;
15974
17581
  }
17582
+ ctx.emit({
17583
+ type: "metadata",
17584
+ otelTracing: {
17585
+ exported: true,
17586
+ endpoint: report.endpoint,
17587
+ spans: result.spans,
17588
+ terminal: report.terminal,
17589
+ // A 200 that refused some spans: the collector's count and message.
17590
+ ...result.partialSuccess ? { rejectedSpans: result.partialSuccess.rejectedSpans, ...result.partialSuccess.message ? { rejectionMessage: result.partialSuccess.message } : {} } : {}
17591
+ }
17592
+ });
15975
17593
  }
15976
17594
  }
15977
17595
  };
@@ -19007,9 +20625,9 @@ function mapAnthropicStopReason(reason) {
19007
20625
  return "stop";
19008
20626
  }
19009
20627
  }
19010
- function safeJsonParse(str) {
20628
+ function safeJsonParse(str2) {
19011
20629
  try {
19012
- return JSON.parse(str);
20630
+ return JSON.parse(str2);
19013
20631
  } catch {
19014
20632
  return {};
19015
20633
  }
@@ -19879,9 +21497,9 @@ function mediaTypeToFormat(mediaType) {
19879
21497
  };
19880
21498
  return map[mediaType] ?? "png";
19881
21499
  }
19882
- function safeJsonParse2(str) {
21500
+ function safeJsonParse2(str2) {
19883
21501
  try {
19884
- return JSON.parse(str);
21502
+ return JSON.parse(str2);
19885
21503
  } catch {
19886
21504
  return {};
19887
21505
  }
@@ -20278,10 +21896,13 @@ var VertexProvider = class extends BaseProvider {
20278
21896
  textParts.push(part.text);
20279
21897
  }
20280
21898
  } else if (part.functionCall) {
21899
+ const suppliedId = typeof part.functionCall.id === "string" && part.functionCall.id ? part.functionCall.id : void 0;
21900
+ const position = toolCallIdx++;
20281
21901
  toolCalls.push({
20282
- id: `call_${toolCallIdx++}`,
21902
+ id: suppliedId ?? `call_${position}`,
20283
21903
  name: part.functionCall.name,
20284
21904
  arguments: JSON.stringify(part.functionCall.args ?? {}),
21905
+ ...suppliedId ? {} : { idSynthesized: true },
20285
21906
  ...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
20286
21907
  });
20287
21908
  }
@@ -20321,12 +21942,15 @@ var VertexProvider = class extends BaseProvider {
20321
21942
  }
20322
21943
  } else if (part.functionCall) {
20323
21944
  if (!delta.toolCalls) delta.toolCalls = [];
21945
+ const suppliedId = typeof part.functionCall.id === "string" && part.functionCall.id ? part.functionCall.id : void 0;
21946
+ const position = counter.next++;
20324
21947
  delta.toolCalls.push({
20325
21948
  // Unique across the whole stream: the adapter merges chunks by id.
20326
- id: `call_${counter.next}`,
20327
- index: counter.next++,
21949
+ id: suppliedId ?? `call_${position}`,
21950
+ index: position,
20328
21951
  name: part.functionCall.name,
20329
21952
  arguments: JSON.stringify(part.functionCall.args ?? {}),
21953
+ ...suppliedId ? {} : { idSynthesized: true },
20330
21954
  ...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
20331
21955
  });
20332
21956
  }
@@ -20379,12 +22003,12 @@ function mapGeminiFinishReason(reason) {
20379
22003
  return "stop";
20380
22004
  }
20381
22005
  }
20382
- function base64url(str) {
20383
- return Buffer.from(str).toString("base64url");
22006
+ function base64url(str2) {
22007
+ return Buffer.from(str2).toString("base64url");
20384
22008
  }
20385
- function safeJsonParse3(str) {
22009
+ function safeJsonParse3(str2) {
20386
22010
  try {
20387
- return JSON.parse(str);
22011
+ return JSON.parse(str2);
20388
22012
  } catch {
20389
22013
  return {};
20390
22014
  }
@@ -20429,6 +22053,7 @@ exports.DEFAULT_SUBAGENT_TOOL_NAMES = DEFAULT_SUBAGENT_TOOL_NAMES;
20429
22053
  exports.DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS = DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS;
20430
22054
  exports.DELEGATION_TOOL_NAMES = DELEGATION_TOOL_NAMES;
20431
22055
  exports.DedupTracker = DedupTracker;
22056
+ exports.GENAI_SEMCONV_COMMIT = GENAI_SEMCONV_COMMIT;
20432
22057
  exports.GuardrailPhase = GuardrailPhase;
20433
22058
  exports.HOOK_CONTRACT_VERSION = HOOK_CONTRACT_VERSION;
20434
22059
  exports.HOOK_NAMES = HOOK_NAMES;
@@ -20469,6 +22094,7 @@ exports.canSpawn = canSpawn;
20469
22094
  exports.captureSnapshot = captureSnapshot;
20470
22095
  exports.checkpointing = checkpointing;
20471
22096
  exports.clearLearnedModelRules = clearLearnedModelRules;
22097
+ exports.closeTraceContinuation = closeTraceContinuation;
20472
22098
  exports.codePresenceRule = codePresenceRule;
20473
22099
  exports.coerceToolArgs = coerceToolArgs;
20474
22100
  exports.cognipeerGuardrail = cognipeerGuardrail;
@@ -20503,6 +22129,7 @@ exports.createJsonGuardrail = createJsonGuardrail;
20503
22129
  exports.createManageTodoListAliasTool = createManageTodoListAliasTool;
20504
22130
  exports.createManageTodoTool = createManageTodoTool;
20505
22131
  exports.createOpenSkillTool = createOpenSkillTool;
22132
+ exports.createOtlpExporter = createOtlpExporter;
20506
22133
  exports.createParallelTool = createParallelTool;
20507
22134
  exports.createPluginHost = createPluginHost;
20508
22135
  exports.createProvider = createProvider;
@@ -20539,6 +22166,8 @@ exports.extractMessageText = extractMessageText;
20539
22166
  exports.fileCheckpointStore = fileCheckpointStore;
20540
22167
  exports.fileSink = fileSink;
20541
22168
  exports.findSubagent = findSubagent;
22169
+ exports.foldSupersededSpans = foldSupersededSpans;
22170
+ exports.formatTraceparent = formatTraceparent;
20542
22171
  exports.formatZodError = formatZodError;
20543
22172
  exports.fromLangchainModel = fromLangchainModel;
20544
22173
  exports.fromLangchainTools = fromLangchainTools;
@@ -20586,6 +22215,7 @@ exports.outputGuard = outputGuard;
20586
22215
  exports.parseApprovalDecision = parseApprovalDecision;
20587
22216
  exports.parseModelError = parseModelError;
20588
22217
  exports.parseSkillFrontmatter = parseSkillFrontmatter;
22218
+ exports.parseTraceparent = parseTraceparent;
20589
22219
  exports.pathSandbox = pathSandbox;
20590
22220
  exports.piiRedaction = piiRedaction;
20591
22221
  exports.pluginCapabilities = pluginCapabilities;
@@ -20640,6 +22270,7 @@ exports.toolPolicy = toolPolicy;
20640
22270
  exports.traceContinuationOf = traceContinuationOf;
20641
22271
  exports.traceSectionsFromMessages = traceSectionsFromMessages;
20642
22272
  exports.traceSessionToOtlp = traceSessionToOtlp;
22273
+ exports.traceparentOf = traceparentOf;
20643
22274
  exports.validateReasoningConfig = validateReasoningConfig;
20644
22275
  exports.validateToolArgs = validateToolArgs;
20645
22276
  exports.webhookApproval = webhookApproval;