@cognipeer/agent-sdk 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +2012 -373
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +581 -40
- package/dist/index.d.ts +581 -40
- package/dist/index.mjs +2006 -374
- package/dist/index.mjs.map +1 -1
- package/dist/{model-rules-Bg9nSqyN.d.cts → model-rules--welxWDw.d.cts} +2 -0
- package/dist/{model-rules-Bg9nSqyN.d.ts → model-rules--welxWDw.d.ts} +2 -0
- package/dist/model-rules.d.cts +1 -1
- package/dist/model-rules.d.ts +1 -1
- package/package.json +2 -1
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.19.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" || event.status === "running"))
|
|
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(
|
|
1263
|
-
return { type: "otlp",
|
|
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
|
|
1337
|
-
if (
|
|
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
|
|
1344
|
-
if (
|
|
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
|
|
1352
|
-
if (
|
|
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
|
|
1384
|
-
if (
|
|
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
|
|
1403
|
-
if (
|
|
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
|
|
1466
|
-
if (
|
|
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,
|
|
2919
|
+
constructor(status, message, retryAfterMs2) {
|
|
1511
2920
|
super(message);
|
|
1512
2921
|
this.name = "RetryableHttpError";
|
|
1513
2922
|
this.status = status;
|
|
1514
|
-
this.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
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
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
|
-
|
|
1776
|
-
const
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
"
|
|
1782
|
-
...
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,19 @@ 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(
|
|
3770
|
+
(event, i) => !(event.spanId && (event.status === "pending" || event.status === "running") && winner.get(event.spanId) !== i)
|
|
3771
|
+
);
|
|
3772
|
+
}
|
|
2417
3773
|
function recordOrDeferTraceEvent(ctx, event, options) {
|
|
2418
3774
|
const session = ctx?.__traceSession;
|
|
2419
3775
|
if (isTraceSessionOpen(session)) {
|
|
@@ -2424,7 +3780,8 @@ function recordOrDeferTraceEvent(ctx, event, options) {
|
|
|
2424
3780
|
const held = Array.isArray(ctx?.[DEFERRED_TRACE_EVENTS_KEY]) ? ctx[DEFERRED_TRACE_EVENTS_KEY] : [];
|
|
2425
3781
|
return {
|
|
2426
3782
|
...ctx || {},
|
|
2427
|
-
|
|
3783
|
+
// `capture` (content for exporters) is never parked on ctx, which callers persist.
|
|
3784
|
+
[DEFERRED_TRACE_EVENTS_KEY]: [...held, { ...event, capture: void 0, timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString() }]
|
|
2428
3785
|
};
|
|
2429
3786
|
}
|
|
2430
3787
|
function replayDeferredTraceEvents(session, deferred) {
|
|
@@ -2458,6 +3815,7 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
2458
3815
|
message: params.error.message || "Unknown error",
|
|
2459
3816
|
stack: params.error.stack,
|
|
2460
3817
|
type: "session",
|
|
3818
|
+
...params.error.name ? { errorName: params.error.name } : {},
|
|
2461
3819
|
timestamp: endedAtIso
|
|
2462
3820
|
});
|
|
2463
3821
|
}
|
|
@@ -2481,24 +3839,62 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
2481
3839
|
...(session.part ?? 1) > 1 ? { continuation: { part: session.part, firstSequence: (session.sequenceOffset ?? 0) + 1 } } : {}
|
|
2482
3840
|
});
|
|
2483
3841
|
const payloadForSink = buildPayload(initialStatus);
|
|
3842
|
+
const carried = session.carriedSpans ?? [];
|
|
3843
|
+
const exportPayload = carried.length > 0 ? { ...payloadForSink, events: [...carried, ...payloadForSink.events] } : payloadForSink;
|
|
2484
3844
|
let sinkFailed = false;
|
|
2485
3845
|
const sink = session.resolvedConfig.sink;
|
|
2486
3846
|
const isStreamingMode = session.resolvedConfig.mode === "streaming";
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
3847
|
+
const terminal = initialStatus !== "paused" && initialStatus !== "in_progress";
|
|
3848
|
+
const exportTargets = [];
|
|
3849
|
+
if (sink.type === "otlp") exportTargets.push({ exporter: sink.exporter, isSink: true });
|
|
3850
|
+
if (!isSubagentTraceScope(session)) {
|
|
3851
|
+
for (const exporter of session.exporters ?? []) exportTargets.push({ exporter, isSink: false });
|
|
3852
|
+
}
|
|
3853
|
+
const unsampled = session.parent !== void 0 && !session.parent.sampled;
|
|
3854
|
+
if (exportTargets.length > 0) {
|
|
3855
|
+
const results = await Promise.all(
|
|
3856
|
+
exportTargets.map(async ({ exporter }) => {
|
|
3857
|
+
if (unsampled) {
|
|
3858
|
+
return { ok: true, skipped: true, reason: "the upstream traceparent is not sampled (sampled=0)", attempts: 0, spans: 0, bytes: 0 };
|
|
3859
|
+
}
|
|
3860
|
+
try {
|
|
3861
|
+
return await exporter.exportSession(exportPayload, {
|
|
3862
|
+
terminal,
|
|
3863
|
+
cancelled: params.cancelled,
|
|
3864
|
+
parent: session.parent
|
|
3865
|
+
});
|
|
3866
|
+
} catch (err) {
|
|
3867
|
+
return { ok: false, attempts: 0, spans: 0, bytes: 0, error: err instanceof Error ? err.message : String(err) };
|
|
3868
|
+
}
|
|
3869
|
+
})
|
|
3870
|
+
);
|
|
3871
|
+
results.forEach((result, index) => {
|
|
3872
|
+
const { exporter, isSink } = exportTargets[index];
|
|
3873
|
+
(session.exportReports ?? (session.exportReports = [])).push({ exporter: exporter.name, endpoint: exporter.endpoint, sink: isSink, terminal, result });
|
|
3874
|
+
if (result.ok) {
|
|
3875
|
+
const rejected = result.partialSuccess?.rejectedSpans ?? 0;
|
|
3876
|
+
if ((rejected > 0 || result.partialSuccess?.message) && typeof console !== "undefined" && typeof console.warn === "function") {
|
|
3877
|
+
const detail = result.partialSuccess?.message ? `: ${result.partialSuccess.message}` : "";
|
|
3878
|
+
console.warn(`[Tracing] OTLP exporter "${exporter.name}": the collector rejected ${rejected} span(s)${detail}`);
|
|
3879
|
+
}
|
|
3880
|
+
return;
|
|
3881
|
+
}
|
|
3882
|
+
const message = result.error ?? "OTLP export failed";
|
|
3883
|
+
if (isSink) {
|
|
3884
|
+
sinkFailed = true;
|
|
3885
|
+
session.errors.push({ eventId: "sink", message, type: "sink", timestamp: endedAtIso });
|
|
3886
|
+
if (typeof console !== "undefined" && typeof console.error === "function") {
|
|
3887
|
+
console.error("[Tracing] OTLP export failed:", message);
|
|
3888
|
+
}
|
|
3889
|
+
} else if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
3890
|
+
console.warn(`[Tracing] OTLP exporter "${exporter.name}" failed:`, message);
|
|
3891
|
+
}
|
|
3892
|
+
});
|
|
3893
|
+
}
|
|
3894
|
+
if (params.exportOnly) {
|
|
3895
|
+
return buildPayload(payloadForSink.status);
|
|
3896
|
+
}
|
|
3897
|
+
if (sink.type === "cognipeer" || sink.type === "http") {
|
|
2502
3898
|
try {
|
|
2503
3899
|
const headers = sink.type === "cognipeer" ? { Authorization: `Bearer ${sink.apiKey}` } : sink.headers;
|
|
2504
3900
|
if (isStreamingMode && session.sessionStarted) {
|
|
@@ -2594,6 +3990,23 @@ async function finalizeTraceSession(session, params = {}) {
|
|
|
2594
3990
|
}
|
|
2595
3991
|
return finalPayload;
|
|
2596
3992
|
}
|
|
3993
|
+
async function closeTraceContinuation(continuation, params = {}) {
|
|
3994
|
+
const parsed = readTraceContinuation(continuation);
|
|
3995
|
+
if (!parsed) return void 0;
|
|
3996
|
+
const tracing = { ...params.tracing ?? {}, enabled: true };
|
|
3997
|
+
const hasOtlpSink = withDefaults(tracing).sink.type === "otlp";
|
|
3998
|
+
if (!hasOtlpSink && !params.exporters?.length) return void 0;
|
|
3999
|
+
const session = createTraceSession({ tracing }, parsed, { exporters: params.exporters });
|
|
4000
|
+
if (!session) return void 0;
|
|
4001
|
+
replayDeferredTraceEvents(session, params.events);
|
|
4002
|
+
const status = params.status ?? "partial";
|
|
4003
|
+
return finalizeTraceSession(session, {
|
|
4004
|
+
agentRuntime: params.agentRuntime,
|
|
4005
|
+
status,
|
|
4006
|
+
error: status === "error" ? params.error ?? { message: "The run ended in an error before it could be resumed." } : null,
|
|
4007
|
+
exportOnly: true
|
|
4008
|
+
});
|
|
4009
|
+
}
|
|
2597
4010
|
function sanitizeTracePayload(value) {
|
|
2598
4011
|
if (value === void 0) return void 0;
|
|
2599
4012
|
try {
|
|
@@ -2633,6 +4046,72 @@ function estimatePayloadBytes(value) {
|
|
|
2633
4046
|
}
|
|
2634
4047
|
}
|
|
2635
4048
|
}
|
|
4049
|
+
|
|
4050
|
+
// src/providers/wireInfo.ts
|
|
4051
|
+
var WIRE_INFO = Symbol.for("cognipeer.agent-sdk.wireInfo");
|
|
4052
|
+
function usageBasisOf(provider) {
|
|
4053
|
+
switch (provider) {
|
|
4054
|
+
case "anthropic":
|
|
4055
|
+
case "bedrock":
|
|
4056
|
+
return { inputExcludesCache: true };
|
|
4057
|
+
case "vertex":
|
|
4058
|
+
return { outputExcludesReasoning: true };
|
|
4059
|
+
default:
|
|
4060
|
+
return void 0;
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
function attachWireInfo(message, info) {
|
|
4064
|
+
const clean = {};
|
|
4065
|
+
if (info.provider) clean.provider = info.provider;
|
|
4066
|
+
if (info.responseId) clean.responseId = info.responseId;
|
|
4067
|
+
if (info.responseModel) clean.responseModel = info.responseModel;
|
|
4068
|
+
if (info.rawFinishReason) clean.rawFinishReason = info.rawFinishReason;
|
|
4069
|
+
if (info.streaming) clean.streaming = true;
|
|
4070
|
+
const basis = info.usageBasis ?? usageBasisOf(info.provider);
|
|
4071
|
+
if (basis) clean.usageBasis = basis;
|
|
4072
|
+
message[WIRE_INFO] = clean;
|
|
4073
|
+
return message;
|
|
4074
|
+
}
|
|
4075
|
+
function wireInfoOf(message) {
|
|
4076
|
+
if (!message || typeof message !== "object") return void 0;
|
|
4077
|
+
return message[WIRE_INFO];
|
|
4078
|
+
}
|
|
4079
|
+
|
|
4080
|
+
// src/utils/traceFacts.ts
|
|
4081
|
+
var nonEmpty2 = (value) => typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
4082
|
+
var isRunId = (id) => /^(run-|lc_run)/i.test(id);
|
|
4083
|
+
function providerHintOf(model, response) {
|
|
4084
|
+
const named = getProviderName(model);
|
|
4085
|
+
if (named) return named;
|
|
4086
|
+
const fromWire = wireInfoOf(response)?.provider;
|
|
4087
|
+
if (fromWire) return fromWire;
|
|
4088
|
+
try {
|
|
4089
|
+
return nonEmpty2(getModelCapabilities(model).provider);
|
|
4090
|
+
} catch {
|
|
4091
|
+
return void 0;
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
function traceResponseFacts(model, response, rawUsage, streaming) {
|
|
4095
|
+
const wire = wireInfoOf(response);
|
|
4096
|
+
const meta = response?.response_metadata ?? {};
|
|
4097
|
+
const message = response;
|
|
4098
|
+
const idCandidate = nonEmpty2(wire?.responseId) ?? nonEmpty2(meta.id) ?? nonEmpty2(message?.id);
|
|
4099
|
+
const responseId = idCandidate && !isRunId(idCandidate) ? idCandidate : void 0;
|
|
4100
|
+
const responseModel = nonEmpty2(wire?.responseModel) ?? nonEmpty2(meta.model_name) ?? nonEmpty2(meta.model) ?? nonEmpty2(meta.modelName);
|
|
4101
|
+
const rawFinishReason = nonEmpty2(wire?.rawFinishReason) ?? nonEmpty2(meta.stop_reason) ?? nonEmpty2(meta.finish_reason) ?? nonEmpty2(meta.finishReason);
|
|
4102
|
+
const cacheWriteTokens = cacheWriteTokensOf(rawUsage);
|
|
4103
|
+
const provider = providerHintOf(model, response);
|
|
4104
|
+
const isStreaming = streaming ?? wire?.streaming;
|
|
4105
|
+
return {
|
|
4106
|
+
...provider ? { provider } : {},
|
|
4107
|
+
...responseId ? { responseId } : {},
|
|
4108
|
+
...responseModel ? { responseModel } : {},
|
|
4109
|
+
...rawFinishReason ? { rawFinishReason } : {},
|
|
4110
|
+
...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {},
|
|
4111
|
+
...wire?.usageBasis ? { usageBasis: { ...wire.usageBasis } } : {},
|
|
4112
|
+
...isStreaming ? { streaming: true } : {}
|
|
4113
|
+
};
|
|
4114
|
+
}
|
|
2636
4115
|
function toMessageUsage(u) {
|
|
2637
4116
|
return {
|
|
2638
4117
|
prompt_tokens: u.inputTokens,
|
|
@@ -2655,7 +4134,12 @@ function fromNativeProvider(provider, options) {
|
|
|
2655
4134
|
if (link.signal) request.signal = link.signal;
|
|
2656
4135
|
request = await applyTransform(request);
|
|
2657
4136
|
const response = await provider.complete(request);
|
|
2658
|
-
return toBaseChatMessage(response)
|
|
4137
|
+
return attachWireInfo(toBaseChatMessage(response), {
|
|
4138
|
+
provider: provider.providerName,
|
|
4139
|
+
responseId: response.id,
|
|
4140
|
+
responseModel: response.model,
|
|
4141
|
+
rawFinishReason: response.rawFinishReason
|
|
4142
|
+
});
|
|
2659
4143
|
} finally {
|
|
2660
4144
|
link.dispose();
|
|
2661
4145
|
}
|
|
@@ -2674,6 +4158,8 @@ function fromNativeProvider(provider, options) {
|
|
|
2674
4158
|
let reasoningText = "";
|
|
2675
4159
|
let finishReason;
|
|
2676
4160
|
let responseModel;
|
|
4161
|
+
let responseId;
|
|
4162
|
+
let rawFinishReason;
|
|
2677
4163
|
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
2678
4164
|
for await (const chunk of provider.completeStream(request)) {
|
|
2679
4165
|
if (chunk.delta.content) {
|
|
@@ -2681,6 +4167,8 @@ function fromNativeProvider(provider, options) {
|
|
|
2681
4167
|
yield chunk.delta.content;
|
|
2682
4168
|
}
|
|
2683
4169
|
if (chunk.model) responseModel = chunk.model;
|
|
4170
|
+
if (chunk.id) responseId = chunk.id;
|
|
4171
|
+
if (chunk.rawFinishReason) rawFinishReason = chunk.rawFinishReason;
|
|
2684
4172
|
if (chunk.finishReason) finishReason = chunk.finishReason;
|
|
2685
4173
|
if (chunk.delta.reasoning?.blocks?.length) {
|
|
2686
4174
|
reasoningBlocks = chunk.delta.reasoning.blocks;
|
|
@@ -2702,7 +4190,8 @@ function fromNativeProvider(provider, options) {
|
|
|
2702
4190
|
id: tc.id,
|
|
2703
4191
|
name: tc.name ?? "",
|
|
2704
4192
|
arguments: tc.arguments ?? "",
|
|
2705
|
-
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
4193
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
|
|
4194
|
+
...tc.idSynthesized ? { idSynthesized: true } : {}
|
|
2706
4195
|
});
|
|
2707
4196
|
}
|
|
2708
4197
|
}
|
|
@@ -2726,7 +4215,13 @@ function fromNativeProvider(provider, options) {
|
|
|
2726
4215
|
...responseModel ? { model_name: responseModel } : {}
|
|
2727
4216
|
};
|
|
2728
4217
|
}
|
|
2729
|
-
yield finalMessage
|
|
4218
|
+
yield attachWireInfo(finalMessage, {
|
|
4219
|
+
provider: provider.providerName,
|
|
4220
|
+
responseId,
|
|
4221
|
+
responseModel,
|
|
4222
|
+
rawFinishReason,
|
|
4223
|
+
streaming: true
|
|
4224
|
+
});
|
|
2730
4225
|
} finally {
|
|
2731
4226
|
link.dispose();
|
|
2732
4227
|
}
|
|
@@ -3100,7 +4595,8 @@ function toBaseChatMessage(response) {
|
|
|
3100
4595
|
id: tc.id,
|
|
3101
4596
|
type: "function",
|
|
3102
4597
|
function: { name: tc.name, arguments: tc.arguments },
|
|
3103
|
-
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
4598
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
|
|
4599
|
+
...tc.idSynthesized ? { idSynthesized: true } : {}
|
|
3104
4600
|
}));
|
|
3105
4601
|
}
|
|
3106
4602
|
if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
|
|
@@ -3122,7 +4618,8 @@ function assembleMessage(content, toolCalls, usage) {
|
|
|
3122
4618
|
id: tc.id,
|
|
3123
4619
|
type: "function",
|
|
3124
4620
|
function: { name: tc.name, arguments: tc.arguments },
|
|
3125
|
-
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
4621
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {},
|
|
4622
|
+
...tc.idSynthesized ? { idSynthesized: true } : {}
|
|
3126
4623
|
}));
|
|
3127
4624
|
}
|
|
3128
4625
|
return msg;
|
|
@@ -4016,7 +5513,7 @@ var CCRStore = class _CCRStore {
|
|
|
4016
5513
|
}
|
|
4017
5514
|
static hashOf(value) {
|
|
4018
5515
|
const serialized = typeof value === "string" ? value : JSON.stringify(value);
|
|
4019
|
-
return crypto.createHash("
|
|
5516
|
+
return crypto.createHash("sha256").update(serialized).digest("hex").slice(0, 16);
|
|
4020
5517
|
}
|
|
4021
5518
|
};
|
|
4022
5519
|
var DedupTracker = class {
|
|
@@ -4029,7 +5526,7 @@ var DedupTracker = class {
|
|
|
4029
5526
|
* first time it has been seen.
|
|
4030
5527
|
*/
|
|
4031
5528
|
checkAndRegister(content, executionId, toolName) {
|
|
4032
|
-
const hash = crypto.createHash("
|
|
5529
|
+
const hash = crypto.createHash("sha256").update(content).digest("hex");
|
|
4033
5530
|
const existing = this.seen.get(hash);
|
|
4034
5531
|
if (!existing) {
|
|
4035
5532
|
this.seen.set(hash, { executionId, toolName });
|
|
@@ -4566,7 +6063,7 @@ function createAgentCoreNode(opts) {
|
|
|
4566
6063
|
const actorVersion = runtime.version ?? opts.version;
|
|
4567
6064
|
let traceToolDefinitions;
|
|
4568
6065
|
const computeTraceToolDefinitions = (menu) => {
|
|
4569
|
-
if (!traceSession || !traceSession.resolvedConfig.logData || menu.length === 0) return void 0;
|
|
6066
|
+
if (!traceSession || !(traceSession.resolvedConfig.logData || traceSession.captureContent) || menu.length === 0) return void 0;
|
|
4570
6067
|
try {
|
|
4571
6068
|
const wire = shouldUseStrictToolCalling ? prepareStrictToolMenu(menu).menu : menu;
|
|
4572
6069
|
return wire.map((tool) => {
|
|
@@ -4779,8 +6276,9 @@ ${append}`;
|
|
|
4779
6276
|
// outcome, and an "error" status would flip the whole trace session
|
|
4780
6277
|
// status to error for a run that behaved exactly as configured.
|
|
4781
6278
|
status: "skipped",
|
|
6279
|
+
skipReason: "blocked",
|
|
4782
6280
|
model: getModelName(runtime.model || opts.model),
|
|
4783
|
-
provider:
|
|
6281
|
+
provider: providerHintOf(runtime.model || opts.model),
|
|
4784
6282
|
messageList: state.messages
|
|
4785
6283
|
});
|
|
4786
6284
|
return {
|
|
@@ -4809,9 +6307,12 @@ ${append}`;
|
|
|
4809
6307
|
for (const key of ["usage", "usage_metadata", "response_metadata"]) {
|
|
4810
6308
|
if (merged[key] === void 0 && original?.[key] !== void 0) merged[key] = original[key];
|
|
4811
6309
|
}
|
|
6310
|
+
if (wireInfoOf(merged) === void 0 && wireInfoOf(original) !== void 0) merged[WIRE_INFO] = wireInfoOf(original);
|
|
4812
6311
|
return merged;
|
|
4813
6312
|
};
|
|
4814
6313
|
let response;
|
|
6314
|
+
let sentMessages;
|
|
6315
|
+
let streamedCall = false;
|
|
4815
6316
|
let modelAttempt = 0;
|
|
4816
6317
|
const maxModelRetries = host?.maxModelRetries ?? 0;
|
|
4817
6318
|
const finishCancelledTurn = (partialText) => {
|
|
@@ -4825,12 +6326,16 @@ ${append}`;
|
|
|
4825
6326
|
// "skipped", not "error": the call did not fail, the caller ended it —
|
|
4826
6327
|
// and an "error" would flip the whole session to error.
|
|
4827
6328
|
status: "skipped",
|
|
6329
|
+
// The call reached the provider and was hung up on: still a model call, not a skipped one.
|
|
6330
|
+
skipReason: "cancelled",
|
|
6331
|
+
...streamedCall ? { streaming: true } : {},
|
|
4828
6332
|
durationMs: Date.now() - start,
|
|
4829
6333
|
requestBytes: promptBytes,
|
|
4830
6334
|
model: getModelName(runtime.model || opts.model),
|
|
4831
|
-
provider:
|
|
6335
|
+
provider: providerHintOf(runtime.model || opts.model),
|
|
4832
6336
|
messageList: state.messages,
|
|
4833
|
-
toolDefinitions: traceToolDefinitions
|
|
6337
|
+
toolDefinitions: traceToolDefinitions,
|
|
6338
|
+
capture: { input: sentMessages ?? wireMessages, toolDefinitions: traceToolDefinitions }
|
|
4834
6339
|
});
|
|
4835
6340
|
onEvent?.({ type: "cancelled", stage: "agent", reason });
|
|
4836
6341
|
onProgress?.({ stage: "agent", message: "Cancelled", detail: { reason } });
|
|
@@ -4846,8 +6351,9 @@ ${append}`;
|
|
|
4846
6351
|
label: "Assistant (plugin short-circuit)",
|
|
4847
6352
|
actor: { scope: "agent", name: actorName, role: "assistant", version: actorVersion },
|
|
4848
6353
|
status: "skipped",
|
|
6354
|
+
skipReason: "short_circuit",
|
|
4849
6355
|
model: getModelName(runtime.model || opts.model),
|
|
4850
|
-
provider:
|
|
6356
|
+
provider: providerHintOf(runtime.model || opts.model),
|
|
4851
6357
|
messageList: state.messages,
|
|
4852
6358
|
toolDefinitions: traceToolDefinitions
|
|
4853
6359
|
});
|
|
@@ -4855,8 +6361,10 @@ ${append}`;
|
|
|
4855
6361
|
let streamedText = "";
|
|
4856
6362
|
try {
|
|
4857
6363
|
const normalizedMessages = normalizeBedrockToolPairing([...wireMessages]);
|
|
6364
|
+
sentMessages = normalizedMessages;
|
|
4858
6365
|
debugToolPairing(normalizedMessages);
|
|
4859
6366
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
6367
|
+
streamedCall = true;
|
|
4860
6368
|
let streamedMessage;
|
|
4861
6369
|
let cutByCancel = false;
|
|
4862
6370
|
for await (const chunk of modelWithTools.stream(normalizedMessages, invokeParams)) {
|
|
@@ -4902,12 +6410,14 @@ ${append}`;
|
|
|
4902
6410
|
durationMs: durationMs2,
|
|
4903
6411
|
requestBytes: promptBytes,
|
|
4904
6412
|
model: getModelName(runtime.model || opts.model),
|
|
4905
|
-
provider:
|
|
4906
|
-
error:
|
|
6413
|
+
provider: providerHintOf(runtime.model || opts.model),
|
|
6414
|
+
error: traceErrorOf(err),
|
|
6415
|
+
...streamedCall ? { streaming: true } : {},
|
|
4907
6416
|
messageList: state.messages,
|
|
4908
6417
|
toolDefinitions: traceToolDefinitions,
|
|
4909
6418
|
responseFormat: traceResponseFormat,
|
|
4910
|
-
responseFormatStrategy: traceResponseFormatStrategy
|
|
6419
|
+
responseFormatStrategy: traceResponseFormatStrategy,
|
|
6420
|
+
capture: { input: sentMessages ?? wireMessages, toolDefinitions: traceToolDefinitions }
|
|
4911
6421
|
});
|
|
4912
6422
|
throw err;
|
|
4913
6423
|
}
|
|
@@ -4960,6 +6470,8 @@ ${append}`;
|
|
|
4960
6470
|
const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
|
|
4961
6471
|
const responseBytes = responsePayload !== void 0 ? estimatePayloadBytes(responsePayload) : void 0;
|
|
4962
6472
|
const finishReason = response?.response_metadata?.finish_reason ?? response?.response_metadata?.finishReason ?? response?.finishReason;
|
|
6473
|
+
const facts = traceResponseFacts(runtime.model || opts.model, response, rawUsage, streamedCall);
|
|
6474
|
+
const jsonOutput = Boolean(responseFormat) && responseFormat?.response_format?.type !== "text" && responseFormat?.type !== "text";
|
|
4963
6475
|
recordTraceEvent(traceSession, {
|
|
4964
6476
|
type: "ai_call",
|
|
4965
6477
|
label: "Assistant Response",
|
|
@@ -4976,11 +6488,13 @@ ${append}`;
|
|
|
4976
6488
|
requestBytes: promptBytes,
|
|
4977
6489
|
responseBytes,
|
|
4978
6490
|
model: modelName,
|
|
4979
|
-
|
|
6491
|
+
...facts,
|
|
6492
|
+
outputType: jsonOutput ? "json" : "text",
|
|
4980
6493
|
messageList: messagesWithResponse,
|
|
4981
6494
|
toolDefinitions: traceToolDefinitions,
|
|
4982
6495
|
responseFormat: traceResponseFormat,
|
|
4983
|
-
responseFormatStrategy: traceResponseFormatStrategy
|
|
6496
|
+
responseFormatStrategy: traceResponseFormatStrategy,
|
|
6497
|
+
capture: { input: sentMessages ?? wireMessages, output: response, toolDefinitions: traceToolDefinitions }
|
|
4984
6498
|
});
|
|
4985
6499
|
if (normalized) {
|
|
4986
6500
|
recordUsage(state, modelName, normalized);
|
|
@@ -5006,6 +6520,12 @@ function sameJson(a, b) {
|
|
|
5006
6520
|
return false;
|
|
5007
6521
|
}
|
|
5008
6522
|
}
|
|
6523
|
+
var idSection = (label, data) => ({
|
|
6524
|
+
kind: "metadata",
|
|
6525
|
+
label,
|
|
6526
|
+
data,
|
|
6527
|
+
identity: true
|
|
6528
|
+
});
|
|
5009
6529
|
function recordApprovalRequested(session, entry) {
|
|
5010
6530
|
if (!session || surfacedFromSubagent(entry) || !canPauseForHuman(session)) return;
|
|
5011
6531
|
const logData = session.resolvedConfig.logData;
|
|
@@ -5031,7 +6551,7 @@ function recordApprovalRequested(session, entry) {
|
|
|
5031
6551
|
timestamp: entry.requestedAt,
|
|
5032
6552
|
status: "pending",
|
|
5033
6553
|
actor: { scope: "agent", name: entry.toolName, role: "approval_request" },
|
|
5034
|
-
sections
|
|
6554
|
+
sections: [...sections, idSection("Approval ids", { approvalId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt })]
|
|
5035
6555
|
});
|
|
5036
6556
|
}
|
|
5037
6557
|
function recordHumanDecisions(session, state) {
|
|
@@ -5072,7 +6592,14 @@ function recordHumanDecisions(session, state) {
|
|
|
5072
6592
|
durationMs: waitedMs(entry.requestedAt, entry.decidedAt),
|
|
5073
6593
|
status: "success",
|
|
5074
6594
|
actor: { scope: "human", name: entry.decidedBy || "reviewer", role: "approver" },
|
|
5075
|
-
sections
|
|
6595
|
+
sections: [...sections, idSection("Decision ids", {
|
|
6596
|
+
approvalId: entry.id,
|
|
6597
|
+
toolCallId: entry.toolCallId,
|
|
6598
|
+
decision: entry.status,
|
|
6599
|
+
requestedAt: entry.requestedAt,
|
|
6600
|
+
decidedAt: entry.decidedAt,
|
|
6601
|
+
...waitedMs(entry.requestedAt, entry.decidedAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.decidedAt) } : {}
|
|
6602
|
+
})]
|
|
5076
6603
|
});
|
|
5077
6604
|
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
5078
6605
|
}
|
|
@@ -5117,7 +6644,14 @@ function recordHumanDecisions(session, state) {
|
|
|
5117
6644
|
durationMs: waitedMs(entry.requestedAt, entry.answeredAt),
|
|
5118
6645
|
status: cancelled ? "skipped" : "success",
|
|
5119
6646
|
actor: { scope: "human", name: entry.answeredBy || "user", role: "user" },
|
|
5120
|
-
sections
|
|
6647
|
+
sections: [...sections, idSection("Answer ids", {
|
|
6648
|
+
questionId: entry.id,
|
|
6649
|
+
toolCallId: entry.toolCallId,
|
|
6650
|
+
status: entry.status,
|
|
6651
|
+
requestedAt: entry.requestedAt,
|
|
6652
|
+
answeredAt: entry.answeredAt,
|
|
6653
|
+
...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
|
|
6654
|
+
})]
|
|
5121
6655
|
});
|
|
5122
6656
|
entry.metadata = { ...entry.metadata || {}, [TRACED_KEY]: true };
|
|
5123
6657
|
}
|
|
@@ -5142,7 +6676,7 @@ function recordClientToolRequested(session, entry) {
|
|
|
5142
6676
|
timestamp: entry.requestedAt,
|
|
5143
6677
|
status: "pending",
|
|
5144
6678
|
actor: { scope: "client", name: clientTool.name, role: "tool" },
|
|
5145
|
-
sections
|
|
6679
|
+
sections: [...sections, idSection("Client tool ids", { questionId: entry.id, toolCallId: entry.toolCallId, status: "pending", requestedAt: entry.requestedAt })]
|
|
5146
6680
|
});
|
|
5147
6681
|
}
|
|
5148
6682
|
function readClientTool(entry) {
|
|
@@ -5189,7 +6723,14 @@ function recordClientToolResult(session, entry, clientTool, toolHistory) {
|
|
|
5189
6723
|
durationMs: waitedMs(entry.requestedAt, entry.answeredAt) ?? ranMs,
|
|
5190
6724
|
status: failed ? "error" : "success",
|
|
5191
6725
|
actor: { scope: "client", name: clientTool.name, role: "tool" },
|
|
5192
|
-
sections
|
|
6726
|
+
sections: [...sections, idSection("Client tool ids", {
|
|
6727
|
+
questionId: entry.id,
|
|
6728
|
+
toolCallId: entry.toolCallId,
|
|
6729
|
+
status: failed ? "error" : "answered",
|
|
6730
|
+
requestedAt: entry.requestedAt,
|
|
6731
|
+
answeredAt: entry.answeredAt,
|
|
6732
|
+
...waitedMs(entry.requestedAt, entry.answeredAt) !== void 0 ? { waitedMs: waitedMs(entry.requestedAt, entry.answeredAt) } : {}
|
|
6733
|
+
})]
|
|
5193
6734
|
});
|
|
5194
6735
|
}
|
|
5195
6736
|
|
|
@@ -5295,9 +6836,11 @@ function normalizeToolCall(call) {
|
|
|
5295
6836
|
return {
|
|
5296
6837
|
id: call.id,
|
|
5297
6838
|
name,
|
|
5298
|
-
args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments
|
|
6839
|
+
args: call.args ?? call.arguments ?? call.input ?? call.function?.arguments ?? call.function_call?.arguments,
|
|
6840
|
+
...call.idSynthesized === true ? { idSynthesized: true } : {}
|
|
5299
6841
|
};
|
|
5300
6842
|
}
|
|
6843
|
+
var providerToolCallId = (tc) => tc.id && !tc.idSynthesized ? tc.id : void 0;
|
|
5301
6844
|
function normalizeToolSchema(tool, toolName) {
|
|
5302
6845
|
const schema = tool.schema;
|
|
5303
6846
|
if (!schema) return void 0;
|
|
@@ -5555,6 +7098,8 @@ function createToolsNode(initialTools, opts) {
|
|
|
5555
7098
|
label: `Tool Denied - ${toolName}`,
|
|
5556
7099
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
5557
7100
|
status: "skipped",
|
|
7101
|
+
skipReason: "denied",
|
|
7102
|
+
toolCallId: providerToolCallId(tc),
|
|
5558
7103
|
toolDetails,
|
|
5559
7104
|
toolExecutionId: toolCallId,
|
|
5560
7105
|
sections: buildToolTraceSections({
|
|
@@ -5626,6 +7171,8 @@ function createToolsNode(initialTools, opts) {
|
|
|
5626
7171
|
label: `Tool Skipped - ${toolName}`,
|
|
5627
7172
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
5628
7173
|
status: "skipped",
|
|
7174
|
+
skipReason: "skipped",
|
|
7175
|
+
toolCallId: providerToolCallId(tc),
|
|
5629
7176
|
toolDetails,
|
|
5630
7177
|
toolExecutionId: tc.id,
|
|
5631
7178
|
sections: buildToolTraceSections({
|
|
@@ -5762,10 +7309,13 @@ function createToolsNode(initialTools, opts) {
|
|
|
5762
7309
|
label: `Tool Error - ${toolName}`,
|
|
5763
7310
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
5764
7311
|
status: "error",
|
|
7312
|
+
// The tool was not run: an open breaker refused the call.
|
|
7313
|
+
skipReason: "skipped",
|
|
7314
|
+
toolCallId: providerToolCallId(tc),
|
|
5765
7315
|
requestBytes: inputBytes,
|
|
5766
7316
|
toolDetails,
|
|
5767
7317
|
toolExecutionId: toolCallId,
|
|
5768
|
-
error: { message: breakerMsg },
|
|
7318
|
+
error: { message: breakerMsg, type: "circuit_breaker_open" },
|
|
5769
7319
|
sections: buildToolTraceSections({
|
|
5770
7320
|
args,
|
|
5771
7321
|
executionId: toolCallId,
|
|
@@ -5825,6 +7375,9 @@ function createToolsNode(initialTools, opts) {
|
|
|
5825
7375
|
type: "tool_call",
|
|
5826
7376
|
label: shortCircuitSource === "plugin" ? `Tool Short-Circuited - ${toolName}` : `Tool Execution - ${toolName}`,
|
|
5827
7377
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
7378
|
+
// Answered from the cache or by a plugin: nothing executed.
|
|
7379
|
+
skipReason: "short_circuit",
|
|
7380
|
+
toolCallId: providerToolCallId(tc),
|
|
5828
7381
|
durationMs: 0,
|
|
5829
7382
|
requestBytes: inputBytes,
|
|
5830
7383
|
responseBytes: outputBytes2,
|
|
@@ -5860,7 +7413,15 @@ function createToolsNode(initialTools, opts) {
|
|
|
5860
7413
|
onProgress?.({ stage: "tools", message: `Running tool ${tc.name}` });
|
|
5861
7414
|
const anyTool = tool;
|
|
5862
7415
|
traceSpanId = traceSession ? generateSpanId() : void 0;
|
|
5863
|
-
const callOptions = {
|
|
7416
|
+
const callOptions = {
|
|
7417
|
+
cancellationToken,
|
|
7418
|
+
signal: abortSignal,
|
|
7419
|
+
toolCallId,
|
|
7420
|
+
...traceSpanId ? { traceSpanId } : {},
|
|
7421
|
+
// So the tool can propagate the trace to what it calls (traceparentOf).
|
|
7422
|
+
...traceSpanId && traceSession?.traceId ? { traceId: traceSession.traceId } : {},
|
|
7423
|
+
...traceSpanId && traceSession?.parent ? { traceFlags: traceSession.parent.flags } : {}
|
|
7424
|
+
};
|
|
5864
7425
|
const invokeOnce = async () => {
|
|
5865
7426
|
if (typeof anyTool.func === "function") return anyTool.func(args, callOptions);
|
|
5866
7427
|
if (typeof anyTool.invoke === "function") return anyTool.invoke(args, callOptions);
|
|
@@ -6046,7 +7607,10 @@ function createToolsNode(initialTools, opts) {
|
|
|
6046
7607
|
spanId: traceSpanId,
|
|
6047
7608
|
label: `Tool Execution - ${toolName}`,
|
|
6048
7609
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
6049
|
-
...reportedFailure ? { status: "error", error: { message: reportedFailure } } : {},
|
|
7610
|
+
...reportedFailure ? { status: "error", error: { message: reportedFailure, type: "tool_error" } } : {},
|
|
7611
|
+
toolCallId: providerToolCallId(tc),
|
|
7612
|
+
// `output` is already past postToolUse, so a redaction plugin has applied.
|
|
7613
|
+
capture: reportedFailure ? { toolArguments: args } : { toolArguments: args, toolResult: output, hasToolResult: true },
|
|
6050
7614
|
durationMs,
|
|
6051
7615
|
requestBytes: inputBytes,
|
|
6052
7616
|
responseBytes: outputBytes,
|
|
@@ -6110,12 +7674,14 @@ function createToolsNode(initialTools, opts) {
|
|
|
6110
7674
|
label: `Tool Error - ${toolName}`,
|
|
6111
7675
|
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
6112
7676
|
status: "error",
|
|
7677
|
+
toolCallId: providerToolCallId(tc),
|
|
7678
|
+
capture: { toolArguments: args },
|
|
6113
7679
|
durationMs,
|
|
6114
7680
|
requestBytes: inputBytes,
|
|
6115
7681
|
responseBytes: traceSession?.resolvedConfig.logData ? estimatePayloadBytes(errorOutput) : void 0,
|
|
6116
7682
|
toolDetails,
|
|
6117
7683
|
toolExecutionId: executionId,
|
|
6118
|
-
error: { message, stack: host?.has("postToolUse") ? void 0 : error?.stack },
|
|
7684
|
+
error: { ...traceErrorOf(error), message, stack: host?.has("postToolUse") ? void 0 : error?.stack },
|
|
6119
7685
|
sections: buildToolTraceSections({
|
|
6120
7686
|
args: sanitizedArgs,
|
|
6121
7687
|
durationMs,
|
|
@@ -6230,6 +7796,8 @@ function createToolsNode(initialTools, opts) {
|
|
|
6230
7796
|
label: `Tool Skipped - ${tc.name}`,
|
|
6231
7797
|
actor: { scope: "tool", name: tc.name, role: "tool" },
|
|
6232
7798
|
status: "skipped",
|
|
7799
|
+
skipReason: "skipped",
|
|
7800
|
+
toolCallId: providerToolCallId(tc),
|
|
6233
7801
|
toolDetails,
|
|
6234
7802
|
toolExecutionId: tc.id,
|
|
6235
7803
|
sections: buildToolTraceSections({
|
|
@@ -6396,7 +7964,7 @@ function createReflectionNode(opts, resolved) {
|
|
|
6396
7964
|
label: "Reflection error",
|
|
6397
7965
|
actor: { scope: "agent", name: opts.name || "agent", role: "reflection" },
|
|
6398
7966
|
status: "error",
|
|
6399
|
-
error:
|
|
7967
|
+
error: traceErrorOf(err)
|
|
6400
7968
|
});
|
|
6401
7969
|
return {};
|
|
6402
7970
|
}
|
|
@@ -7407,7 +8975,7 @@ function buildSubagentCatalogBlock(subagents, policy, toolNames, opts) {
|
|
|
7407
8975
|
// src/plugins/host.ts
|
|
7408
8976
|
init_content();
|
|
7409
8977
|
var DEFAULT_PRIORITY = 100;
|
|
7410
|
-
var
|
|
8978
|
+
var DEFAULT_TIMEOUT_MS2 = 1e4;
|
|
7411
8979
|
var HOOK_SPECS = {
|
|
7412
8980
|
sessionStart: { kind: "gate", mutable: ["messages"], collect: ["systemPromptAppend"] },
|
|
7413
8981
|
userPromptSubmit: {
|
|
@@ -7512,7 +9080,7 @@ function collectRegistrations(plugin, registrations, into, orderRef) {
|
|
|
7512
9080
|
plugin: plugin.name,
|
|
7513
9081
|
priority: plugin.priority ?? DEFAULT_PRIORITY,
|
|
7514
9082
|
failureMode: plugin.failureMode ?? "open",
|
|
7515
|
-
timeoutMs: plugin.timeoutMs ??
|
|
9083
|
+
timeoutMs: plugin.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
|
|
7516
9084
|
order: orderRef.value++,
|
|
7517
9085
|
handler
|
|
7518
9086
|
});
|
|
@@ -7567,6 +9135,7 @@ function createPluginHost(plugins = [], options = {}) {
|
|
|
7567
9135
|
let contributions = {
|
|
7568
9136
|
tools: [],
|
|
7569
9137
|
toolDescriptions: {},
|
|
9138
|
+
traceExporters: [],
|
|
7570
9139
|
guardrails: [],
|
|
7571
9140
|
applySystemPrompt: (base) => base,
|
|
7572
9141
|
applyModelWrappers: (model) => model
|
|
@@ -7575,6 +9144,7 @@ function createPluginHost(plugins = [], options = {}) {
|
|
|
7575
9144
|
async function runSetup(setupInput) {
|
|
7576
9145
|
const tools = [];
|
|
7577
9146
|
const toolDescriptions = {};
|
|
9147
|
+
const traceExporters = [];
|
|
7578
9148
|
const guardrails = [];
|
|
7579
9149
|
const promptSteps = [];
|
|
7580
9150
|
const modelWrappers = [];
|
|
@@ -7612,6 +9182,7 @@ function createPluginHost(plugins = [], options = {}) {
|
|
|
7612
9182
|
);
|
|
7613
9183
|
}
|
|
7614
9184
|
if (plugin.toolDescriptions) Object.assign(toolDescriptions, plugin.toolDescriptions);
|
|
9185
|
+
if (plugin.traceExporters?.length) traceExporters.push(...plugin.traceExporters.filter(Boolean));
|
|
7615
9186
|
if (plugin.guardrails?.length) guardrails.push(...plugin.guardrails);
|
|
7616
9187
|
if (typeof plugin.wrapModel === "function") {
|
|
7617
9188
|
modelWrappers.push({ plugin: plugin.name, wrap: plugin.wrapModel });
|
|
@@ -7627,6 +9198,7 @@ function createPluginHost(plugins = [], options = {}) {
|
|
|
7627
9198
|
contributions = {
|
|
7628
9199
|
tools,
|
|
7629
9200
|
toolDescriptions,
|
|
9201
|
+
traceExporters,
|
|
7630
9202
|
guardrails,
|
|
7631
9203
|
applySystemPrompt: (base) => promptSteps.reduce((current, step) => {
|
|
7632
9204
|
try {
|
|
@@ -8650,7 +10222,10 @@ function createAgent(opts) {
|
|
|
8650
10222
|
}
|
|
8651
10223
|
emit({ type: "progress", ...progress });
|
|
8652
10224
|
};
|
|
8653
|
-
const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation)
|
|
10225
|
+
const traceSession = createTraceSession(opts, readTraceContinuation(input.ctx?.__traceContinuation), {
|
|
10226
|
+
exporters: pluginHost.contributions.traceExporters,
|
|
10227
|
+
traceParent: config?.traceParent
|
|
10228
|
+
});
|
|
8654
10229
|
const ctx = {
|
|
8655
10230
|
...input.ctx || {},
|
|
8656
10231
|
__onEvent: onEvent,
|
|
@@ -8802,7 +10377,7 @@ function createAgent(opts) {
|
|
|
8802
10377
|
await finalizeTraceSession(traceSession, {
|
|
8803
10378
|
agentRuntime: runtime,
|
|
8804
10379
|
status: "error",
|
|
8805
|
-
error: { message: err?.message, stack: err?.stack }
|
|
10380
|
+
error: { message: err?.message, stack: err?.stack, name: err?.name }
|
|
8806
10381
|
});
|
|
8807
10382
|
await endSession("error", { error: err instanceof Error ? err : new Error(String(err)), state: stateHolder.value });
|
|
8808
10383
|
if (userTokenCounter) {
|
|
@@ -8823,7 +10398,10 @@ function createAgent(opts) {
|
|
|
8823
10398
|
const midTurn = pausedForHuman || Boolean(res.ctx?.__needsSummarization);
|
|
8824
10399
|
await finalizeTraceSession(traceSession, {
|
|
8825
10400
|
agentRuntime: res.agent || runtime,
|
|
8826
|
-
status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success"
|
|
10401
|
+
status: pausedForHuman ? "paused" : midTurn ? "in_progress" : "success",
|
|
10402
|
+
// The file says `success` for a cancelled run (it did not fail); the
|
|
10403
|
+
// exported root says `partial`, the old plugin mapping.
|
|
10404
|
+
cancelled: statusFor(res) === "cancelled"
|
|
8827
10405
|
});
|
|
8828
10406
|
if (traceSession && midTurn) {
|
|
8829
10407
|
res.ctx = { ...res.ctx || {}, __traceContinuation: traceContinuationOf(traceSession) };
|
|
@@ -8968,14 +10546,16 @@ function createAgent(opts) {
|
|
|
8968
10546
|
const startedAt = Date.now();
|
|
8969
10547
|
const recordSpan = (status, extra) => {
|
|
8970
10548
|
if (!traced || !isTraceSessionOpen(parentSession)) return;
|
|
10549
|
+
const running = status === "running";
|
|
8971
10550
|
recordSubagentSpan(parentSession, {
|
|
8972
10551
|
spanId: agentSpanId,
|
|
8973
|
-
|
|
10552
|
+
// The delegating tool_call span only exists once the tool returns.
|
|
10553
|
+
parentSpanId: running ? parentIterationSpanId : context?.traceSpanId ?? parentIterationSpanId,
|
|
8974
10554
|
name: opts.name || "agent",
|
|
8975
10555
|
status,
|
|
8976
|
-
durationMs: Date.now() - startedAt,
|
|
10556
|
+
durationMs: running ? void 0 : Date.now() - startedAt,
|
|
8977
10557
|
error: extra.error,
|
|
8978
|
-
info: { name: opts.name || "agent", mode: "asTool", depth: currentDepth + 1, parentToolCallId: context?.toolCallId, status: status === "success" ? "ok" : "error" },
|
|
10558
|
+
info: { name: opts.name || "agent", mode: "asTool", depth: currentDepth + 1, parentToolCallId: context?.toolCallId, status: running ? "running" : status === "success" ? "ok" : "error" },
|
|
8979
10559
|
task: input,
|
|
8980
10560
|
result: extra.result
|
|
8981
10561
|
});
|
|
@@ -8995,6 +10575,7 @@ function createAgent(opts) {
|
|
|
8995
10575
|
stream: Boolean(parentCtx.__streaming),
|
|
8996
10576
|
cancellationToken: parentCtx.__cancellationToken ?? parentCtx.__abortSignal
|
|
8997
10577
|
};
|
|
10578
|
+
recordSpan("running", {});
|
|
8998
10579
|
let res;
|
|
8999
10580
|
try {
|
|
9000
10581
|
res = await instance.invoke({ messages: childMessages, ctx: childCtx }, childConfig);
|
|
@@ -9079,9 +10660,10 @@ function createAgentNode(opts) {
|
|
|
9079
10660
|
durationMs: durationMs2,
|
|
9080
10661
|
requestBytes: promptBytes,
|
|
9081
10662
|
model: getModelName(runtime.model || opts.model),
|
|
9082
|
-
provider:
|
|
9083
|
-
error:
|
|
9084
|
-
messageList: promptMessages
|
|
10663
|
+
provider: providerHintOf(runtime.model || opts.model),
|
|
10664
|
+
error: traceErrorOf(err),
|
|
10665
|
+
messageList: promptMessages,
|
|
10666
|
+
capture: { input: promptMessages }
|
|
9085
10667
|
});
|
|
9086
10668
|
throw err;
|
|
9087
10669
|
}
|
|
@@ -9092,7 +10674,7 @@ function createAgentNode(opts) {
|
|
|
9092
10674
|
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
10675
|
const normalized = normalizeUsage(rawUsage);
|
|
9094
10676
|
const modelName = getModelName(runtime.model || opts.model) || "unknown_model";
|
|
9095
|
-
const
|
|
10677
|
+
const facts = traceResponseFacts(runtime.model || opts.model, response, rawUsage);
|
|
9096
10678
|
const durationMs = Date.now() - start;
|
|
9097
10679
|
const shouldLogResponse = !!traceSession && traceSession.resolvedConfig.logData;
|
|
9098
10680
|
const responsePayload = shouldLogResponse ? sanitizeTracePayload(response) : void 0;
|
|
@@ -9109,8 +10691,9 @@ function createAgentNode(opts) {
|
|
|
9109
10691
|
requestBytes: promptBytes,
|
|
9110
10692
|
responseBytes,
|
|
9111
10693
|
model: modelName,
|
|
9112
|
-
|
|
9113
|
-
messageList: messagesWithResponse
|
|
10694
|
+
...facts,
|
|
10695
|
+
messageList: messagesWithResponse,
|
|
10696
|
+
capture: { input: promptMessages, output: response }
|
|
9114
10697
|
});
|
|
9115
10698
|
if (normalized) {
|
|
9116
10699
|
recordUsage(state, modelName, normalized);
|
|
@@ -9761,7 +11344,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
9761
11344
|
];
|
|
9762
11345
|
const inputTokensEstimate = countApproxTokens(summaryPrompt.map((m) => m.content).join("\n"));
|
|
9763
11346
|
const modelName = getModelName(model);
|
|
9764
|
-
const providerName =
|
|
11347
|
+
const providerName = providerHintOf(model);
|
|
9765
11348
|
const tracingEnabled = Boolean(opts.tracing?.enabled);
|
|
9766
11349
|
let ctxWithDeferredTrace;
|
|
9767
11350
|
const traceSummarization = (event) => {
|
|
@@ -9792,6 +11375,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
9792
11375
|
let reasoningTokensActual;
|
|
9793
11376
|
let fallback = false;
|
|
9794
11377
|
let summarizerError;
|
|
11378
|
+
let responseFacts;
|
|
9795
11379
|
const directivesSection = () => ({
|
|
9796
11380
|
kind: "metadata",
|
|
9797
11381
|
label: "User directives",
|
|
@@ -9833,6 +11417,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
9833
11417
|
summaryText = renderStructuredSummary(structuredSummary);
|
|
9834
11418
|
const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
|
|
9835
11419
|
const normalized = normalizeUsage(rawUsage);
|
|
11420
|
+
responseFacts = traceResponseFacts(model, response, rawUsage);
|
|
9836
11421
|
if (normalized) {
|
|
9837
11422
|
inputTokensActual = normalized.prompt_tokens;
|
|
9838
11423
|
outputTokensActual = normalized.completion_tokens;
|
|
@@ -9869,7 +11454,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
9869
11454
|
...droppedDirectives.length > 0 ? { droppedDirectives } : {}
|
|
9870
11455
|
};
|
|
9871
11456
|
onEvent?.(errorEvent);
|
|
9872
|
-
summarizerError =
|
|
11457
|
+
summarizerError = traceErrorOf(err);
|
|
9873
11458
|
}
|
|
9874
11459
|
const toolCallIdToAssistantIdx = /* @__PURE__ */ new Map();
|
|
9875
11460
|
messages.forEach((m, idx) => {
|
|
@@ -10025,10 +11610,16 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
|
|
|
10025
11610
|
outputTokens: outputTokensActual ?? outputTokensEstimate,
|
|
10026
11611
|
cachedInputTokens,
|
|
10027
11612
|
totalTokens: totalTokensActual,
|
|
10028
|
-
...reasoningTokensActual !== void 0 ? { reasoningTokens: reasoningTokensActual } : {}
|
|
11613
|
+
...reasoningTokensActual !== void 0 ? { reasoningTokens: reasoningTokensActual } : {},
|
|
11614
|
+
// Which counting rules the usage above follows (only when the provider reported it).
|
|
11615
|
+
...inputTokensActual !== void 0 && responseFacts?.usageBasis ? { usageBasis: responseFacts.usageBasis } : {},
|
|
11616
|
+
...inputTokensActual !== void 0 && responseFacts?.cacheWriteTokens ? { cacheWriteTokens: responseFacts.cacheWriteTokens } : {}
|
|
10029
11617
|
},
|
|
11618
|
+
...responseFacts?.responseId ? { responseId: responseFacts.responseId } : {},
|
|
11619
|
+
...responseFacts?.responseModel ? { responseModel: responseFacts.responseModel } : {},
|
|
11620
|
+
...responseFacts?.rawFinishReason ? { rawFinishReason: responseFacts.rawFinishReason } : {},
|
|
10030
11621
|
...modelName ? { model: modelName } : {},
|
|
10031
|
-
...providerName ? { provider: providerName } : {},
|
|
11622
|
+
...responseFacts?.provider ?? providerName ? { provider: responseFacts?.provider ?? providerName } : {},
|
|
10032
11623
|
...summarizerError ? { error: summarizerError } : {},
|
|
10033
11624
|
sections: [
|
|
10034
11625
|
...promptAndOutputSections(),
|
|
@@ -11172,19 +12763,29 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11172
12763
|
const childDepth = (Number(parentCtx.__delegationDepth) || 0) + 1;
|
|
11173
12764
|
const parentSession = parentCtx.__traceSession;
|
|
11174
12765
|
const traced = isTraceSessionOpen(parentSession);
|
|
11175
|
-
const
|
|
12766
|
+
const sessionStart = traced ? parentSession.startedAt : void 0;
|
|
12767
|
+
const persistedId = opts.record?.agentSpanId;
|
|
12768
|
+
const agentSpanId = typeof persistedId === "string" && /^[0-9a-f]{16}$/.test(persistedId) ? persistedId : generateSpanId();
|
|
12769
|
+
const persistedStart = opts.record?.startedAt;
|
|
12770
|
+
const startValid = typeof persistedStart === "number" && Number.isFinite(persistedStart) && persistedStart > 0 && persistedStart <= start;
|
|
12771
|
+
const runStartedAt = startValid ? Math.min(start, Math.max(persistedStart, sessionStart ?? persistedStart)) : start;
|
|
12772
|
+
const persistedSegments = opts.record?.segments;
|
|
12773
|
+
const segment = (typeof persistedSegments === "number" && Number.isInteger(persistedSegments) && persistedSegments >= 1 && persistedSegments <= 1e3 ? persistedSegments : 0) + 1;
|
|
12774
|
+
const elapsedMs = () => Math.max(0, Date.now() - runStartedAt);
|
|
11176
12775
|
const parentIterationSpanId = traced ? parentSession.currentIterationSpanId : void 0;
|
|
11177
12776
|
const traceScope = traced ? createSubagentTraceScope(parentSession, { agentSpanId, name: spec.name, spawnId, mode: spec.mode, hitl: opts.allowHITL, iterations: opts.record?.iterations }) : void 0;
|
|
11178
12777
|
const recordSegment = (status, info) => {
|
|
11179
12778
|
if (!traced || !isTraceSessionOpen(parentSession)) return;
|
|
12779
|
+
const unfinished = status === "pending" || status === "running";
|
|
11180
12780
|
recordSubagentSpan(parentSession, {
|
|
11181
12781
|
spanId: agentSpanId,
|
|
11182
|
-
// The tool_call span only exists once the tool returns; a
|
|
11183
|
-
// has not returned, so its span hangs off the iteration.
|
|
11184
|
-
parentSpanId:
|
|
12782
|
+
// The tool_call span only exists once the tool returns; a running or
|
|
12783
|
+
// paused child has not returned, so its span hangs off the iteration.
|
|
12784
|
+
parentSpanId: unfinished ? parentIterationSpanId : opts.parentSpanId ?? parentIterationSpanId,
|
|
11185
12785
|
name: spec.name,
|
|
11186
12786
|
status,
|
|
11187
|
-
|
|
12787
|
+
// A starting segment has no extent yet; a reader draws it over its children.
|
|
12788
|
+
durationMs: status === "running" ? void 0 : elapsedMs(),
|
|
11188
12789
|
error: info.error,
|
|
11189
12790
|
info: {
|
|
11190
12791
|
id: spawnId,
|
|
@@ -11194,6 +12795,8 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11194
12795
|
depth: childDepth,
|
|
11195
12796
|
parentToolCallId: opts.parentToolCallId,
|
|
11196
12797
|
status: info.subagentStatus,
|
|
12798
|
+
// Only a run that paused has more than one segment to tell about.
|
|
12799
|
+
...segment > 1 || unfinished ? { segments: segment } : {},
|
|
11197
12800
|
...info.note ? { note: info.note } : {},
|
|
11198
12801
|
...spec.metadata ? { metadata: spec.metadata } : {}
|
|
11199
12802
|
},
|
|
@@ -11317,6 +12920,7 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11317
12920
|
}
|
|
11318
12921
|
if (traceScope) childInput = { ...childInput, ctx: { ...childInput.ctx || {}, __traceSession: traceScope } };
|
|
11319
12922
|
const usageBaseline = childInput.usage?.perRequest?.length ?? 0;
|
|
12923
|
+
recordSegment("running", { subagentStatus: "running", input });
|
|
11320
12924
|
let res;
|
|
11321
12925
|
try {
|
|
11322
12926
|
res = await child.invoke(childInput, childConfig);
|
|
@@ -11358,7 +12962,10 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11358
12962
|
pendingKind: "approval",
|
|
11359
12963
|
pendingId: childEntry.id,
|
|
11360
12964
|
spawnId,
|
|
11361
|
-
iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
|
|
12965
|
+
iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0,
|
|
12966
|
+
agentSpanId,
|
|
12967
|
+
startedAt: runStartedAt,
|
|
12968
|
+
segments: segment
|
|
11362
12969
|
};
|
|
11363
12970
|
recordSegment("pending", { subagentStatus: "paused", input });
|
|
11364
12971
|
parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
|
|
@@ -11384,7 +12991,10 @@ async function runChild(spec, input, deps, ref, opts) {
|
|
|
11384
12991
|
pendingKind: "user_question",
|
|
11385
12992
|
pendingId: childEntry.id,
|
|
11386
12993
|
spawnId,
|
|
11387
|
-
iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0
|
|
12994
|
+
iterations: traceScope ? subagentTraceScopeOf(traceScope)?.iterations : void 0,
|
|
12995
|
+
agentSpanId,
|
|
12996
|
+
startedAt: runStartedAt,
|
|
12997
|
+
segments: segment
|
|
11388
12998
|
};
|
|
11389
12999
|
recordSegment("pending", { subagentStatus: "paused", input });
|
|
11390
13000
|
parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
|
|
@@ -12071,6 +13681,30 @@ ${pluginAppend}`;
|
|
|
12071
13681
|
};
|
|
12072
13682
|
}
|
|
12073
13683
|
}
|
|
13684
|
+
const traceHandoff = {};
|
|
13685
|
+
const noteTraceHandoff = (current) => {
|
|
13686
|
+
traceHandoff.continuation = current.ctx?.__traceContinuation;
|
|
13687
|
+
traceHandoff.events = current.ctx?.[DEFERRED_TRACE_EVENTS_KEY];
|
|
13688
|
+
};
|
|
13689
|
+
const closeDanglingTrace = async (status, error) => {
|
|
13690
|
+
const continuation = traceHandoff.continuation;
|
|
13691
|
+
const events = traceHandoff.events;
|
|
13692
|
+
traceHandoff.continuation = void 0;
|
|
13693
|
+
traceHandoff.events = void 0;
|
|
13694
|
+
if (!continuation) return;
|
|
13695
|
+
try {
|
|
13696
|
+
await closeTraceContinuation(continuation, {
|
|
13697
|
+
tracing: opts.tracing,
|
|
13698
|
+
exporters: pluginHost?.contributions.traceExporters,
|
|
13699
|
+
status,
|
|
13700
|
+
error,
|
|
13701
|
+
agentRuntime: base.__runtime,
|
|
13702
|
+
events
|
|
13703
|
+
});
|
|
13704
|
+
} catch (closeError) {
|
|
13705
|
+
console.warn("[agent-sdk] closing the trace failed:", closeError);
|
|
13706
|
+
}
|
|
13707
|
+
};
|
|
12074
13708
|
try {
|
|
12075
13709
|
const toolSet = buildInvokeToolSet();
|
|
12076
13710
|
const stateRef = toolSet.stateRef;
|
|
@@ -12149,11 +13783,15 @@ ${pluginAppend}`;
|
|
|
12149
13783
|
const result = await trySummarize(state, rawMessages, stateRef);
|
|
12150
13784
|
state = result.state;
|
|
12151
13785
|
rawMessages = result.rawMessages;
|
|
13786
|
+
noteTraceHandoff(state);
|
|
12152
13787
|
if (result.compressed) continue;
|
|
12153
13788
|
}
|
|
12154
13789
|
const modelMessages = buildModelMessages(state, resolved);
|
|
13790
|
+
traceHandoff.continuation = void 0;
|
|
13791
|
+
traceHandoff.events = void 0;
|
|
12155
13792
|
const res = await base.invoke({ ...state, messages: modelMessages }, turnConfig);
|
|
12156
13793
|
lastResult = res;
|
|
13794
|
+
noteTraceHandoff(res.state ?? state);
|
|
12157
13795
|
const currentSummaries = state.summaries;
|
|
12158
13796
|
const currentSummaryRecords = state.summaryRecords;
|
|
12159
13797
|
const currentPlan = state.plan;
|
|
@@ -12180,6 +13818,7 @@ ${pluginAppend}`;
|
|
|
12180
13818
|
const result = await trySummarize(state, rawMessages, stateRef);
|
|
12181
13819
|
state = result.state;
|
|
12182
13820
|
rawMessages = result.rawMessages;
|
|
13821
|
+
noteTraceHandoff(state);
|
|
12183
13822
|
continue;
|
|
12184
13823
|
}
|
|
12185
13824
|
if (state.ctx?.__finalizedDueToStructuredOutput) break;
|
|
@@ -12191,6 +13830,7 @@ ${pluginAppend}`;
|
|
|
12191
13830
|
const result = await trySummarize(state, rawMessages, stateRef);
|
|
12192
13831
|
state = result.state;
|
|
12193
13832
|
rawMessages = result.rawMessages;
|
|
13833
|
+
noteTraceHandoff(state);
|
|
12194
13834
|
if (result.compressed) continue;
|
|
12195
13835
|
}
|
|
12196
13836
|
}
|
|
@@ -12201,6 +13841,7 @@ ${pluginAppend}`;
|
|
|
12201
13841
|
lastResult = res;
|
|
12202
13842
|
}
|
|
12203
13843
|
if (state.ctx?.[DEFERRED_TRACE_EVENTS_KEY]) {
|
|
13844
|
+
traceHandoff.events = state.ctx[DEFERRED_TRACE_EVENTS_KEY];
|
|
12204
13845
|
const ctx = { ...state.ctx || {} };
|
|
12205
13846
|
delete ctx[DEFERRED_TRACE_EVENTS_KEY];
|
|
12206
13847
|
state = { ...state, ctx };
|
|
@@ -12220,8 +13861,12 @@ ${pluginAppend}`;
|
|
|
12220
13861
|
const strippedCtx = { ...endCtx };
|
|
12221
13862
|
delete strippedCtx.__traceContinuation;
|
|
12222
13863
|
lastResult = { ...lastResult, state: { ...lastResult.state, ctx: strippedCtx } };
|
|
13864
|
+
traceHandoff.continuation = endCtx.__traceContinuation;
|
|
13865
|
+
await closeDanglingTrace("success");
|
|
12223
13866
|
}
|
|
12224
13867
|
}
|
|
13868
|
+
traceHandoff.continuation = void 0;
|
|
13869
|
+
traceHandoff.events = void 0;
|
|
12225
13870
|
if (skillsEnabled && lastResult.state) {
|
|
12226
13871
|
const persisted = skillStateFromRegistry(toolSet.skillRegistryRef);
|
|
12227
13872
|
if (persisted) {
|
|
@@ -12267,6 +13912,11 @@ ${pluginAppend}`;
|
|
|
12267
13912
|
await endSession(endStatus, { result: lastResult });
|
|
12268
13913
|
return lastResult;
|
|
12269
13914
|
} catch (err) {
|
|
13915
|
+
await closeDanglingTrace("error", {
|
|
13916
|
+
message: err instanceof Error ? err.message : String(err),
|
|
13917
|
+
stack: err instanceof Error ? err.stack : void 0,
|
|
13918
|
+
name: err instanceof Error ? err.name : void 0
|
|
13919
|
+
});
|
|
12270
13920
|
await endSession("error", { error: err instanceof Error ? err : new Error(String(err)) });
|
|
12271
13921
|
throw err;
|
|
12272
13922
|
}
|
|
@@ -13183,7 +14833,7 @@ function isHookImplemented(hook) {
|
|
|
13183
14833
|
// src/plugins/builtin/guardrail.ts
|
|
13184
14834
|
init_content();
|
|
13185
14835
|
var ALLOW = { action: "allow" };
|
|
13186
|
-
var
|
|
14836
|
+
var RETRYABLE_STATUS2 = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
13187
14837
|
var RetryableGuardrailError = class extends Error {
|
|
13188
14838
|
constructor(message) {
|
|
13189
14839
|
super(message);
|
|
@@ -13281,7 +14931,7 @@ function httpGuardrail(options) {
|
|
|
13281
14931
|
} catch {
|
|
13282
14932
|
}
|
|
13283
14933
|
const message = `HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ""}${text ? ` - ${text.slice(0, 200)}` : ""}`;
|
|
13284
|
-
if (
|
|
14934
|
+
if (RETRYABLE_STATUS2.has(response.status)) throw new RetryableGuardrailError(message);
|
|
13285
14935
|
throw new Error(message);
|
|
13286
14936
|
}
|
|
13287
14937
|
return response.json();
|
|
@@ -13388,9 +15038,9 @@ function createGuardrailPlugin(options) {
|
|
|
13388
15038
|
});
|
|
13389
15039
|
const resolved = verdict ?? ALLOW;
|
|
13390
15040
|
if (resolved.raw?.disabled === true) {
|
|
13391
|
-
const
|
|
13392
|
-
if (!
|
|
13393
|
-
|
|
15041
|
+
const warned2 = (_b = ctx.store).__disabledWarned ?? (_b.__disabledWarned = /* @__PURE__ */ new Set());
|
|
15042
|
+
if (!warned2.has(request.phase)) {
|
|
15043
|
+
warned2.add(request.phase);
|
|
13394
15044
|
ctx.logger.warn(
|
|
13395
15045
|
`guardrail reports it is not active for the "${request.phase}" surface; nothing is being enforced there`
|
|
13396
15046
|
);
|
|
@@ -13887,7 +15537,7 @@ function safeJson(value) {
|
|
|
13887
15537
|
function matches(pattern, toolName) {
|
|
13888
15538
|
return typeof pattern === "string" ? pattern === toolName : pattern.test(toolName);
|
|
13889
15539
|
}
|
|
13890
|
-
function
|
|
15540
|
+
function asObject2(args) {
|
|
13891
15541
|
return args && typeof args === "object" ? args : {};
|
|
13892
15542
|
}
|
|
13893
15543
|
function toolPolicy(config = {}) {
|
|
@@ -13908,7 +15558,7 @@ function toolPolicy(config = {}) {
|
|
|
13908
15558
|
hooks: {
|
|
13909
15559
|
preToolUse: ({ toolName, args }, ctx) => {
|
|
13910
15560
|
var _a;
|
|
13911
|
-
const argObject =
|
|
15561
|
+
const argObject = asObject2(args);
|
|
13912
15562
|
const isControlPlane = CONTROL_PLANE_TOOL_NAMES.includes(toolName);
|
|
13913
15563
|
const allowListApplies = !isControlPlane || config.governControlPlaneTools === true;
|
|
13914
15564
|
if (config.allowOnly && allowListApplies && !config.allowOnly.some((pattern) => matches(pattern, toolName))) {
|
|
@@ -13970,7 +15620,7 @@ function pathSandbox(config) {
|
|
|
13970
15620
|
hooks: {
|
|
13971
15621
|
preToolUse: ({ toolName, args }) => {
|
|
13972
15622
|
if (config.tools && !config.tools.some((pattern) => matches(pattern, toolName))) return void 0;
|
|
13973
|
-
const argObject =
|
|
15623
|
+
const argObject = asObject2(args);
|
|
13974
15624
|
for (const key of argNames) {
|
|
13975
15625
|
const value = argObject[key];
|
|
13976
15626
|
if (typeof value !== "string" || value.length === 0) continue;
|
|
@@ -14738,7 +16388,7 @@ function mcp(config) {
|
|
|
14738
16388
|
}
|
|
14739
16389
|
|
|
14740
16390
|
// src/plugins/builtin/rateLimit.ts
|
|
14741
|
-
function
|
|
16391
|
+
function sleep2(ms, signal) {
|
|
14742
16392
|
return new Promise((resolve) => {
|
|
14743
16393
|
let timer;
|
|
14744
16394
|
const done = () => {
|
|
@@ -14795,7 +16445,7 @@ function rateLimit(config = {}) {
|
|
|
14795
16445
|
while (!attempt.ok) {
|
|
14796
16446
|
const remaining = deadline - Date.now();
|
|
14797
16447
|
if (!Number.isFinite(attempt.waitMs) || attempt.waitMs > remaining) break;
|
|
14798
|
-
await
|
|
16448
|
+
await sleep2(Math.max(1, attempt.waitMs), ctx.signal);
|
|
14799
16449
|
if (ctx.signal?.aborted) break;
|
|
14800
16450
|
attempt = consume(applicable);
|
|
14801
16451
|
}
|
|
@@ -15891,18 +17541,21 @@ function langfuseTracing(config = {}) {
|
|
|
15891
17541
|
}
|
|
15892
17542
|
|
|
15893
17543
|
// src/plugins/builtin/otel.ts
|
|
15894
|
-
function
|
|
15895
|
-
if (
|
|
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) {
|
|
17544
|
+
function otelTracing(config = {}) {
|
|
17545
|
+
if (config.endpoint !== void 0 && !config.endpoint.trim()) {
|
|
15902
17546
|
throw new Error("[agent-sdk] otelTracing requires a non-empty `endpoint`.");
|
|
15903
17547
|
}
|
|
17548
|
+
const name = config.name ?? "otel-tracing";
|
|
17549
|
+
let exporter;
|
|
17550
|
+
try {
|
|
17551
|
+
exporter = createOtlpExporter({ ...config, endpoint: config.endpoint?.trim(), name });
|
|
17552
|
+
} catch {
|
|
17553
|
+
throw new Error(
|
|
17554
|
+
"[agent-sdk] otelTracing requires a non-empty `endpoint` (or OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_TRACES_ENDPOINT in the environment)."
|
|
17555
|
+
);
|
|
17556
|
+
}
|
|
15904
17557
|
return {
|
|
15905
|
-
name
|
|
17558
|
+
name,
|
|
15906
17559
|
// Registers only the `sessionEnd` observer, and observers run concurrently,
|
|
15907
17560
|
// so this number orders nothing at runtime. It is set above checkpointing
|
|
15908
17561
|
// (900) to record intent: this plugin is the last thing interested in the
|
|
@@ -15910,8 +17563,9 @@ function otelTracing(config) {
|
|
|
15910
17563
|
priority: 950,
|
|
15911
17564
|
// Observability. A dropped export is a reporting gap, never a safety hole.
|
|
15912
17565
|
failureMode: "open",
|
|
17566
|
+
traceExporters: [exporter],
|
|
15913
17567
|
hooks: {
|
|
15914
|
-
sessionEnd: async (
|
|
17568
|
+
sessionEnd: async (_event, ctx) => {
|
|
15915
17569
|
const state = ctx.state;
|
|
15916
17570
|
const session = state.ctx?.__traceSession;
|
|
15917
17571
|
if (isSubagentTraceScope(session)) return;
|
|
@@ -15921,57 +17575,29 @@ function otelTracing(config) {
|
|
|
15921
17575
|
ctx.emit({ type: "metadata", otelTracing: { exported: false, reason: message } });
|
|
15922
17576
|
return;
|
|
15923
17577
|
}
|
|
15924
|
-
const
|
|
15925
|
-
const
|
|
15926
|
-
|
|
15927
|
-
const
|
|
15928
|
-
|
|
15929
|
-
|
|
15930
|
-
|
|
15931
|
-
|
|
15932
|
-
|
|
15933
|
-
|
|
15934
|
-
|
|
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);
|
|
17578
|
+
const reports = (session.exportReports ?? []).filter((report2) => !report2.sink && report2.exporter === name);
|
|
17579
|
+
const report = reports[reports.length - 1];
|
|
17580
|
+
if (!report) return;
|
|
17581
|
+
const { result } = report;
|
|
17582
|
+
if (!result.ok) {
|
|
17583
|
+
ctx.logger.warn(`otelTracing export failed: ${result.error ?? "unknown error"}`);
|
|
17584
|
+
return;
|
|
17585
|
+
}
|
|
17586
|
+
if (result.skipped) {
|
|
17587
|
+
ctx.emit({ type: "metadata", otelTracing: { exported: false, reason: result.reason ?? "nothing to export" } });
|
|
17588
|
+
return;
|
|
15974
17589
|
}
|
|
17590
|
+
ctx.emit({
|
|
17591
|
+
type: "metadata",
|
|
17592
|
+
otelTracing: {
|
|
17593
|
+
exported: true,
|
|
17594
|
+
endpoint: report.endpoint,
|
|
17595
|
+
spans: result.spans,
|
|
17596
|
+
terminal: report.terminal,
|
|
17597
|
+
// A 200 that refused some spans: the collector's count and message.
|
|
17598
|
+
...result.partialSuccess ? { rejectedSpans: result.partialSuccess.rejectedSpans, ...result.partialSuccess.message ? { rejectionMessage: result.partialSuccess.message } : {} } : {}
|
|
17599
|
+
}
|
|
17600
|
+
});
|
|
15975
17601
|
}
|
|
15976
17602
|
}
|
|
15977
17603
|
};
|
|
@@ -19007,9 +20633,9 @@ function mapAnthropicStopReason(reason) {
|
|
|
19007
20633
|
return "stop";
|
|
19008
20634
|
}
|
|
19009
20635
|
}
|
|
19010
|
-
function safeJsonParse(
|
|
20636
|
+
function safeJsonParse(str2) {
|
|
19011
20637
|
try {
|
|
19012
|
-
return JSON.parse(
|
|
20638
|
+
return JSON.parse(str2);
|
|
19013
20639
|
} catch {
|
|
19014
20640
|
return {};
|
|
19015
20641
|
}
|
|
@@ -19879,9 +21505,9 @@ function mediaTypeToFormat(mediaType) {
|
|
|
19879
21505
|
};
|
|
19880
21506
|
return map[mediaType] ?? "png";
|
|
19881
21507
|
}
|
|
19882
|
-
function safeJsonParse2(
|
|
21508
|
+
function safeJsonParse2(str2) {
|
|
19883
21509
|
try {
|
|
19884
|
-
return JSON.parse(
|
|
21510
|
+
return JSON.parse(str2);
|
|
19885
21511
|
} catch {
|
|
19886
21512
|
return {};
|
|
19887
21513
|
}
|
|
@@ -20278,10 +21904,13 @@ var VertexProvider = class extends BaseProvider {
|
|
|
20278
21904
|
textParts.push(part.text);
|
|
20279
21905
|
}
|
|
20280
21906
|
} else if (part.functionCall) {
|
|
21907
|
+
const suppliedId = typeof part.functionCall.id === "string" && part.functionCall.id ? part.functionCall.id : void 0;
|
|
21908
|
+
const position = toolCallIdx++;
|
|
20281
21909
|
toolCalls.push({
|
|
20282
|
-
id: `call_${
|
|
21910
|
+
id: suppliedId ?? `call_${position}`,
|
|
20283
21911
|
name: part.functionCall.name,
|
|
20284
21912
|
arguments: JSON.stringify(part.functionCall.args ?? {}),
|
|
21913
|
+
...suppliedId ? {} : { idSynthesized: true },
|
|
20285
21914
|
...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
|
|
20286
21915
|
});
|
|
20287
21916
|
}
|
|
@@ -20321,12 +21950,15 @@ var VertexProvider = class extends BaseProvider {
|
|
|
20321
21950
|
}
|
|
20322
21951
|
} else if (part.functionCall) {
|
|
20323
21952
|
if (!delta.toolCalls) delta.toolCalls = [];
|
|
21953
|
+
const suppliedId = typeof part.functionCall.id === "string" && part.functionCall.id ? part.functionCall.id : void 0;
|
|
21954
|
+
const position = counter.next++;
|
|
20324
21955
|
delta.toolCalls.push({
|
|
20325
21956
|
// Unique across the whole stream: the adapter merges chunks by id.
|
|
20326
|
-
id: `call_${
|
|
20327
|
-
index:
|
|
21957
|
+
id: suppliedId ?? `call_${position}`,
|
|
21958
|
+
index: position,
|
|
20328
21959
|
name: part.functionCall.name,
|
|
20329
21960
|
arguments: JSON.stringify(part.functionCall.args ?? {}),
|
|
21961
|
+
...suppliedId ? {} : { idSynthesized: true },
|
|
20330
21962
|
...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
|
|
20331
21963
|
});
|
|
20332
21964
|
}
|
|
@@ -20379,12 +22011,12 @@ function mapGeminiFinishReason(reason) {
|
|
|
20379
22011
|
return "stop";
|
|
20380
22012
|
}
|
|
20381
22013
|
}
|
|
20382
|
-
function base64url(
|
|
20383
|
-
return Buffer.from(
|
|
22014
|
+
function base64url(str2) {
|
|
22015
|
+
return Buffer.from(str2).toString("base64url");
|
|
20384
22016
|
}
|
|
20385
|
-
function safeJsonParse3(
|
|
22017
|
+
function safeJsonParse3(str2) {
|
|
20386
22018
|
try {
|
|
20387
|
-
return JSON.parse(
|
|
22019
|
+
return JSON.parse(str2);
|
|
20388
22020
|
} catch {
|
|
20389
22021
|
return {};
|
|
20390
22022
|
}
|
|
@@ -20429,6 +22061,7 @@ exports.DEFAULT_SUBAGENT_TOOL_NAMES = DEFAULT_SUBAGENT_TOOL_NAMES;
|
|
|
20429
22061
|
exports.DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS = DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS;
|
|
20430
22062
|
exports.DELEGATION_TOOL_NAMES = DELEGATION_TOOL_NAMES;
|
|
20431
22063
|
exports.DedupTracker = DedupTracker;
|
|
22064
|
+
exports.GENAI_SEMCONV_COMMIT = GENAI_SEMCONV_COMMIT;
|
|
20432
22065
|
exports.GuardrailPhase = GuardrailPhase;
|
|
20433
22066
|
exports.HOOK_CONTRACT_VERSION = HOOK_CONTRACT_VERSION;
|
|
20434
22067
|
exports.HOOK_NAMES = HOOK_NAMES;
|
|
@@ -20469,6 +22102,7 @@ exports.canSpawn = canSpawn;
|
|
|
20469
22102
|
exports.captureSnapshot = captureSnapshot;
|
|
20470
22103
|
exports.checkpointing = checkpointing;
|
|
20471
22104
|
exports.clearLearnedModelRules = clearLearnedModelRules;
|
|
22105
|
+
exports.closeTraceContinuation = closeTraceContinuation;
|
|
20472
22106
|
exports.codePresenceRule = codePresenceRule;
|
|
20473
22107
|
exports.coerceToolArgs = coerceToolArgs;
|
|
20474
22108
|
exports.cognipeerGuardrail = cognipeerGuardrail;
|
|
@@ -20503,6 +22137,7 @@ exports.createJsonGuardrail = createJsonGuardrail;
|
|
|
20503
22137
|
exports.createManageTodoListAliasTool = createManageTodoListAliasTool;
|
|
20504
22138
|
exports.createManageTodoTool = createManageTodoTool;
|
|
20505
22139
|
exports.createOpenSkillTool = createOpenSkillTool;
|
|
22140
|
+
exports.createOtlpExporter = createOtlpExporter;
|
|
20506
22141
|
exports.createParallelTool = createParallelTool;
|
|
20507
22142
|
exports.createPluginHost = createPluginHost;
|
|
20508
22143
|
exports.createProvider = createProvider;
|
|
@@ -20539,6 +22174,8 @@ exports.extractMessageText = extractMessageText;
|
|
|
20539
22174
|
exports.fileCheckpointStore = fileCheckpointStore;
|
|
20540
22175
|
exports.fileSink = fileSink;
|
|
20541
22176
|
exports.findSubagent = findSubagent;
|
|
22177
|
+
exports.foldSupersededSpans = foldSupersededSpans;
|
|
22178
|
+
exports.formatTraceparent = formatTraceparent;
|
|
20542
22179
|
exports.formatZodError = formatZodError;
|
|
20543
22180
|
exports.fromLangchainModel = fromLangchainModel;
|
|
20544
22181
|
exports.fromLangchainTools = fromLangchainTools;
|
|
@@ -20586,6 +22223,7 @@ exports.outputGuard = outputGuard;
|
|
|
20586
22223
|
exports.parseApprovalDecision = parseApprovalDecision;
|
|
20587
22224
|
exports.parseModelError = parseModelError;
|
|
20588
22225
|
exports.parseSkillFrontmatter = parseSkillFrontmatter;
|
|
22226
|
+
exports.parseTraceparent = parseTraceparent;
|
|
20589
22227
|
exports.pathSandbox = pathSandbox;
|
|
20590
22228
|
exports.piiRedaction = piiRedaction;
|
|
20591
22229
|
exports.pluginCapabilities = pluginCapabilities;
|
|
@@ -20640,6 +22278,7 @@ exports.toolPolicy = toolPolicy;
|
|
|
20640
22278
|
exports.traceContinuationOf = traceContinuationOf;
|
|
20641
22279
|
exports.traceSectionsFromMessages = traceSectionsFromMessages;
|
|
20642
22280
|
exports.traceSessionToOtlp = traceSessionToOtlp;
|
|
22281
|
+
exports.traceparentOf = traceparentOf;
|
|
20643
22282
|
exports.validateReasoningConfig = validateReasoningConfig;
|
|
20644
22283
|
exports.validateToolArgs = validateToolArgs;
|
|
20645
22284
|
exports.webhookApproval = webhookApproval;
|