@cognipeer/agent-sdk 0.2.7 → 0.2.8
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 +62 -244
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -15
- package/dist/index.d.ts +8 -15
- package/dist/index.mjs +62 -244
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.d.cts
CHANGED
|
@@ -75,15 +75,16 @@ interface ToolInterface<TInput = any, TOutput = any, TCallOptions = any> {
|
|
|
75
75
|
approvalDefaults?: any;
|
|
76
76
|
[key: string]: any;
|
|
77
77
|
}
|
|
78
|
-
type RunnableConfig =
|
|
78
|
+
type RunnableConfig = {
|
|
79
|
+
[key: string]: any;
|
|
80
|
+
};
|
|
79
81
|
type BaseMessage = {
|
|
80
82
|
role: string;
|
|
81
83
|
name?: string;
|
|
82
84
|
content: string | ContentPart[];
|
|
83
85
|
tool_calls?: any;
|
|
84
86
|
tool_call_id?: string;
|
|
85
|
-
|
|
86
|
-
additional_kwargs?: Record<string, any>;
|
|
87
|
+
[key: string]: any;
|
|
87
88
|
};
|
|
88
89
|
type AIMessage = BaseMessage & {
|
|
89
90
|
role: 'assistant';
|
|
@@ -143,7 +144,6 @@ type AgentLimits = {
|
|
|
143
144
|
maxToolCalls?: number;
|
|
144
145
|
maxParallelTools?: number;
|
|
145
146
|
};
|
|
146
|
-
/** @deprecated Use AgentLimits instead */
|
|
147
147
|
type SmartAgentLimits = AgentLimits;
|
|
148
148
|
type TraceSinkFileConfig = {
|
|
149
149
|
type: "file";
|
|
@@ -168,20 +168,15 @@ type TraceSinkConfig = TraceSinkFileConfig | TraceSinkCustomConfig | TraceSinkCo
|
|
|
168
168
|
type TracingMode = "batched" | "streaming";
|
|
169
169
|
type TracingConfig = {
|
|
170
170
|
enabled: boolean;
|
|
171
|
-
logData?: boolean;
|
|
172
|
-
/** Tracing mode:
|
|
173
|
-
* - "batched" (default): Events are collected and sent together when session ends
|
|
174
|
-
* - "streaming": Session starts immediately, events are sent in real-time as they occur
|
|
175
|
-
*/
|
|
176
171
|
mode?: TracingMode;
|
|
172
|
+
logData?: boolean;
|
|
177
173
|
sink?: TraceSinkConfig;
|
|
178
174
|
};
|
|
179
|
-
/** @deprecated Use TracingConfig instead */
|
|
180
175
|
type SmartAgentTracingConfig = TracingConfig;
|
|
181
176
|
type AgentOptions = {
|
|
182
177
|
name?: string;
|
|
183
178
|
version?: string;
|
|
184
|
-
model:
|
|
179
|
+
model: any;
|
|
185
180
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
186
181
|
guardrails?: ConversationGuardrail[];
|
|
187
182
|
handoffs?: HandoffDescriptor[];
|
|
@@ -193,7 +188,7 @@ type AgentOptions = {
|
|
|
193
188
|
type SmartAgentOptions = {
|
|
194
189
|
name?: string;
|
|
195
190
|
version?: string;
|
|
196
|
-
model:
|
|
191
|
+
model: any;
|
|
197
192
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
198
193
|
guardrails?: ConversationGuardrail[];
|
|
199
194
|
handoffs?: HandoffDescriptor[];
|
|
@@ -215,7 +210,7 @@ type SmartAgentOptions = {
|
|
|
215
210
|
type AgentRuntimeConfig = {
|
|
216
211
|
name?: string;
|
|
217
212
|
version?: string;
|
|
218
|
-
model:
|
|
213
|
+
model: any;
|
|
219
214
|
tools: Array<ToolInterface<any, any, any>>;
|
|
220
215
|
guardrails?: ConversationGuardrail[];
|
|
221
216
|
systemPrompt?: string;
|
|
@@ -393,9 +388,7 @@ type TraceSessionRuntime = {
|
|
|
393
388
|
errors: TraceErrorRecord[];
|
|
394
389
|
fileBaseDir?: string;
|
|
395
390
|
fileSessionDir?: string;
|
|
396
|
-
/** For streaming mode: whether session start has been sent to sink */
|
|
397
391
|
sessionStarted?: boolean;
|
|
398
|
-
/** Agent info for streaming mode session start */
|
|
399
392
|
agentInfo?: {
|
|
400
393
|
name?: string;
|
|
401
394
|
version?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -75,15 +75,16 @@ interface ToolInterface<TInput = any, TOutput = any, TCallOptions = any> {
|
|
|
75
75
|
approvalDefaults?: any;
|
|
76
76
|
[key: string]: any;
|
|
77
77
|
}
|
|
78
|
-
type RunnableConfig =
|
|
78
|
+
type RunnableConfig = {
|
|
79
|
+
[key: string]: any;
|
|
80
|
+
};
|
|
79
81
|
type BaseMessage = {
|
|
80
82
|
role: string;
|
|
81
83
|
name?: string;
|
|
82
84
|
content: string | ContentPart[];
|
|
83
85
|
tool_calls?: any;
|
|
84
86
|
tool_call_id?: string;
|
|
85
|
-
|
|
86
|
-
additional_kwargs?: Record<string, any>;
|
|
87
|
+
[key: string]: any;
|
|
87
88
|
};
|
|
88
89
|
type AIMessage = BaseMessage & {
|
|
89
90
|
role: 'assistant';
|
|
@@ -143,7 +144,6 @@ type AgentLimits = {
|
|
|
143
144
|
maxToolCalls?: number;
|
|
144
145
|
maxParallelTools?: number;
|
|
145
146
|
};
|
|
146
|
-
/** @deprecated Use AgentLimits instead */
|
|
147
147
|
type SmartAgentLimits = AgentLimits;
|
|
148
148
|
type TraceSinkFileConfig = {
|
|
149
149
|
type: "file";
|
|
@@ -168,20 +168,15 @@ type TraceSinkConfig = TraceSinkFileConfig | TraceSinkCustomConfig | TraceSinkCo
|
|
|
168
168
|
type TracingMode = "batched" | "streaming";
|
|
169
169
|
type TracingConfig = {
|
|
170
170
|
enabled: boolean;
|
|
171
|
-
logData?: boolean;
|
|
172
|
-
/** Tracing mode:
|
|
173
|
-
* - "batched" (default): Events are collected and sent together when session ends
|
|
174
|
-
* - "streaming": Session starts immediately, events are sent in real-time as they occur
|
|
175
|
-
*/
|
|
176
171
|
mode?: TracingMode;
|
|
172
|
+
logData?: boolean;
|
|
177
173
|
sink?: TraceSinkConfig;
|
|
178
174
|
};
|
|
179
|
-
/** @deprecated Use TracingConfig instead */
|
|
180
175
|
type SmartAgentTracingConfig = TracingConfig;
|
|
181
176
|
type AgentOptions = {
|
|
182
177
|
name?: string;
|
|
183
178
|
version?: string;
|
|
184
|
-
model:
|
|
179
|
+
model: any;
|
|
185
180
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
186
181
|
guardrails?: ConversationGuardrail[];
|
|
187
182
|
handoffs?: HandoffDescriptor[];
|
|
@@ -193,7 +188,7 @@ type AgentOptions = {
|
|
|
193
188
|
type SmartAgentOptions = {
|
|
194
189
|
name?: string;
|
|
195
190
|
version?: string;
|
|
196
|
-
model:
|
|
191
|
+
model: any;
|
|
197
192
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
198
193
|
guardrails?: ConversationGuardrail[];
|
|
199
194
|
handoffs?: HandoffDescriptor[];
|
|
@@ -215,7 +210,7 @@ type SmartAgentOptions = {
|
|
|
215
210
|
type AgentRuntimeConfig = {
|
|
216
211
|
name?: string;
|
|
217
212
|
version?: string;
|
|
218
|
-
model:
|
|
213
|
+
model: any;
|
|
219
214
|
tools: Array<ToolInterface<any, any, any>>;
|
|
220
215
|
guardrails?: ConversationGuardrail[];
|
|
221
216
|
systemPrompt?: string;
|
|
@@ -393,9 +388,7 @@ type TraceSessionRuntime = {
|
|
|
393
388
|
errors: TraceErrorRecord[];
|
|
394
389
|
fileBaseDir?: string;
|
|
395
390
|
fileSessionDir?: string;
|
|
396
|
-
/** For streaming mode: whether session start has been sent to sink */
|
|
397
391
|
sessionStarted?: boolean;
|
|
398
|
-
/** Agent info for streaming mode session start */
|
|
399
392
|
agentInfo?: {
|
|
400
393
|
name?: string;
|
|
401
394
|
version?: string;
|
package/dist/index.mjs
CHANGED
|
@@ -638,7 +638,7 @@ async function postStreamingSessionStart(baseUrl, headers, payload) {
|
|
|
638
638
|
if (!fetchFn) {
|
|
639
639
|
throw new Error("HTTP sink requires fetch to be available in this runtime.");
|
|
640
640
|
}
|
|
641
|
-
const url = `${baseUrl.replace(/\/$/, "")}/${payload.sessionId}/start`;
|
|
641
|
+
const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/start`;
|
|
642
642
|
const finalHeaders = { ...headers || {} };
|
|
643
643
|
if (!Object.keys(finalHeaders).some((key) => key.toLowerCase() === "content-type")) {
|
|
644
644
|
finalHeaders["content-type"] = "application/json";
|
|
@@ -672,7 +672,7 @@ async function postStreamingEvent(baseUrl, headers, sessionId, event) {
|
|
|
672
672
|
if (!fetchFn) {
|
|
673
673
|
throw new Error("HTTP sink requires fetch to be available in this runtime.");
|
|
674
674
|
}
|
|
675
|
-
const url = `${baseUrl.replace(/\/$/, "")}/${sessionId}/events`;
|
|
675
|
+
const url = `${baseUrl.replace(/\/$/, "")}/stream/${sessionId}/events`;
|
|
676
676
|
const finalHeaders = { ...headers || {} };
|
|
677
677
|
if (!Object.keys(finalHeaders).some((key) => key.toLowerCase() === "content-type")) {
|
|
678
678
|
finalHeaders["content-type"] = "application/json";
|
|
@@ -706,7 +706,7 @@ async function postStreamingSessionEnd(baseUrl, headers, payload) {
|
|
|
706
706
|
if (!fetchFn) {
|
|
707
707
|
throw new Error("HTTP sink requires fetch to be available in this runtime.");
|
|
708
708
|
}
|
|
709
|
-
const url = `${baseUrl.replace(/\/$/, "")}/${payload.sessionId}/end`;
|
|
709
|
+
const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/end`;
|
|
710
710
|
const finalHeaders = { ...headers || {} };
|
|
711
711
|
if (!Object.keys(finalHeaders).some((key) => key.toLowerCase() === "content-type")) {
|
|
712
712
|
finalHeaders["content-type"] = "application/json";
|
|
@@ -1271,18 +1271,7 @@ function createAgentCoreNode(opts) {
|
|
|
1271
1271
|
outputSchema: opts.outputSchema,
|
|
1272
1272
|
tracing: opts.tracing
|
|
1273
1273
|
};
|
|
1274
|
-
const
|
|
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
|
-
}
|
|
1274
|
+
const tools = runtime.tools ?? [];
|
|
1286
1275
|
const modelWithTools = runtime.model?.bindTools ? runtime.model.bindTools(tools) : runtime.model;
|
|
1287
1276
|
const traceSession = state.ctx?.__traceSession;
|
|
1288
1277
|
const actorName = runtime.name ?? opts.name ?? "agent";
|
|
@@ -1335,6 +1324,26 @@ function createAgentCoreNode(opts) {
|
|
|
1335
1324
|
}
|
|
1336
1325
|
return filteredMsgs;
|
|
1337
1326
|
};
|
|
1327
|
+
const debugToolPairing = (messagesToSend) => {
|
|
1328
|
+
try {
|
|
1329
|
+
const msgs = Array.isArray(messagesToSend) ? messagesToSend : [];
|
|
1330
|
+
const toolUseIds = [];
|
|
1331
|
+
const missingResults = [];
|
|
1332
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
1333
|
+
const m = msgs[i];
|
|
1334
|
+
if (m?.role === "assistant") {
|
|
1335
|
+
for (const tu of extractToolUses(m)) {
|
|
1336
|
+
toolUseIds.push(tu.id);
|
|
1337
|
+
const next = msgs[i + 1];
|
|
1338
|
+
if (!(next && next.role === "tool" && (next.tool_call_id === tu.id || next.tool_call_id === m?.tool_call_id))) {
|
|
1339
|
+
missingResults.push({ id: tu.id, atIndex: i, tool: tu.name });
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
} catch (e) {
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1338
1347
|
const onEvent = state.ctx?.__onEvent;
|
|
1339
1348
|
const onStream = state.ctx?.__onStream;
|
|
1340
1349
|
const streamingEnabled = Boolean(state.ctx?.__streaming);
|
|
@@ -1353,130 +1362,12 @@ function createAgentCoreNode(opts) {
|
|
|
1353
1362
|
};
|
|
1354
1363
|
let response;
|
|
1355
1364
|
try {
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
const usedIds = /* @__PURE__ */ new Set();
|
|
1359
|
-
let counter = 0;
|
|
1360
|
-
for (let i = 0; i < msgs.length; i++) {
|
|
1361
|
-
const m = msgs[i];
|
|
1362
|
-
if (m?.role !== "assistant") continue;
|
|
1363
|
-
const hasToolCalls = Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
|
|
1364
|
-
const contentArr = Array.isArray(m.content) ? m.content : [];
|
|
1365
|
-
const hasContentToolUse = contentArr.some((c) => c?.type === "tool_use" && c?.id);
|
|
1366
|
-
const hasAdditionalToolCalls = Array.isArray(m.additional_kwargs?.tool_calls) && m.additional_kwargs.tool_calls.length > 0;
|
|
1367
|
-
if (!hasToolCalls && !hasContentToolUse && !hasAdditionalToolCalls) continue;
|
|
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
|
-
}
|
|
1381
|
-
}
|
|
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)
|
|
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 }));
|
|
1397
|
-
}
|
|
1398
|
-
if (hasAdditionalToolCalls) {
|
|
1399
|
-
m.additional_kwargs = { ...m.additional_kwargs };
|
|
1400
|
-
m.additional_kwargs.tool_calls = m.additional_kwargs.tool_calls.map((tc) => ({ ...tc }));
|
|
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
|
-
}
|
|
1409
|
-
const idsInMessage = /* @__PURE__ */ new Set();
|
|
1410
|
-
if (hasToolCalls) {
|
|
1411
|
-
for (const tc of m.tool_calls) {
|
|
1412
|
-
if (tc?.id) idsInMessage.add(tc.id);
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
if (hasRemainingContentToolUse) {
|
|
1416
|
-
for (const c of m.content) {
|
|
1417
|
-
if (c?.type === "tool_use" && c?.id) idsInMessage.add(c.id);
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
if (hasAdditionalToolCalls) {
|
|
1421
|
-
for (const tc of m.additional_kwargs.tool_calls) {
|
|
1422
|
-
if (tc?.id) idsInMessage.add(tc.id);
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
for (const id of idsInMessage) {
|
|
1426
|
-
if (!usedIds.has(id)) {
|
|
1427
|
-
usedIds.add(id);
|
|
1428
|
-
continue;
|
|
1429
|
-
}
|
|
1430
|
-
const newId = `${id}_${Date.now()}_${counter++}`;
|
|
1431
|
-
if (hasToolCalls) {
|
|
1432
|
-
for (const tc of m.tool_calls) {
|
|
1433
|
-
if (tc.id === id) tc.id = newId;
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
if (hasRemainingContentToolUse && Array.isArray(m.content)) {
|
|
1437
|
-
for (const c of m.content) {
|
|
1438
|
-
if (c?.type === "tool_use" && c.id === id) c.id = newId;
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
if (hasAdditionalToolCalls) {
|
|
1442
|
-
for (const tc of m.additional_kwargs.tool_calls) {
|
|
1443
|
-
if (tc.id === id) tc.id = newId;
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
for (let j = i + 1; j < msgs.length; j++) {
|
|
1447
|
-
const next = msgs[j];
|
|
1448
|
-
if (next?.role === "assistant") break;
|
|
1449
|
-
if (next?.role === "tool" && next.tool_call_id === id) {
|
|
1450
|
-
next.tool_call_id = newId;
|
|
1451
|
-
}
|
|
1452
|
-
if (Array.isArray(next?.content)) {
|
|
1453
|
-
let contentCloned = false;
|
|
1454
|
-
for (let k = 0; k < next.content.length; k++) {
|
|
1455
|
-
const block = next.content[k];
|
|
1456
|
-
if (block?.type === "tool_result" && block.tool_use_id === id) {
|
|
1457
|
-
if (!contentCloned) {
|
|
1458
|
-
next.content = next.content.map((x) => x && typeof x === "object" ? { ...x } : x);
|
|
1459
|
-
contentCloned = true;
|
|
1460
|
-
}
|
|
1461
|
-
next.content[k].tool_use_id = newId;
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
usedIds.add(newId);
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
return msgs;
|
|
1470
|
-
};
|
|
1471
|
-
const normalizedMessages = ensureUniqueToolCallIds(
|
|
1472
|
-
normalizeBedrockToolPairing([...state.messages])
|
|
1473
|
-
);
|
|
1365
|
+
const normalizedMessages = normalizeBedrockToolPairing([...state.messages]);
|
|
1366
|
+
debugToolPairing(normalizedMessages);
|
|
1474
1367
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
1475
1368
|
let streamedText = "";
|
|
1476
1369
|
let streamedMessage;
|
|
1477
|
-
const
|
|
1478
|
-
const stream = typeof streamResult?.then === "function" ? await streamResult : streamResult;
|
|
1479
|
-
for await (const chunk of stream) {
|
|
1370
|
+
for await (const chunk of modelWithTools.stream(normalizedMessages, { signal: abortSignal, cancellationToken })) {
|
|
1480
1371
|
if (cancellationToken && cancellationToken.isCancellationRequested || abortSignal?.aborted) {
|
|
1481
1372
|
break;
|
|
1482
1373
|
}
|
|
@@ -1521,7 +1412,7 @@ function createAgentCoreNode(opts) {
|
|
|
1521
1412
|
...state.messages,
|
|
1522
1413
|
response
|
|
1523
1414
|
];
|
|
1524
|
-
const rawUsage = response?.
|
|
1415
|
+
const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
|
|
1525
1416
|
const normalized = normalizeUsage(rawUsage);
|
|
1526
1417
|
const modelName = getModelName(runtime.model || opts.model) || "unknown_model";
|
|
1527
1418
|
const durationMs = Date.now() - start;
|
|
@@ -2726,83 +2617,6 @@ function createAgentNode(opts) {
|
|
|
2726
2617
|
};
|
|
2727
2618
|
}
|
|
2728
2619
|
|
|
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
|
-
|
|
2806
2620
|
// src/nodes/contextSummarize.ts
|
|
2807
2621
|
var systemMessage = (content) => ({ role: "system", content });
|
|
2808
2622
|
var humanMessage = (content) => ({ role: "user", content });
|
|
@@ -2861,7 +2675,8 @@ function createContextSummarizeNode(opts) {
|
|
|
2861
2675
|
if (compressableMessages.length === 0) {
|
|
2862
2676
|
return {};
|
|
2863
2677
|
}
|
|
2864
|
-
const
|
|
2678
|
+
const allTextBefore = messages.map((m) => typeof m.content === "string" ? m.content : Array.isArray(m.content) ? m.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? "").join("") : "").join("\n");
|
|
2679
|
+
const tokenCountBefore = countApproxTokens(allTextBefore);
|
|
2865
2680
|
const summaryPromptMaxTokens = config.summaryPromptMaxTokens;
|
|
2866
2681
|
const availableTokensForConversation = summaryPromptMaxTokens - 500;
|
|
2867
2682
|
const messageTexts = [];
|
|
@@ -2924,7 +2739,7 @@ Summary:`;
|
|
|
2924
2739
|
durationMs = Date.now() - startTime;
|
|
2925
2740
|
summaryText = typeof response.content === "string" ? response.content : Array.isArray(response.content) ? response.content.map((c) => c.text || "").join("") : JSON.stringify(response.content);
|
|
2926
2741
|
outputTokensEstimate = countApproxTokens(summaryText);
|
|
2927
|
-
const rawUsage = response?.
|
|
2742
|
+
const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
|
|
2928
2743
|
const normalized = normalizeUsage(rawUsage);
|
|
2929
2744
|
if (normalized) {
|
|
2930
2745
|
inputTokensActual = normalized.prompt_tokens;
|
|
@@ -2956,16 +2771,7 @@ Summary:`;
|
|
|
2956
2771
|
inputTokens: inputTokensEstimate,
|
|
2957
2772
|
outputTokens: 0,
|
|
2958
2773
|
error: { message: err?.message || String(err), stack: err?.stack },
|
|
2959
|
-
|
|
2960
|
-
summaryText: "",
|
|
2961
|
-
messagesCompressed: 0,
|
|
2962
|
-
tokenCountBefore,
|
|
2963
|
-
tokenCountAfter: tokenCountBefore,
|
|
2964
|
-
inputTokens: inputTokensEstimate,
|
|
2965
|
-
outputTokens: 0,
|
|
2966
|
-
durationMs,
|
|
2967
|
-
promptMessages: summaryPrompt
|
|
2968
|
-
})
|
|
2774
|
+
messageList: sanitizeTracePayload(summaryPrompt)
|
|
2969
2775
|
});
|
|
2970
2776
|
return {};
|
|
2971
2777
|
}
|
|
@@ -3019,7 +2825,8 @@ Summary:`;
|
|
|
3019
2825
|
};
|
|
3020
2826
|
const summaries = Array.isArray(state.summaries) ? [...state.summaries, summaryText] : [summaryText];
|
|
3021
2827
|
const finalMessages = [...validatedMessages, assistantSummaryCall, toolSummaryResponse];
|
|
3022
|
-
const
|
|
2828
|
+
const allTextAfter = finalMessages.map((m) => typeof m.content === "string" ? m.content : Array.isArray(m.content) ? m.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? "").join("") : "").join("\n");
|
|
2829
|
+
const tokenCountAfter = countApproxTokens(allTextAfter);
|
|
3023
2830
|
const summarizationEvent = {
|
|
3024
2831
|
type: "summarization",
|
|
3025
2832
|
summary: summaryText,
|
|
@@ -3046,21 +2853,10 @@ Summary:`;
|
|
|
3046
2853
|
outputTokens: outputTokensActual ?? outputTokensEstimate,
|
|
3047
2854
|
cachedInputTokens,
|
|
3048
2855
|
totalTokens: totalTokensActual,
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
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
|
-
}),
|
|
2856
|
+
messageList: sanitizeTracePayload([
|
|
2857
|
+
...summaryPrompt,
|
|
2858
|
+
{ role: "assistant", content: summaryText, name: "summarization_result" }
|
|
2859
|
+
]),
|
|
3064
2860
|
debug: {
|
|
3065
2861
|
messagesCompressed: compressableMessages.length,
|
|
3066
2862
|
tokenCountBefore,
|
|
@@ -3184,8 +2980,30 @@ function needsSummarization(state, opts, summarizationEnabled) {
|
|
|
3184
2980
|
maxTok = 5e4;
|
|
3185
2981
|
}
|
|
3186
2982
|
try {
|
|
3187
|
-
const
|
|
3188
|
-
|
|
2983
|
+
const allText = (state.messages || []).map((m) => {
|
|
2984
|
+
if (typeof m.content === "string") return m.content;
|
|
2985
|
+
if (Array.isArray(m.content)) {
|
|
2986
|
+
return m.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? JSON.stringify(c)).join("");
|
|
2987
|
+
}
|
|
2988
|
+
if (m.content && typeof m.content === "object") {
|
|
2989
|
+
return JSON.stringify(m.content);
|
|
2990
|
+
}
|
|
2991
|
+
return "";
|
|
2992
|
+
}).join("\n");
|
|
2993
|
+
const tokenCount = countApproxTokens(allText);
|
|
2994
|
+
const needsSum = tokenCount > maxTok;
|
|
2995
|
+
if (process.env.DEBUG_SUMMARIZATION) {
|
|
2996
|
+
const msgCount = (state.messages || []).length;
|
|
2997
|
+
const toolMsgs = (state.messages || []).filter((m) => m.role === "tool");
|
|
2998
|
+
const toolDetails = toolMsgs.map((m, i) => {
|
|
2999
|
+
const contentStr = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
3000
|
+
return `[${i}] id:${m.tool_call_id?.slice(-8) || "none"} len:${contentStr.length} preview:"${contentStr.slice(0, 30)}..."`;
|
|
3001
|
+
});
|
|
3002
|
+
console.log(`[Summarization] Messages: ${msgCount}, Tool messages: ${toolMsgs.length}`);
|
|
3003
|
+
toolDetails.forEach((d) => console.log(` ${d}`));
|
|
3004
|
+
console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Needs summarization: ${needsSum}`);
|
|
3005
|
+
}
|
|
3006
|
+
return needsSum;
|
|
3189
3007
|
} catch (e) {
|
|
3190
3008
|
return false;
|
|
3191
3009
|
}
|