@cognipeer/agent-sdk 0.2.4 → 0.2.6
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 +179 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -7
- package/dist/index.d.ts +17 -7
- package/dist/index.mjs +179 -102
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -142,39 +142,38 @@ function withTools(model, tools) {
|
|
|
142
142
|
}
|
|
143
143
|
function fromLangchainModel(lcModel) {
|
|
144
144
|
if (!lcModel) throw new Error("fromLangchainModel: model is undefined/null");
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const detail = img.detail;
|
|
163
|
-
return { type: "image_url", image_url: { url: dataUrl, detail } };
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return part;
|
|
145
|
+
const normalizeContent = (content) => {
|
|
146
|
+
if (content == null) return content;
|
|
147
|
+
if (typeof content === "string") return content;
|
|
148
|
+
if (Array.isArray(content)) {
|
|
149
|
+
return content.map((part) => {
|
|
150
|
+
if (!part || typeof part !== "object") return part;
|
|
151
|
+
if (part.type === "text") return { type: "text", text: String(part.text ?? "") };
|
|
152
|
+
if (part.type === "image_url") {
|
|
153
|
+
const img = part.image_url;
|
|
154
|
+
if (typeof img === "string") return { type: "image_url", image_url: { url: img } };
|
|
155
|
+
if (img && typeof img === "object") {
|
|
156
|
+
if ("url" in img) return { type: "image_url", image_url: img };
|
|
157
|
+
if ("base64" in img) {
|
|
158
|
+
const media = img.media_type || "image/jpeg";
|
|
159
|
+
const dataUrl = `data:${media};base64,${img.base64}`;
|
|
160
|
+
const detail = img.detail;
|
|
161
|
+
return { type: "image_url", image_url: { url: dataUrl, detail } };
|
|
167
162
|
}
|
|
168
|
-
|
|
169
|
-
|
|
163
|
+
}
|
|
164
|
+
return part;
|
|
170
165
|
}
|
|
171
|
-
return
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
166
|
+
return part;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return content;
|
|
170
|
+
};
|
|
171
|
+
const toLC = (m) => {
|
|
172
|
+
if (m._getType || m.lc_serializable) return m;
|
|
173
|
+
return { role: m.role, content: normalizeContent(m.content), name: m.name, tool_calls: m.tool_calls, tool_call_id: m.tool_call_id };
|
|
174
|
+
};
|
|
175
|
+
const adapted = {
|
|
176
|
+
invoke: async (messages, options) => {
|
|
178
177
|
const lcMessages = messages.map(toLC);
|
|
179
178
|
const response = await lcModel.invoke(lcMessages, options);
|
|
180
179
|
if (response && typeof response === "object") {
|
|
@@ -192,36 +191,6 @@ function fromLangchainModel(lcModel) {
|
|
|
192
191
|
},
|
|
193
192
|
stream: async function* (messages, options) {
|
|
194
193
|
if (typeof lcModel.stream !== "function") return;
|
|
195
|
-
const normalizeContent = (content) => {
|
|
196
|
-
if (content == null) return content;
|
|
197
|
-
if (typeof content === "string") return content;
|
|
198
|
-
if (Array.isArray(content)) {
|
|
199
|
-
return content.map((part) => {
|
|
200
|
-
if (!part || typeof part !== "object") return part;
|
|
201
|
-
if (part.type === "text") return { type: "text", text: String(part.text ?? "") };
|
|
202
|
-
if (part.type === "image_url") {
|
|
203
|
-
const img = part.image_url;
|
|
204
|
-
if (typeof img === "string") return { type: "image_url", image_url: { url: img } };
|
|
205
|
-
if (img && typeof img === "object") {
|
|
206
|
-
if ("url" in img) return { type: "image_url", image_url: img };
|
|
207
|
-
if ("base64" in img) {
|
|
208
|
-
const media = img.media_type || "image/jpeg";
|
|
209
|
-
const dataUrl = `data:${media};base64,${img.base64}`;
|
|
210
|
-
const detail = img.detail;
|
|
211
|
-
return { type: "image_url", image_url: { url: dataUrl, detail } };
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return part;
|
|
215
|
-
}
|
|
216
|
-
return part;
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
return content;
|
|
220
|
-
};
|
|
221
|
-
const toLC = (m) => {
|
|
222
|
-
if (m._getType || m.lc_serializable) return m;
|
|
223
|
-
return { role: m.role, content: normalizeContent(m.content), name: m.name, tool_calls: m.tool_calls, tool_call_id: m.tool_call_id };
|
|
224
|
-
};
|
|
225
194
|
const lcMessages = messages.map(toLC);
|
|
226
195
|
for await (const chunk of lcModel.stream(lcMessages, options)) {
|
|
227
196
|
yield chunk;
|
|
@@ -1305,7 +1274,18 @@ function createAgentCoreNode(opts) {
|
|
|
1305
1274
|
outputSchema: opts.outputSchema,
|
|
1306
1275
|
tracing: opts.tracing
|
|
1307
1276
|
};
|
|
1308
|
-
const
|
|
1277
|
+
const rawTools = runtime.tools ?? [];
|
|
1278
|
+
const seenNames = /* @__PURE__ */ new Map();
|
|
1279
|
+
const tools = [];
|
|
1280
|
+
for (const t of rawTools) {
|
|
1281
|
+
const tName = t.name ?? t.schema?.title;
|
|
1282
|
+
if (tName && seenNames.has(tName)) {
|
|
1283
|
+
tools[seenNames.get(tName)] = t;
|
|
1284
|
+
} else {
|
|
1285
|
+
if (tName) seenNames.set(tName, tools.length);
|
|
1286
|
+
tools.push(t);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1309
1289
|
const modelWithTools = runtime.model?.bindTools ? runtime.model.bindTools(tools) : runtime.model;
|
|
1310
1290
|
const traceSession = state.ctx?.__traceSession;
|
|
1311
1291
|
const actorName = runtime.name ?? opts.name ?? "agent";
|
|
@@ -1358,26 +1338,6 @@ function createAgentCoreNode(opts) {
|
|
|
1358
1338
|
}
|
|
1359
1339
|
return filteredMsgs;
|
|
1360
1340
|
};
|
|
1361
|
-
const debugToolPairing = (messagesToSend) => {
|
|
1362
|
-
try {
|
|
1363
|
-
const msgs = Array.isArray(messagesToSend) ? messagesToSend : [];
|
|
1364
|
-
const toolUseIds = [];
|
|
1365
|
-
const missingResults = [];
|
|
1366
|
-
for (let i = 0; i < msgs.length; i++) {
|
|
1367
|
-
const m = msgs[i];
|
|
1368
|
-
if (m?.role === "assistant") {
|
|
1369
|
-
for (const tu of extractToolUses(m)) {
|
|
1370
|
-
toolUseIds.push(tu.id);
|
|
1371
|
-
const next = msgs[i + 1];
|
|
1372
|
-
if (!(next && next.role === "tool" && (next.tool_call_id === tu.id || next.tool_call_id === m?.tool_call_id))) {
|
|
1373
|
-
missingResults.push({ id: tu.id, atIndex: i, tool: tu.name });
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
} catch (e) {
|
|
1379
|
-
}
|
|
1380
|
-
};
|
|
1381
1341
|
const onEvent = state.ctx?.__onEvent;
|
|
1382
1342
|
const onStream = state.ctx?.__onStream;
|
|
1383
1343
|
const streamingEnabled = Boolean(state.ctx?.__streaming);
|
|
@@ -1396,8 +1356,124 @@ function createAgentCoreNode(opts) {
|
|
|
1396
1356
|
};
|
|
1397
1357
|
let response;
|
|
1398
1358
|
try {
|
|
1399
|
-
const
|
|
1400
|
-
|
|
1359
|
+
const ensureUniqueToolCallIds = (input) => {
|
|
1360
|
+
const msgs = Array.isArray(input) ? input.map((m) => ({ ...m })) : [];
|
|
1361
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
1362
|
+
let counter = 0;
|
|
1363
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
1364
|
+
const m = msgs[i];
|
|
1365
|
+
if (m?.role !== "assistant") continue;
|
|
1366
|
+
const hasToolCalls = Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
|
|
1367
|
+
const contentArr = Array.isArray(m.content) ? m.content : [];
|
|
1368
|
+
const hasContentToolUse = contentArr.some((c) => c?.type === "tool_use" && c?.id);
|
|
1369
|
+
const hasAdditionalToolCalls = Array.isArray(m.additional_kwargs?.tool_calls) && m.additional_kwargs.tool_calls.length > 0;
|
|
1370
|
+
if (!hasToolCalls && !hasContentToolUse && !hasAdditionalToolCalls) continue;
|
|
1371
|
+
if (hasToolCalls && hasContentToolUse) {
|
|
1372
|
+
const toolCallIds = new Set(
|
|
1373
|
+
m.tool_calls.filter((tc) => tc?.id).map((tc) => tc.id)
|
|
1374
|
+
);
|
|
1375
|
+
const filtered = contentArr.filter((c) => {
|
|
1376
|
+
if (c?.type === "tool_use" && c?.id && toolCallIds.has(c.id)) return false;
|
|
1377
|
+
return true;
|
|
1378
|
+
});
|
|
1379
|
+
if (filtered.length === 0) {
|
|
1380
|
+
m.content = "";
|
|
1381
|
+
} else if (filtered.length !== contentArr.length) {
|
|
1382
|
+
m.content = filtered.length === 1 && filtered[0]?.type === "text" ? filtered[0].text ?? "" : filtered;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
if (hasAdditionalToolCalls && Array.isArray(m.content)) {
|
|
1386
|
+
const akIds = new Set(
|
|
1387
|
+
m.additional_kwargs.tool_calls.filter((tc) => tc?.id).map((tc) => tc.id)
|
|
1388
|
+
);
|
|
1389
|
+
const arr = m.content;
|
|
1390
|
+
const filtered = arr.filter((c) => {
|
|
1391
|
+
if (c?.type === "tool_use" && c?.id && akIds.has(c.id)) return false;
|
|
1392
|
+
return true;
|
|
1393
|
+
});
|
|
1394
|
+
if (filtered.length !== arr.length) {
|
|
1395
|
+
m.content = filtered.length === 0 ? "" : filtered.length === 1 && filtered[0]?.type === "text" ? filtered[0].text ?? "" : filtered;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
if (hasToolCalls) {
|
|
1399
|
+
m.tool_calls = m.tool_calls.map((tc) => ({ ...tc }));
|
|
1400
|
+
}
|
|
1401
|
+
if (hasAdditionalToolCalls) {
|
|
1402
|
+
m.additional_kwargs = { ...m.additional_kwargs };
|
|
1403
|
+
m.additional_kwargs.tool_calls = m.additional_kwargs.tool_calls.map((tc) => ({ ...tc }));
|
|
1404
|
+
}
|
|
1405
|
+
const remainingContentArr = Array.isArray(m.content) ? m.content : [];
|
|
1406
|
+
const hasRemainingContentToolUse = remainingContentArr.some((c) => c?.type === "tool_use" && c?.id);
|
|
1407
|
+
if (hasRemainingContentToolUse) {
|
|
1408
|
+
m.content = remainingContentArr.map(
|
|
1409
|
+
(c) => c && typeof c === "object" ? { ...c } : c
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
const idsInMessage = /* @__PURE__ */ new Set();
|
|
1413
|
+
if (hasToolCalls) {
|
|
1414
|
+
for (const tc of m.tool_calls) {
|
|
1415
|
+
if (tc?.id) idsInMessage.add(tc.id);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
if (hasRemainingContentToolUse) {
|
|
1419
|
+
for (const c of m.content) {
|
|
1420
|
+
if (c?.type === "tool_use" && c?.id) idsInMessage.add(c.id);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
if (hasAdditionalToolCalls) {
|
|
1424
|
+
for (const tc of m.additional_kwargs.tool_calls) {
|
|
1425
|
+
if (tc?.id) idsInMessage.add(tc.id);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
for (const id of idsInMessage) {
|
|
1429
|
+
if (!usedIds.has(id)) {
|
|
1430
|
+
usedIds.add(id);
|
|
1431
|
+
continue;
|
|
1432
|
+
}
|
|
1433
|
+
const newId = `${id}_${Date.now()}_${counter++}`;
|
|
1434
|
+
if (hasToolCalls) {
|
|
1435
|
+
for (const tc of m.tool_calls) {
|
|
1436
|
+
if (tc.id === id) tc.id = newId;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
if (hasRemainingContentToolUse && Array.isArray(m.content)) {
|
|
1440
|
+
for (const c of m.content) {
|
|
1441
|
+
if (c?.type === "tool_use" && c.id === id) c.id = newId;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
if (hasAdditionalToolCalls) {
|
|
1445
|
+
for (const tc of m.additional_kwargs.tool_calls) {
|
|
1446
|
+
if (tc.id === id) tc.id = newId;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
for (let j = i + 1; j < msgs.length; j++) {
|
|
1450
|
+
const next = msgs[j];
|
|
1451
|
+
if (next?.role === "assistant") break;
|
|
1452
|
+
if (next?.role === "tool" && next.tool_call_id === id) {
|
|
1453
|
+
next.tool_call_id = newId;
|
|
1454
|
+
}
|
|
1455
|
+
if (Array.isArray(next?.content)) {
|
|
1456
|
+
let contentCloned = false;
|
|
1457
|
+
for (let k = 0; k < next.content.length; k++) {
|
|
1458
|
+
const block = next.content[k];
|
|
1459
|
+
if (block?.type === "tool_result" && block.tool_use_id === id) {
|
|
1460
|
+
if (!contentCloned) {
|
|
1461
|
+
next.content = next.content.map((x) => x && typeof x === "object" ? { ...x } : x);
|
|
1462
|
+
contentCloned = true;
|
|
1463
|
+
}
|
|
1464
|
+
next.content[k].tool_use_id = newId;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
usedIds.add(newId);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
return msgs;
|
|
1473
|
+
};
|
|
1474
|
+
const normalizedMessages = ensureUniqueToolCallIds(
|
|
1475
|
+
normalizeBedrockToolPairing([...state.messages])
|
|
1476
|
+
);
|
|
1401
1477
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
1402
1478
|
let streamedText = "";
|
|
1403
1479
|
let streamedMessage;
|
|
@@ -2043,7 +2119,9 @@ function resolveToolApprovalState(state, resolution) {
|
|
|
2043
2119
|
// src/utils/utilTokens.ts
|
|
2044
2120
|
function countApproxTokens(text) {
|
|
2045
2121
|
if (!text) return 0;
|
|
2046
|
-
|
|
2122
|
+
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
2123
|
+
const asciiCount = text.length - nonAsciiCount;
|
|
2124
|
+
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
2047
2125
|
}
|
|
2048
2126
|
|
|
2049
2127
|
// src/agent.ts
|
|
@@ -2146,7 +2224,8 @@ function createAgent(opts) {
|
|
|
2146
2224
|
let result = false;
|
|
2147
2225
|
try {
|
|
2148
2226
|
result = onStateChange(state);
|
|
2149
|
-
} catch {
|
|
2227
|
+
} catch (err) {
|
|
2228
|
+
console.warn("[agent-sdk] onStateChange callback error:", err);
|
|
2150
2229
|
result = false;
|
|
2151
2230
|
}
|
|
2152
2231
|
if (!result) return false;
|
|
@@ -2324,7 +2403,9 @@ function createAgent(opts) {
|
|
|
2324
2403
|
if (toolCallsAfter.length > 0) {
|
|
2325
2404
|
state = { ...state, ...await toolsNode(state) };
|
|
2326
2405
|
}
|
|
2327
|
-
} catch {
|
|
2406
|
+
} catch (err) {
|
|
2407
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2408
|
+
emit?.({ type: "metadata", error: `Structured output force-finalize failed: ${errMsg}` });
|
|
2328
2409
|
}
|
|
2329
2410
|
}
|
|
2330
2411
|
}
|
|
@@ -2342,13 +2423,15 @@ function createAgent(opts) {
|
|
|
2342
2423
|
const emit = (e) => {
|
|
2343
2424
|
try {
|
|
2344
2425
|
onEvent?.(e);
|
|
2345
|
-
} catch {
|
|
2426
|
+
} catch (err) {
|
|
2427
|
+
console.warn("[agent-sdk] onEvent callback error:", err);
|
|
2346
2428
|
}
|
|
2347
2429
|
};
|
|
2348
2430
|
const emitProgress = (progress) => {
|
|
2349
2431
|
try {
|
|
2350
2432
|
onProgress?.(progress);
|
|
2351
|
-
} catch {
|
|
2433
|
+
} catch (err) {
|
|
2434
|
+
console.warn("[agent-sdk] onProgress callback error:", err);
|
|
2352
2435
|
}
|
|
2353
2436
|
emit({ type: "progress", ...progress });
|
|
2354
2437
|
};
|
|
@@ -2858,6 +2941,12 @@ async function applyTokenLimits({
|
|
|
2858
2941
|
let total = messages.reduce((acc, m) => acc + countApproxTokens(String(m.content || "")), 0);
|
|
2859
2942
|
if (total <= budget) return state;
|
|
2860
2943
|
const newMessages = [...messages];
|
|
2944
|
+
while (total > budget && newMessages.length > 1) {
|
|
2945
|
+
const idx = newMessages.findIndex((m) => m.role !== "system");
|
|
2946
|
+
if (idx === -1) break;
|
|
2947
|
+
const removed = newMessages.splice(idx, 1)[0];
|
|
2948
|
+
total -= countApproxTokens(String(removed.content || ""));
|
|
2949
|
+
}
|
|
2861
2950
|
return { ...state, messages: newMessages };
|
|
2862
2951
|
}
|
|
2863
2952
|
function createContextTools(stateRef, opts) {
|
|
@@ -2959,19 +3048,7 @@ function needsSummarization(state, opts, summarizationEnabled) {
|
|
|
2959
3048
|
return "";
|
|
2960
3049
|
}).join("\n");
|
|
2961
3050
|
const tokenCount = countApproxTokens(allText);
|
|
2962
|
-
|
|
2963
|
-
if (process.env.DEBUG_SUMMARIZATION) {
|
|
2964
|
-
const msgCount = (state.messages || []).length;
|
|
2965
|
-
const toolMsgs = (state.messages || []).filter((m) => m.role === "tool");
|
|
2966
|
-
const toolDetails = toolMsgs.map((m, i) => {
|
|
2967
|
-
const contentStr = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
2968
|
-
return `[${i}] id:${m.tool_call_id?.slice(-8) || "none"} len:${contentStr.length} preview:"${contentStr.slice(0, 30)}..."`;
|
|
2969
|
-
});
|
|
2970
|
-
console.log(`[Summarization] Messages: ${msgCount}, Tool messages: ${toolMsgs.length}`);
|
|
2971
|
-
toolDetails.forEach((d) => console.log(` ${d}`));
|
|
2972
|
-
console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Needs summarization: ${needsSum}`);
|
|
2973
|
-
}
|
|
2974
|
-
return needsSum;
|
|
3051
|
+
return tokenCount > maxTok;
|
|
2975
3052
|
} catch (e) {
|
|
2976
3053
|
return false;
|
|
2977
3054
|
}
|