@cognipeer/agent-sdk 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +311 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -8
- package/dist/index.d.ts +29 -8
- package/dist/index.mjs +311 -176
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -133,39 +133,38 @@ function withTools(model, tools) {
|
|
|
133
133
|
}
|
|
134
134
|
function fromLangchainModel(lcModel) {
|
|
135
135
|
if (!lcModel) throw new Error("fromLangchainModel: model is undefined/null");
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const detail = img.detail;
|
|
154
|
-
return { type: "image_url", image_url: { url: dataUrl, detail } };
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return part;
|
|
136
|
+
const normalizeContent = (content) => {
|
|
137
|
+
if (content == null) return content;
|
|
138
|
+
if (typeof content === "string") return content;
|
|
139
|
+
if (Array.isArray(content)) {
|
|
140
|
+
return content.map((part) => {
|
|
141
|
+
if (!part || typeof part !== "object") return part;
|
|
142
|
+
if (part.type === "text") return { type: "text", text: String(part.text ?? "") };
|
|
143
|
+
if (part.type === "image_url") {
|
|
144
|
+
const img = part.image_url;
|
|
145
|
+
if (typeof img === "string") return { type: "image_url", image_url: { url: img } };
|
|
146
|
+
if (img && typeof img === "object") {
|
|
147
|
+
if ("url" in img) return { type: "image_url", image_url: img };
|
|
148
|
+
if ("base64" in img) {
|
|
149
|
+
const media = img.media_type || "image/jpeg";
|
|
150
|
+
const dataUrl = `data:${media};base64,${img.base64}`;
|
|
151
|
+
const detail = img.detail;
|
|
152
|
+
return { type: "image_url", image_url: { url: dataUrl, detail } };
|
|
158
153
|
}
|
|
159
|
-
|
|
160
|
-
|
|
154
|
+
}
|
|
155
|
+
return part;
|
|
161
156
|
}
|
|
162
|
-
return
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
157
|
+
return part;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return content;
|
|
161
|
+
};
|
|
162
|
+
const toLC = (m) => {
|
|
163
|
+
if (m._getType || m.lc_serializable) return m;
|
|
164
|
+
return { role: m.role, content: normalizeContent(m.content), name: m.name, tool_calls: m.tool_calls, tool_call_id: m.tool_call_id };
|
|
165
|
+
};
|
|
166
|
+
const adapted = {
|
|
167
|
+
invoke: async (messages, options) => {
|
|
169
168
|
const lcMessages = messages.map(toLC);
|
|
170
169
|
const response = await lcModel.invoke(lcMessages, options);
|
|
171
170
|
if (response && typeof response === "object") {
|
|
@@ -183,38 +182,10 @@ function fromLangchainModel(lcModel) {
|
|
|
183
182
|
},
|
|
184
183
|
stream: async function* (messages, options) {
|
|
185
184
|
if (typeof lcModel.stream !== "function") return;
|
|
186
|
-
const normalizeContent = (content) => {
|
|
187
|
-
if (content == null) return content;
|
|
188
|
-
if (typeof content === "string") return content;
|
|
189
|
-
if (Array.isArray(content)) {
|
|
190
|
-
return content.map((part) => {
|
|
191
|
-
if (!part || typeof part !== "object") return part;
|
|
192
|
-
if (part.type === "text") return { type: "text", text: String(part.text ?? "") };
|
|
193
|
-
if (part.type === "image_url") {
|
|
194
|
-
const img = part.image_url;
|
|
195
|
-
if (typeof img === "string") return { type: "image_url", image_url: { url: img } };
|
|
196
|
-
if (img && typeof img === "object") {
|
|
197
|
-
if ("url" in img) return { type: "image_url", image_url: img };
|
|
198
|
-
if ("base64" in img) {
|
|
199
|
-
const media = img.media_type || "image/jpeg";
|
|
200
|
-
const dataUrl = `data:${media};base64,${img.base64}`;
|
|
201
|
-
const detail = img.detail;
|
|
202
|
-
return { type: "image_url", image_url: { url: dataUrl, detail } };
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return part;
|
|
206
|
-
}
|
|
207
|
-
return part;
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return content;
|
|
211
|
-
};
|
|
212
|
-
const toLC = (m) => {
|
|
213
|
-
if (m._getType || m.lc_serializable) return m;
|
|
214
|
-
return { role: m.role, content: normalizeContent(m.content), name: m.name, tool_calls: m.tool_calls, tool_call_id: m.tool_call_id };
|
|
215
|
-
};
|
|
216
185
|
const lcMessages = messages.map(toLC);
|
|
217
|
-
|
|
186
|
+
const streamResult = lcModel.stream(lcMessages, options);
|
|
187
|
+
const stream = typeof streamResult?.then === "function" ? await streamResult : streamResult;
|
|
188
|
+
for await (const chunk of stream) {
|
|
218
189
|
yield chunk;
|
|
219
190
|
}
|
|
220
191
|
},
|
|
@@ -336,17 +307,17 @@ function normalizeUsage(raw) {
|
|
|
336
307
|
raw.totalTokens,
|
|
337
308
|
(typeof prompt === "number" ? prompt : 0) + (typeof completion === "number" ? completion : 0)
|
|
338
309
|
);
|
|
339
|
-
const promptDetailsSrc = raw.prompt_tokens_details || raw.promptTokensDetails || {};
|
|
340
|
-
const completionDetailsSrc = raw.completion_tokens_details || raw.completionTokensDetails || {};
|
|
310
|
+
const promptDetailsSrc = raw.prompt_tokens_details || raw.promptTokensDetails || raw.input_token_details || raw.inputTokenDetails || {};
|
|
311
|
+
const completionDetailsSrc = raw.completion_tokens_details || raw.completionTokensDetails || raw.output_token_details || raw.outputTokenDetails || {};
|
|
341
312
|
const normalized = {
|
|
342
313
|
prompt_tokens: safe(prompt),
|
|
343
314
|
completion_tokens: safe(completion),
|
|
344
315
|
total_tokens: safe(total || (prompt || 0) + (completion || 0)),
|
|
345
316
|
prompt_tokens_details: {
|
|
346
317
|
cached_tokens: safe(
|
|
347
|
-
promptDetailsSrc.cached_tokens || promptDetailsSrc.cached || raw.cached_input_tokens || raw.cached_prompt_tokens
|
|
318
|
+
promptDetailsSrc.cached_tokens || promptDetailsSrc.cached || promptDetailsSrc.cache_read || raw.cached_input_tokens || raw.cached_prompt_tokens || raw.cache_read_input_tokens
|
|
348
319
|
),
|
|
349
|
-
audio_tokens: safe(promptDetailsSrc.audio_tokens)
|
|
320
|
+
audio_tokens: safe(promptDetailsSrc.audio_tokens || promptDetailsSrc.audio)
|
|
350
321
|
},
|
|
351
322
|
completion_tokens_details: {
|
|
352
323
|
reasoning_tokens: safe(completionDetailsSrc.reasoning_tokens),
|
|
@@ -1032,8 +1003,12 @@ function recordTraceEvent(session, event) {
|
|
|
1032
1003
|
session.summary.eventCounts[event.type] = (session.summary.eventCounts[event.type] || 0) + 1;
|
|
1033
1004
|
let sections;
|
|
1034
1005
|
if (session.resolvedConfig.logData) {
|
|
1035
|
-
|
|
1036
|
-
|
|
1006
|
+
if (event.sections && event.sections.length > 0) {
|
|
1007
|
+
sections = ensureUniqueSections(id, event.sections);
|
|
1008
|
+
} else {
|
|
1009
|
+
const converted = convertMessageListToSections(event.messageList);
|
|
1010
|
+
sections = ensureUniqueSections(id, converted);
|
|
1011
|
+
}
|
|
1037
1012
|
}
|
|
1038
1013
|
const resolvedModel = event.model ?? inferModelFromMessages(event.messageList);
|
|
1039
1014
|
const resolvedProvider = event.provider ?? inferProviderFromMessages(event.messageList);
|
|
@@ -1296,7 +1271,18 @@ function createAgentCoreNode(opts) {
|
|
|
1296
1271
|
outputSchema: opts.outputSchema,
|
|
1297
1272
|
tracing: opts.tracing
|
|
1298
1273
|
};
|
|
1299
|
-
const
|
|
1274
|
+
const rawTools = runtime.tools ?? [];
|
|
1275
|
+
const seenNames = /* @__PURE__ */ new Map();
|
|
1276
|
+
const tools = [];
|
|
1277
|
+
for (const t of rawTools) {
|
|
1278
|
+
const tName = t.name ?? t.schema?.title;
|
|
1279
|
+
if (tName && seenNames.has(tName)) {
|
|
1280
|
+
tools[seenNames.get(tName)] = t;
|
|
1281
|
+
} else {
|
|
1282
|
+
if (tName) seenNames.set(tName, tools.length);
|
|
1283
|
+
tools.push(t);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1300
1286
|
const modelWithTools = runtime.model?.bindTools ? runtime.model.bindTools(tools) : runtime.model;
|
|
1301
1287
|
const traceSession = state.ctx?.__traceSession;
|
|
1302
1288
|
const actorName = runtime.name ?? opts.name ?? "agent";
|
|
@@ -1349,26 +1335,6 @@ function createAgentCoreNode(opts) {
|
|
|
1349
1335
|
}
|
|
1350
1336
|
return filteredMsgs;
|
|
1351
1337
|
};
|
|
1352
|
-
const debugToolPairing = (messagesToSend) => {
|
|
1353
|
-
try {
|
|
1354
|
-
const msgs = Array.isArray(messagesToSend) ? messagesToSend : [];
|
|
1355
|
-
const toolUseIds = [];
|
|
1356
|
-
const missingResults = [];
|
|
1357
|
-
for (let i = 0; i < msgs.length; i++) {
|
|
1358
|
-
const m = msgs[i];
|
|
1359
|
-
if (m?.role === "assistant") {
|
|
1360
|
-
for (const tu of extractToolUses(m)) {
|
|
1361
|
-
toolUseIds.push(tu.id);
|
|
1362
|
-
const next = msgs[i + 1];
|
|
1363
|
-
if (!(next && next.role === "tool" && (next.tool_call_id === tu.id || next.tool_call_id === m?.tool_call_id))) {
|
|
1364
|
-
missingResults.push({ id: tu.id, atIndex: i, tool: tu.name });
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
} catch (e) {
|
|
1370
|
-
}
|
|
1371
|
-
};
|
|
1372
1338
|
const onEvent = state.ctx?.__onEvent;
|
|
1373
1339
|
const onStream = state.ctx?.__onStream;
|
|
1374
1340
|
const streamingEnabled = Boolean(state.ctx?.__streaming);
|
|
@@ -1399,25 +1365,54 @@ function createAgentCoreNode(opts) {
|
|
|
1399
1365
|
const hasContentToolUse = contentArr.some((c) => c?.type === "tool_use" && c?.id);
|
|
1400
1366
|
const hasAdditionalToolCalls = Array.isArray(m.additional_kwargs?.tool_calls) && m.additional_kwargs.tool_calls.length > 0;
|
|
1401
1367
|
if (!hasToolCalls && !hasContentToolUse && !hasAdditionalToolCalls) continue;
|
|
1402
|
-
if (hasToolCalls) {
|
|
1403
|
-
|
|
1368
|
+
if (hasToolCalls && hasContentToolUse) {
|
|
1369
|
+
const toolCallIds = new Set(
|
|
1370
|
+
m.tool_calls.filter((tc) => tc?.id).map((tc) => tc.id)
|
|
1371
|
+
);
|
|
1372
|
+
const filtered = contentArr.filter((c) => {
|
|
1373
|
+
if (c?.type === "tool_use" && c?.id && toolCallIds.has(c.id)) return false;
|
|
1374
|
+
return true;
|
|
1375
|
+
});
|
|
1376
|
+
if (filtered.length === 0) {
|
|
1377
|
+
m.content = "";
|
|
1378
|
+
} else if (filtered.length !== contentArr.length) {
|
|
1379
|
+
m.content = filtered.length === 1 && filtered[0]?.type === "text" ? filtered[0].text ?? "" : filtered;
|
|
1380
|
+
}
|
|
1404
1381
|
}
|
|
1405
|
-
if (
|
|
1406
|
-
|
|
1407
|
-
(
|
|
1382
|
+
if (hasAdditionalToolCalls && Array.isArray(m.content)) {
|
|
1383
|
+
const akIds = new Set(
|
|
1384
|
+
m.additional_kwargs.tool_calls.filter((tc) => tc?.id).map((tc) => tc.id)
|
|
1408
1385
|
);
|
|
1386
|
+
const arr = m.content;
|
|
1387
|
+
const filtered = arr.filter((c) => {
|
|
1388
|
+
if (c?.type === "tool_use" && c?.id && akIds.has(c.id)) return false;
|
|
1389
|
+
return true;
|
|
1390
|
+
});
|
|
1391
|
+
if (filtered.length !== arr.length) {
|
|
1392
|
+
m.content = filtered.length === 0 ? "" : filtered.length === 1 && filtered[0]?.type === "text" ? filtered[0].text ?? "" : filtered;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
if (hasToolCalls) {
|
|
1396
|
+
m.tool_calls = m.tool_calls.map((tc) => ({ ...tc }));
|
|
1409
1397
|
}
|
|
1410
1398
|
if (hasAdditionalToolCalls) {
|
|
1411
1399
|
m.additional_kwargs = { ...m.additional_kwargs };
|
|
1412
1400
|
m.additional_kwargs.tool_calls = m.additional_kwargs.tool_calls.map((tc) => ({ ...tc }));
|
|
1413
1401
|
}
|
|
1402
|
+
const remainingContentArr = Array.isArray(m.content) ? m.content : [];
|
|
1403
|
+
const hasRemainingContentToolUse = remainingContentArr.some((c) => c?.type === "tool_use" && c?.id);
|
|
1404
|
+
if (hasRemainingContentToolUse) {
|
|
1405
|
+
m.content = remainingContentArr.map(
|
|
1406
|
+
(c) => c && typeof c === "object" ? { ...c } : c
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1414
1409
|
const idsInMessage = /* @__PURE__ */ new Set();
|
|
1415
1410
|
if (hasToolCalls) {
|
|
1416
1411
|
for (const tc of m.tool_calls) {
|
|
1417
1412
|
if (tc?.id) idsInMessage.add(tc.id);
|
|
1418
1413
|
}
|
|
1419
1414
|
}
|
|
1420
|
-
if (
|
|
1415
|
+
if (hasRemainingContentToolUse) {
|
|
1421
1416
|
for (const c of m.content) {
|
|
1422
1417
|
if (c?.type === "tool_use" && c?.id) idsInMessage.add(c.id);
|
|
1423
1418
|
}
|
|
@@ -1438,7 +1433,7 @@ function createAgentCoreNode(opts) {
|
|
|
1438
1433
|
if (tc.id === id) tc.id = newId;
|
|
1439
1434
|
}
|
|
1440
1435
|
}
|
|
1441
|
-
if (
|
|
1436
|
+
if (hasRemainingContentToolUse && Array.isArray(m.content)) {
|
|
1442
1437
|
for (const c of m.content) {
|
|
1443
1438
|
if (c?.type === "tool_use" && c.id === id) c.id = newId;
|
|
1444
1439
|
}
|
|
@@ -1476,11 +1471,12 @@ function createAgentCoreNode(opts) {
|
|
|
1476
1471
|
const normalizedMessages = ensureUniqueToolCallIds(
|
|
1477
1472
|
normalizeBedrockToolPairing([...state.messages])
|
|
1478
1473
|
);
|
|
1479
|
-
debugToolPairing(normalizedMessages);
|
|
1480
1474
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
1481
1475
|
let streamedText = "";
|
|
1482
1476
|
let streamedMessage;
|
|
1483
|
-
|
|
1477
|
+
const streamResult = modelWithTools.stream(normalizedMessages, { signal: abortSignal, cancellationToken });
|
|
1478
|
+
const stream = typeof streamResult?.then === "function" ? await streamResult : streamResult;
|
|
1479
|
+
for await (const chunk of stream) {
|
|
1484
1480
|
if (cancellationToken && cancellationToken.isCancellationRequested || abortSignal?.aborted) {
|
|
1485
1481
|
break;
|
|
1486
1482
|
}
|
|
@@ -1525,7 +1521,7 @@ function createAgentCoreNode(opts) {
|
|
|
1525
1521
|
...state.messages,
|
|
1526
1522
|
response
|
|
1527
1523
|
];
|
|
1528
|
-
const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
|
|
1524
|
+
const rawUsage = response?.usage_metadata || response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
|
|
1529
1525
|
const normalized = normalizeUsage(rawUsage);
|
|
1530
1526
|
const modelName = getModelName(runtime.model || opts.model) || "unknown_model";
|
|
1531
1527
|
const durationMs = Date.now() - start;
|
|
@@ -1616,41 +1612,6 @@ function createToolsNode(initialTools, opts) {
|
|
|
1616
1612
|
const remaining = Math.max(0, limits.maxToolCalls - toolCount);
|
|
1617
1613
|
const planned = toolCalls.slice(0, remaining);
|
|
1618
1614
|
const skipped = toolCalls.slice(remaining);
|
|
1619
|
-
for (const tc of skipped) {
|
|
1620
|
-
onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
|
|
1621
|
-
const sanitizedArgs = sanitizeTracePayload(tc.args);
|
|
1622
|
-
const messageList = [
|
|
1623
|
-
{
|
|
1624
|
-
role: "assistant",
|
|
1625
|
-
name: tc.name,
|
|
1626
|
-
content: `Skipped tool due to tool-call limit: ${tc.name}`,
|
|
1627
|
-
tool_calls: [
|
|
1628
|
-
{
|
|
1629
|
-
id: tc.id,
|
|
1630
|
-
type: "function",
|
|
1631
|
-
function: {
|
|
1632
|
-
name: tc.name,
|
|
1633
|
-
arguments: sanitizedArgs
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
]
|
|
1637
|
-
}
|
|
1638
|
-
];
|
|
1639
|
-
recordTraceEvent(traceSession, {
|
|
1640
|
-
type: "tool_call",
|
|
1641
|
-
label: `Tool Skipped - ${tc.name}`,
|
|
1642
|
-
actor: { scope: "tool", name: tc.name, role: "tool" },
|
|
1643
|
-
status: "skipped",
|
|
1644
|
-
toolExecutionId: tc.id,
|
|
1645
|
-
messageList
|
|
1646
|
-
});
|
|
1647
|
-
appended.push({
|
|
1648
|
-
role: "tool",
|
|
1649
|
-
content: `Skipped tool due to tool-call limit: ${tc.name}`,
|
|
1650
|
-
tool_call_id: tc.id || `${tc.name}_${appended.length}`,
|
|
1651
|
-
name: tc.name
|
|
1652
|
-
});
|
|
1653
|
-
}
|
|
1654
1615
|
const isCancelled = () => {
|
|
1655
1616
|
if (abortSignal?.aborted) return { cancelled: true, reason: "aborted" };
|
|
1656
1617
|
if (cancellationToken && cancellationToken.isCancellationRequested) return { cancelled: true, reason: "cancelled" };
|
|
@@ -1891,6 +1852,42 @@ function createToolsNode(initialTools, opts) {
|
|
|
1891
1852
|
break;
|
|
1892
1853
|
}
|
|
1893
1854
|
}
|
|
1855
|
+
for (const tc of skipped) {
|
|
1856
|
+
onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
|
|
1857
|
+
const sanitizedArgs = sanitizeTracePayload(tc.args);
|
|
1858
|
+
const messageList = [
|
|
1859
|
+
{
|
|
1860
|
+
role: "assistant",
|
|
1861
|
+
name: tc.name,
|
|
1862
|
+
content: `Skipped tool due to tool-call limit: ${tc.name}`,
|
|
1863
|
+
tool_calls: [
|
|
1864
|
+
{
|
|
1865
|
+
id: tc.id,
|
|
1866
|
+
type: "function",
|
|
1867
|
+
function: {
|
|
1868
|
+
name: tc.name,
|
|
1869
|
+
arguments: sanitizedArgs
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
]
|
|
1873
|
+
}
|
|
1874
|
+
];
|
|
1875
|
+
recordTraceEvent(traceSession, {
|
|
1876
|
+
type: "tool_call",
|
|
1877
|
+
label: `Tool Skipped - ${tc.name}`,
|
|
1878
|
+
actor: { scope: "tool", name: tc.name, role: "tool" },
|
|
1879
|
+
status: "skipped",
|
|
1880
|
+
toolExecutionId: tc.id,
|
|
1881
|
+
messageList
|
|
1882
|
+
});
|
|
1883
|
+
appended.push({
|
|
1884
|
+
role: "tool",
|
|
1885
|
+
content: `Skipped tool due to tool-call limit: ${tc.name}`,
|
|
1886
|
+
tool_call_id: tc.id || `${tc.name}_${appended.length}`,
|
|
1887
|
+
name: tc.name
|
|
1888
|
+
});
|
|
1889
|
+
toolCount += 1;
|
|
1890
|
+
}
|
|
1894
1891
|
if (!awaitingApproval && state.ctx?.__awaitingApproval) {
|
|
1895
1892
|
const ctx = { ...state.ctx };
|
|
1896
1893
|
delete ctx.__awaitingApproval;
|
|
@@ -2122,7 +2119,62 @@ function resolveToolApprovalState(state, resolution) {
|
|
|
2122
2119
|
// src/utils/utilTokens.ts
|
|
2123
2120
|
function countApproxTokens(text) {
|
|
2124
2121
|
if (!text) return 0;
|
|
2125
|
-
|
|
2122
|
+
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
2123
|
+
const asciiCount = text.length - nonAsciiCount;
|
|
2124
|
+
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
2125
|
+
}
|
|
2126
|
+
function extractMessageText(m) {
|
|
2127
|
+
if (!m) return "";
|
|
2128
|
+
const parts = [];
|
|
2129
|
+
parts.push(m.role || "");
|
|
2130
|
+
if (m.name) parts.push(m.name);
|
|
2131
|
+
if (typeof m.content === "string") {
|
|
2132
|
+
parts.push(m.content);
|
|
2133
|
+
} else if (Array.isArray(m.content)) {
|
|
2134
|
+
for (const c of m.content) {
|
|
2135
|
+
if (typeof c === "string") parts.push(c);
|
|
2136
|
+
else if (c?.text) parts.push(c.text);
|
|
2137
|
+
else if (c?.content) parts.push(c.content);
|
|
2138
|
+
else if (c?.type === "tool_use" && c?.input) {
|
|
2139
|
+
parts.push(c.name || "");
|
|
2140
|
+
parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
|
|
2141
|
+
} else if (c != null && typeof c === "object") {
|
|
2142
|
+
parts.push(JSON.stringify(c));
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
} else if (m.content != null && typeof m.content === "object") {
|
|
2146
|
+
parts.push(JSON.stringify(m.content));
|
|
2147
|
+
}
|
|
2148
|
+
if (Array.isArray(m.tool_calls)) {
|
|
2149
|
+
for (const tc of m.tool_calls) {
|
|
2150
|
+
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2151
|
+
if (tc?.function?.arguments) {
|
|
2152
|
+
parts.push(
|
|
2153
|
+
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2154
|
+
);
|
|
2155
|
+
}
|
|
2156
|
+
if (tc?.name && !tc?.function?.name) parts.push(tc.name);
|
|
2157
|
+
if (tc?.args && !tc?.function?.arguments) {
|
|
2158
|
+
parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
if (Array.isArray(m.additional_kwargs?.tool_calls)) {
|
|
2163
|
+
for (const tc of m.additional_kwargs.tool_calls) {
|
|
2164
|
+
if (tc?.function?.name) parts.push(tc.function.name);
|
|
2165
|
+
if (tc?.function?.arguments) {
|
|
2166
|
+
parts.push(
|
|
2167
|
+
typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
return parts.join("\n");
|
|
2173
|
+
}
|
|
2174
|
+
function countMessagesTokens(messages) {
|
|
2175
|
+
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
2176
|
+
const allText = messages.map(extractMessageText).join("\n");
|
|
2177
|
+
return countApproxTokens(allText) + messages.length * 4;
|
|
2126
2178
|
}
|
|
2127
2179
|
|
|
2128
2180
|
// src/agent.ts
|
|
@@ -2225,7 +2277,8 @@ function createAgent(opts) {
|
|
|
2225
2277
|
let result = false;
|
|
2226
2278
|
try {
|
|
2227
2279
|
result = onStateChange(state);
|
|
2228
|
-
} catch {
|
|
2280
|
+
} catch (err) {
|
|
2281
|
+
console.warn("[agent-sdk] onStateChange callback error:", err);
|
|
2229
2282
|
result = false;
|
|
2230
2283
|
}
|
|
2231
2284
|
if (!result) return false;
|
|
@@ -2292,8 +2345,7 @@ function createAgent(opts) {
|
|
|
2292
2345
|
maxTok = 5e4;
|
|
2293
2346
|
}
|
|
2294
2347
|
if (maxTok) {
|
|
2295
|
-
const
|
|
2296
|
-
const tokenCount = countApproxTokens(allText);
|
|
2348
|
+
const tokenCount = countMessagesTokens(state.messages || []);
|
|
2297
2349
|
if (tokenCount > maxTok) {
|
|
2298
2350
|
const ctx = { ...state.ctx || {}, __needsSummarization: true };
|
|
2299
2351
|
state = { ...state, ctx };
|
|
@@ -2403,7 +2455,9 @@ function createAgent(opts) {
|
|
|
2403
2455
|
if (toolCallsAfter.length > 0) {
|
|
2404
2456
|
state = { ...state, ...await toolsNode(state) };
|
|
2405
2457
|
}
|
|
2406
|
-
} catch {
|
|
2458
|
+
} catch (err) {
|
|
2459
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2460
|
+
emit?.({ type: "metadata", error: `Structured output force-finalize failed: ${errMsg}` });
|
|
2407
2461
|
}
|
|
2408
2462
|
}
|
|
2409
2463
|
}
|
|
@@ -2421,13 +2475,15 @@ function createAgent(opts) {
|
|
|
2421
2475
|
const emit = (e) => {
|
|
2422
2476
|
try {
|
|
2423
2477
|
onEvent?.(e);
|
|
2424
|
-
} catch {
|
|
2478
|
+
} catch (err) {
|
|
2479
|
+
console.warn("[agent-sdk] onEvent callback error:", err);
|
|
2425
2480
|
}
|
|
2426
2481
|
};
|
|
2427
2482
|
const emitProgress = (progress) => {
|
|
2428
2483
|
try {
|
|
2429
2484
|
onProgress?.(progress);
|
|
2430
|
-
} catch {
|
|
2485
|
+
} catch (err) {
|
|
2486
|
+
console.warn("[agent-sdk] onProgress callback error:", err);
|
|
2431
2487
|
}
|
|
2432
2488
|
emit({ type: "progress", ...progress });
|
|
2433
2489
|
};
|
|
@@ -2670,6 +2726,83 @@ function createAgentNode(opts) {
|
|
|
2670
2726
|
};
|
|
2671
2727
|
}
|
|
2672
2728
|
|
|
2729
|
+
// src/utils/traceSections.ts
|
|
2730
|
+
function formatMessageContent(content) {
|
|
2731
|
+
if (content == null) return "";
|
|
2732
|
+
if (typeof content === "string") return content;
|
|
2733
|
+
if (Array.isArray(content)) {
|
|
2734
|
+
return content.map((item) => {
|
|
2735
|
+
if (typeof item === "string") return item;
|
|
2736
|
+
if (item && typeof item === "object") {
|
|
2737
|
+
if (typeof item.text === "string") return item.text;
|
|
2738
|
+
if (typeof item.content === "string") return item.content;
|
|
2739
|
+
try {
|
|
2740
|
+
return JSON.stringify(item);
|
|
2741
|
+
} catch {
|
|
2742
|
+
return String(item);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
try {
|
|
2746
|
+
return JSON.stringify(item);
|
|
2747
|
+
} catch {
|
|
2748
|
+
return String(item);
|
|
2749
|
+
}
|
|
2750
|
+
}).filter(Boolean).join("\n");
|
|
2751
|
+
}
|
|
2752
|
+
if (typeof content === "object") {
|
|
2753
|
+
if (typeof content.text === "string") return content.text;
|
|
2754
|
+
if (typeof content.content === "string") return content.content;
|
|
2755
|
+
try {
|
|
2756
|
+
return JSON.stringify(content, null, 2);
|
|
2757
|
+
} catch {
|
|
2758
|
+
return String(content);
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
return String(content);
|
|
2762
|
+
}
|
|
2763
|
+
function buildSummarizationSections(opts) {
|
|
2764
|
+
const sections = [];
|
|
2765
|
+
sections.push({
|
|
2766
|
+
kind: "summary",
|
|
2767
|
+
label: "Context Summary",
|
|
2768
|
+
content: opts.summaryText
|
|
2769
|
+
});
|
|
2770
|
+
const tokensSaved = opts.tokenCountBefore - opts.tokenCountAfter;
|
|
2771
|
+
const reductionPct = opts.tokenCountBefore > 0 ? Math.round(tokensSaved / opts.tokenCountBefore * 100) : 0;
|
|
2772
|
+
const metaData = {
|
|
2773
|
+
messagesCompressed: opts.messagesCompressed,
|
|
2774
|
+
tokenCountBefore: opts.tokenCountBefore,
|
|
2775
|
+
tokenCountAfter: opts.tokenCountAfter,
|
|
2776
|
+
tokensSaved,
|
|
2777
|
+
reductionPercent: reductionPct
|
|
2778
|
+
};
|
|
2779
|
+
if (opts.inputTokens !== void 0) metaData.inputTokens = opts.inputTokens;
|
|
2780
|
+
if (opts.outputTokens !== void 0) metaData.outputTokens = opts.outputTokens;
|
|
2781
|
+
if (opts.cachedInputTokens !== void 0) metaData.cachedInputTokens = opts.cachedInputTokens;
|
|
2782
|
+
if (opts.durationMs !== void 0) metaData.durationMs = opts.durationMs;
|
|
2783
|
+
if (opts.previousSummary) metaData.previousSummaryLength = opts.previousSummary.length;
|
|
2784
|
+
sections.push({
|
|
2785
|
+
kind: "metadata",
|
|
2786
|
+
label: "Summarization Stats",
|
|
2787
|
+
data: metaData
|
|
2788
|
+
});
|
|
2789
|
+
if (Array.isArray(opts.promptMessages) && opts.promptMessages.length > 0) {
|
|
2790
|
+
for (const msg of opts.promptMessages) {
|
|
2791
|
+
const role = typeof msg?.role === "string" ? msg.role : "system";
|
|
2792
|
+
const content = formatMessageContent(msg?.content ?? "");
|
|
2793
|
+
if (content) {
|
|
2794
|
+
sections.push({
|
|
2795
|
+
kind: "message",
|
|
2796
|
+
label: `Summarization Prompt (${role})`,
|
|
2797
|
+
role,
|
|
2798
|
+
content
|
|
2799
|
+
});
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
return sections;
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2673
2806
|
// src/nodes/contextSummarize.ts
|
|
2674
2807
|
var systemMessage = (content) => ({ role: "system", content });
|
|
2675
2808
|
var humanMessage = (content) => ({ role: "user", content });
|
|
@@ -2728,8 +2861,7 @@ function createContextSummarizeNode(opts) {
|
|
|
2728
2861
|
if (compressableMessages.length === 0) {
|
|
2729
2862
|
return {};
|
|
2730
2863
|
}
|
|
2731
|
-
const
|
|
2732
|
-
const tokenCountBefore = countApproxTokens(allTextBefore);
|
|
2864
|
+
const tokenCountBefore = countMessagesTokens(messages);
|
|
2733
2865
|
const summaryPromptMaxTokens = config.summaryPromptMaxTokens;
|
|
2734
2866
|
const availableTokensForConversation = summaryPromptMaxTokens - 500;
|
|
2735
2867
|
const messageTexts = [];
|
|
@@ -2792,7 +2924,7 @@ Summary:`;
|
|
|
2792
2924
|
durationMs = Date.now() - startTime;
|
|
2793
2925
|
summaryText = typeof response.content === "string" ? response.content : Array.isArray(response.content) ? response.content.map((c) => c.text || "").join("") : JSON.stringify(response.content);
|
|
2794
2926
|
outputTokensEstimate = countApproxTokens(summaryText);
|
|
2795
|
-
const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
|
|
2927
|
+
const rawUsage = response?.usage_metadata || response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
|
|
2796
2928
|
const normalized = normalizeUsage(rawUsage);
|
|
2797
2929
|
if (normalized) {
|
|
2798
2930
|
inputTokensActual = normalized.prompt_tokens;
|
|
@@ -2824,7 +2956,16 @@ Summary:`;
|
|
|
2824
2956
|
inputTokens: inputTokensEstimate,
|
|
2825
2957
|
outputTokens: 0,
|
|
2826
2958
|
error: { message: err?.message || String(err), stack: err?.stack },
|
|
2827
|
-
|
|
2959
|
+
sections: buildSummarizationSections({
|
|
2960
|
+
summaryText: "",
|
|
2961
|
+
messagesCompressed: 0,
|
|
2962
|
+
tokenCountBefore,
|
|
2963
|
+
tokenCountAfter: tokenCountBefore,
|
|
2964
|
+
inputTokens: inputTokensEstimate,
|
|
2965
|
+
outputTokens: 0,
|
|
2966
|
+
durationMs,
|
|
2967
|
+
promptMessages: summaryPrompt
|
|
2968
|
+
})
|
|
2828
2969
|
});
|
|
2829
2970
|
return {};
|
|
2830
2971
|
}
|
|
@@ -2878,8 +3019,7 @@ Summary:`;
|
|
|
2878
3019
|
};
|
|
2879
3020
|
const summaries = Array.isArray(state.summaries) ? [...state.summaries, summaryText] : [summaryText];
|
|
2880
3021
|
const finalMessages = [...validatedMessages, assistantSummaryCall, toolSummaryResponse];
|
|
2881
|
-
const
|
|
2882
|
-
const tokenCountAfter = countApproxTokens(allTextAfter);
|
|
3022
|
+
const tokenCountAfter = countMessagesTokens(finalMessages);
|
|
2883
3023
|
const summarizationEvent = {
|
|
2884
3024
|
type: "summarization",
|
|
2885
3025
|
summary: summaryText,
|
|
@@ -2906,10 +3046,21 @@ Summary:`;
|
|
|
2906
3046
|
outputTokens: outputTokensActual ?? outputTokensEstimate,
|
|
2907
3047
|
cachedInputTokens,
|
|
2908
3048
|
totalTokens: totalTokensActual,
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
3049
|
+
sections: buildSummarizationSections({
|
|
3050
|
+
summaryText,
|
|
3051
|
+
previousSummary: previousSummary || void 0,
|
|
3052
|
+
messagesCompressed: compressableMessages.length,
|
|
3053
|
+
tokenCountBefore,
|
|
3054
|
+
tokenCountAfter,
|
|
3055
|
+
inputTokens: inputTokensActual ?? inputTokensEstimate,
|
|
3056
|
+
outputTokens: outputTokensActual ?? outputTokensEstimate,
|
|
3057
|
+
cachedInputTokens,
|
|
3058
|
+
durationMs,
|
|
3059
|
+
promptMessages: sanitizeTracePayload([
|
|
3060
|
+
...summaryPrompt,
|
|
3061
|
+
{ role: "assistant", content: summaryText, name: "summarization_result" }
|
|
3062
|
+
])
|
|
3063
|
+
}),
|
|
2913
3064
|
debug: {
|
|
2914
3065
|
messagesCompressed: compressableMessages.length,
|
|
2915
3066
|
tokenCountBefore,
|
|
@@ -2937,6 +3088,12 @@ async function applyTokenLimits({
|
|
|
2937
3088
|
let total = messages.reduce((acc, m) => acc + countApproxTokens(String(m.content || "")), 0);
|
|
2938
3089
|
if (total <= budget) return state;
|
|
2939
3090
|
const newMessages = [...messages];
|
|
3091
|
+
while (total > budget && newMessages.length > 1) {
|
|
3092
|
+
const idx = newMessages.findIndex((m) => m.role !== "system");
|
|
3093
|
+
if (idx === -1) break;
|
|
3094
|
+
const removed = newMessages.splice(idx, 1)[0];
|
|
3095
|
+
total -= countApproxTokens(String(removed.content || ""));
|
|
3096
|
+
}
|
|
2940
3097
|
return { ...state, messages: newMessages };
|
|
2941
3098
|
}
|
|
2942
3099
|
function createContextTools(stateRef, opts) {
|
|
@@ -3027,30 +3184,8 @@ function needsSummarization(state, opts, summarizationEnabled) {
|
|
|
3027
3184
|
maxTok = 5e4;
|
|
3028
3185
|
}
|
|
3029
3186
|
try {
|
|
3030
|
-
const
|
|
3031
|
-
|
|
3032
|
-
if (Array.isArray(m.content)) {
|
|
3033
|
-
return m.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? JSON.stringify(c)).join("");
|
|
3034
|
-
}
|
|
3035
|
-
if (m.content && typeof m.content === "object") {
|
|
3036
|
-
return JSON.stringify(m.content);
|
|
3037
|
-
}
|
|
3038
|
-
return "";
|
|
3039
|
-
}).join("\n");
|
|
3040
|
-
const tokenCount = countApproxTokens(allText);
|
|
3041
|
-
const needsSum = tokenCount > maxTok;
|
|
3042
|
-
if (process.env.DEBUG_SUMMARIZATION) {
|
|
3043
|
-
const msgCount = (state.messages || []).length;
|
|
3044
|
-
const toolMsgs = (state.messages || []).filter((m) => m.role === "tool");
|
|
3045
|
-
const toolDetails = toolMsgs.map((m, i) => {
|
|
3046
|
-
const contentStr = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
3047
|
-
return `[${i}] id:${m.tool_call_id?.slice(-8) || "none"} len:${contentStr.length} preview:"${contentStr.slice(0, 30)}..."`;
|
|
3048
|
-
});
|
|
3049
|
-
console.log(`[Summarization] Messages: ${msgCount}, Tool messages: ${toolMsgs.length}`);
|
|
3050
|
-
toolDetails.forEach((d) => console.log(` ${d}`));
|
|
3051
|
-
console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Needs summarization: ${needsSum}`);
|
|
3052
|
-
}
|
|
3053
|
-
return needsSum;
|
|
3187
|
+
const tokenCount = countMessagesTokens(state.messages || []);
|
|
3188
|
+
return tokenCount > maxTok;
|
|
3054
3189
|
} catch (e) {
|
|
3055
3190
|
return false;
|
|
3056
3191
|
}
|
|
@@ -3448,6 +3583,6 @@ function createCodeGuardrail(options) {
|
|
|
3448
3583
|
});
|
|
3449
3584
|
}
|
|
3450
3585
|
|
|
3451
|
-
export { GuardrailPhase, agentVerdictRule, applyTokenLimits, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, createAgent, createAgentNode, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGuardrail, createJsonGuardrail, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, evaluateGuardrails, fileSink, fromLangchainModel, fromLangchainTools, httpSink, isSmartModel, jsonSchemaRule, regexRule, resolveToolApprovalState, restoreSnapshot, startStreamingSession, withTools };
|
|
3586
|
+
export { GuardrailPhase, agentVerdictRule, applyTokenLimits, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGuardrail, createJsonGuardrail, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, evaluateGuardrails, fileSink, fromLangchainModel, fromLangchainTools, httpSink, isSmartModel, jsonSchemaRule, regexRule, resolveToolApprovalState, restoreSnapshot, startStreamingSession, withTools };
|
|
3452
3587
|
//# sourceMappingURL=index.mjs.map
|
|
3453
3588
|
//# sourceMappingURL=index.mjs.map
|