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