@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.d.cts
CHANGED
|
@@ -75,16 +75,15 @@ interface ToolInterface<TInput = any, TOutput = any, TCallOptions = any> {
|
|
|
75
75
|
approvalDefaults?: any;
|
|
76
76
|
[key: string]: any;
|
|
77
77
|
}
|
|
78
|
-
type RunnableConfig =
|
|
79
|
-
[key: string]: any;
|
|
80
|
-
};
|
|
78
|
+
type RunnableConfig = Record<string, unknown>;
|
|
81
79
|
type BaseMessage = {
|
|
82
80
|
role: string;
|
|
83
81
|
name?: string;
|
|
84
82
|
content: string | ContentPart[];
|
|
85
83
|
tool_calls?: any;
|
|
86
84
|
tool_call_id?: string;
|
|
87
|
-
|
|
85
|
+
metadata?: Record<string, any>;
|
|
86
|
+
additional_kwargs?: Record<string, any>;
|
|
88
87
|
};
|
|
89
88
|
type AIMessage = BaseMessage & {
|
|
90
89
|
role: 'assistant';
|
|
@@ -144,6 +143,7 @@ type AgentLimits = {
|
|
|
144
143
|
maxToolCalls?: number;
|
|
145
144
|
maxParallelTools?: number;
|
|
146
145
|
};
|
|
146
|
+
/** @deprecated Use AgentLimits instead */
|
|
147
147
|
type SmartAgentLimits = AgentLimits;
|
|
148
148
|
type TraceSinkFileConfig = {
|
|
149
149
|
type: "file";
|
|
@@ -176,11 +176,12 @@ type TracingConfig = {
|
|
|
176
176
|
mode?: TracingMode;
|
|
177
177
|
sink?: TraceSinkConfig;
|
|
178
178
|
};
|
|
179
|
+
/** @deprecated Use TracingConfig instead */
|
|
179
180
|
type SmartAgentTracingConfig = TracingConfig;
|
|
180
181
|
type AgentOptions = {
|
|
181
182
|
name?: string;
|
|
182
183
|
version?: string;
|
|
183
|
-
model:
|
|
184
|
+
model: BaseChatModel;
|
|
184
185
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
185
186
|
guardrails?: ConversationGuardrail[];
|
|
186
187
|
handoffs?: HandoffDescriptor[];
|
|
@@ -192,7 +193,7 @@ type AgentOptions = {
|
|
|
192
193
|
type SmartAgentOptions = {
|
|
193
194
|
name?: string;
|
|
194
195
|
version?: string;
|
|
195
|
-
model:
|
|
196
|
+
model: BaseChatModel;
|
|
196
197
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
197
198
|
guardrails?: ConversationGuardrail[];
|
|
198
199
|
handoffs?: HandoffDescriptor[];
|
|
@@ -214,7 +215,7 @@ type SmartAgentOptions = {
|
|
|
214
215
|
type AgentRuntimeConfig = {
|
|
215
216
|
name?: string;
|
|
216
217
|
version?: string;
|
|
217
|
-
model:
|
|
218
|
+
model: BaseChatModel;
|
|
218
219
|
tools: Array<ToolInterface<any, any, any>>;
|
|
219
220
|
guardrails?: ConversationGuardrail[];
|
|
220
221
|
systemPrompt?: string;
|
|
@@ -747,6 +748,15 @@ declare function applyTokenLimits({ state, limits, }: {
|
|
|
747
748
|
summaries?: string[];
|
|
748
749
|
}>;
|
|
749
750
|
|
|
751
|
+
/**
|
|
752
|
+
* Estimates token count from text using a character-based heuristic.
|
|
753
|
+
*
|
|
754
|
+
* This is a rough approximation:
|
|
755
|
+
* - For Latin/ASCII text: ~4 characters per token (GPT-family models)
|
|
756
|
+
* - For CJK/Unicode text: ~1.5 characters per token
|
|
757
|
+
*
|
|
758
|
+
* For production accuracy, consider using a proper tokenizer like tiktoken.
|
|
759
|
+
*/
|
|
750
760
|
declare function countApproxTokens(text: string): number;
|
|
751
761
|
|
|
752
762
|
declare function createContextTools(stateRef: {
|
package/dist/index.d.ts
CHANGED
|
@@ -75,16 +75,15 @@ interface ToolInterface<TInput = any, TOutput = any, TCallOptions = any> {
|
|
|
75
75
|
approvalDefaults?: any;
|
|
76
76
|
[key: string]: any;
|
|
77
77
|
}
|
|
78
|
-
type RunnableConfig =
|
|
79
|
-
[key: string]: any;
|
|
80
|
-
};
|
|
78
|
+
type RunnableConfig = Record<string, unknown>;
|
|
81
79
|
type BaseMessage = {
|
|
82
80
|
role: string;
|
|
83
81
|
name?: string;
|
|
84
82
|
content: string | ContentPart[];
|
|
85
83
|
tool_calls?: any;
|
|
86
84
|
tool_call_id?: string;
|
|
87
|
-
|
|
85
|
+
metadata?: Record<string, any>;
|
|
86
|
+
additional_kwargs?: Record<string, any>;
|
|
88
87
|
};
|
|
89
88
|
type AIMessage = BaseMessage & {
|
|
90
89
|
role: 'assistant';
|
|
@@ -144,6 +143,7 @@ type AgentLimits = {
|
|
|
144
143
|
maxToolCalls?: number;
|
|
145
144
|
maxParallelTools?: number;
|
|
146
145
|
};
|
|
146
|
+
/** @deprecated Use AgentLimits instead */
|
|
147
147
|
type SmartAgentLimits = AgentLimits;
|
|
148
148
|
type TraceSinkFileConfig = {
|
|
149
149
|
type: "file";
|
|
@@ -176,11 +176,12 @@ type TracingConfig = {
|
|
|
176
176
|
mode?: TracingMode;
|
|
177
177
|
sink?: TraceSinkConfig;
|
|
178
178
|
};
|
|
179
|
+
/** @deprecated Use TracingConfig instead */
|
|
179
180
|
type SmartAgentTracingConfig = TracingConfig;
|
|
180
181
|
type AgentOptions = {
|
|
181
182
|
name?: string;
|
|
182
183
|
version?: string;
|
|
183
|
-
model:
|
|
184
|
+
model: BaseChatModel;
|
|
184
185
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
185
186
|
guardrails?: ConversationGuardrail[];
|
|
186
187
|
handoffs?: HandoffDescriptor[];
|
|
@@ -192,7 +193,7 @@ type AgentOptions = {
|
|
|
192
193
|
type SmartAgentOptions = {
|
|
193
194
|
name?: string;
|
|
194
195
|
version?: string;
|
|
195
|
-
model:
|
|
196
|
+
model: BaseChatModel;
|
|
196
197
|
tools?: Array<ToolInterface<any, any, any>>;
|
|
197
198
|
guardrails?: ConversationGuardrail[];
|
|
198
199
|
handoffs?: HandoffDescriptor[];
|
|
@@ -214,7 +215,7 @@ type SmartAgentOptions = {
|
|
|
214
215
|
type AgentRuntimeConfig = {
|
|
215
216
|
name?: string;
|
|
216
217
|
version?: string;
|
|
217
|
-
model:
|
|
218
|
+
model: BaseChatModel;
|
|
218
219
|
tools: Array<ToolInterface<any, any, any>>;
|
|
219
220
|
guardrails?: ConversationGuardrail[];
|
|
220
221
|
systemPrompt?: string;
|
|
@@ -747,6 +748,15 @@ declare function applyTokenLimits({ state, limits, }: {
|
|
|
747
748
|
summaries?: string[];
|
|
748
749
|
}>;
|
|
749
750
|
|
|
751
|
+
/**
|
|
752
|
+
* Estimates token count from text using a character-based heuristic.
|
|
753
|
+
*
|
|
754
|
+
* This is a rough approximation:
|
|
755
|
+
* - For Latin/ASCII text: ~4 characters per token (GPT-family models)
|
|
756
|
+
* - For CJK/Unicode text: ~1.5 characters per token
|
|
757
|
+
*
|
|
758
|
+
* For production accuracy, consider using a proper tokenizer like tiktoken.
|
|
759
|
+
*/
|
|
750
760
|
declare function countApproxTokens(text: string): number;
|
|
751
761
|
|
|
752
762
|
declare function createContextTools(stateRef: {
|
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,36 +182,6 @@ 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
|
for await (const chunk of lcModel.stream(lcMessages, options)) {
|
|
218
187
|
yield chunk;
|
|
@@ -1296,7 +1265,18 @@ function createAgentCoreNode(opts) {
|
|
|
1296
1265
|
outputSchema: opts.outputSchema,
|
|
1297
1266
|
tracing: opts.tracing
|
|
1298
1267
|
};
|
|
1299
|
-
const
|
|
1268
|
+
const rawTools = runtime.tools ?? [];
|
|
1269
|
+
const seenNames = /* @__PURE__ */ new Map();
|
|
1270
|
+
const tools = [];
|
|
1271
|
+
for (const t of rawTools) {
|
|
1272
|
+
const tName = t.name ?? t.schema?.title;
|
|
1273
|
+
if (tName && seenNames.has(tName)) {
|
|
1274
|
+
tools[seenNames.get(tName)] = t;
|
|
1275
|
+
} else {
|
|
1276
|
+
if (tName) seenNames.set(tName, tools.length);
|
|
1277
|
+
tools.push(t);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1300
1280
|
const modelWithTools = runtime.model?.bindTools ? runtime.model.bindTools(tools) : runtime.model;
|
|
1301
1281
|
const traceSession = state.ctx?.__traceSession;
|
|
1302
1282
|
const actorName = runtime.name ?? opts.name ?? "agent";
|
|
@@ -1349,26 +1329,6 @@ function createAgentCoreNode(opts) {
|
|
|
1349
1329
|
}
|
|
1350
1330
|
return filteredMsgs;
|
|
1351
1331
|
};
|
|
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
1332
|
const onEvent = state.ctx?.__onEvent;
|
|
1373
1333
|
const onStream = state.ctx?.__onStream;
|
|
1374
1334
|
const streamingEnabled = Boolean(state.ctx?.__streaming);
|
|
@@ -1387,8 +1347,124 @@ function createAgentCoreNode(opts) {
|
|
|
1387
1347
|
};
|
|
1388
1348
|
let response;
|
|
1389
1349
|
try {
|
|
1390
|
-
const
|
|
1391
|
-
|
|
1350
|
+
const ensureUniqueToolCallIds = (input) => {
|
|
1351
|
+
const msgs = Array.isArray(input) ? input.map((m) => ({ ...m })) : [];
|
|
1352
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
1353
|
+
let counter = 0;
|
|
1354
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
1355
|
+
const m = msgs[i];
|
|
1356
|
+
if (m?.role !== "assistant") continue;
|
|
1357
|
+
const hasToolCalls = Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
|
|
1358
|
+
const contentArr = Array.isArray(m.content) ? m.content : [];
|
|
1359
|
+
const hasContentToolUse = contentArr.some((c) => c?.type === "tool_use" && c?.id);
|
|
1360
|
+
const hasAdditionalToolCalls = Array.isArray(m.additional_kwargs?.tool_calls) && m.additional_kwargs.tool_calls.length > 0;
|
|
1361
|
+
if (!hasToolCalls && !hasContentToolUse && !hasAdditionalToolCalls) continue;
|
|
1362
|
+
if (hasToolCalls && hasContentToolUse) {
|
|
1363
|
+
const toolCallIds = new Set(
|
|
1364
|
+
m.tool_calls.filter((tc) => tc?.id).map((tc) => tc.id)
|
|
1365
|
+
);
|
|
1366
|
+
const filtered = contentArr.filter((c) => {
|
|
1367
|
+
if (c?.type === "tool_use" && c?.id && toolCallIds.has(c.id)) return false;
|
|
1368
|
+
return true;
|
|
1369
|
+
});
|
|
1370
|
+
if (filtered.length === 0) {
|
|
1371
|
+
m.content = "";
|
|
1372
|
+
} else if (filtered.length !== contentArr.length) {
|
|
1373
|
+
m.content = filtered.length === 1 && filtered[0]?.type === "text" ? filtered[0].text ?? "" : filtered;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
if (hasAdditionalToolCalls && Array.isArray(m.content)) {
|
|
1377
|
+
const akIds = new Set(
|
|
1378
|
+
m.additional_kwargs.tool_calls.filter((tc) => tc?.id).map((tc) => tc.id)
|
|
1379
|
+
);
|
|
1380
|
+
const arr = m.content;
|
|
1381
|
+
const filtered = arr.filter((c) => {
|
|
1382
|
+
if (c?.type === "tool_use" && c?.id && akIds.has(c.id)) return false;
|
|
1383
|
+
return true;
|
|
1384
|
+
});
|
|
1385
|
+
if (filtered.length !== arr.length) {
|
|
1386
|
+
m.content = filtered.length === 0 ? "" : filtered.length === 1 && filtered[0]?.type === "text" ? filtered[0].text ?? "" : filtered;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
if (hasToolCalls) {
|
|
1390
|
+
m.tool_calls = m.tool_calls.map((tc) => ({ ...tc }));
|
|
1391
|
+
}
|
|
1392
|
+
if (hasAdditionalToolCalls) {
|
|
1393
|
+
m.additional_kwargs = { ...m.additional_kwargs };
|
|
1394
|
+
m.additional_kwargs.tool_calls = m.additional_kwargs.tool_calls.map((tc) => ({ ...tc }));
|
|
1395
|
+
}
|
|
1396
|
+
const remainingContentArr = Array.isArray(m.content) ? m.content : [];
|
|
1397
|
+
const hasRemainingContentToolUse = remainingContentArr.some((c) => c?.type === "tool_use" && c?.id);
|
|
1398
|
+
if (hasRemainingContentToolUse) {
|
|
1399
|
+
m.content = remainingContentArr.map(
|
|
1400
|
+
(c) => c && typeof c === "object" ? { ...c } : c
|
|
1401
|
+
);
|
|
1402
|
+
}
|
|
1403
|
+
const idsInMessage = /* @__PURE__ */ new Set();
|
|
1404
|
+
if (hasToolCalls) {
|
|
1405
|
+
for (const tc of m.tool_calls) {
|
|
1406
|
+
if (tc?.id) idsInMessage.add(tc.id);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
if (hasRemainingContentToolUse) {
|
|
1410
|
+
for (const c of m.content) {
|
|
1411
|
+
if (c?.type === "tool_use" && c?.id) idsInMessage.add(c.id);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
if (hasAdditionalToolCalls) {
|
|
1415
|
+
for (const tc of m.additional_kwargs.tool_calls) {
|
|
1416
|
+
if (tc?.id) idsInMessage.add(tc.id);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
for (const id of idsInMessage) {
|
|
1420
|
+
if (!usedIds.has(id)) {
|
|
1421
|
+
usedIds.add(id);
|
|
1422
|
+
continue;
|
|
1423
|
+
}
|
|
1424
|
+
const newId = `${id}_${Date.now()}_${counter++}`;
|
|
1425
|
+
if (hasToolCalls) {
|
|
1426
|
+
for (const tc of m.tool_calls) {
|
|
1427
|
+
if (tc.id === id) tc.id = newId;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
if (hasRemainingContentToolUse && Array.isArray(m.content)) {
|
|
1431
|
+
for (const c of m.content) {
|
|
1432
|
+
if (c?.type === "tool_use" && c.id === id) c.id = newId;
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
if (hasAdditionalToolCalls) {
|
|
1436
|
+
for (const tc of m.additional_kwargs.tool_calls) {
|
|
1437
|
+
if (tc.id === id) tc.id = newId;
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
for (let j = i + 1; j < msgs.length; j++) {
|
|
1441
|
+
const next = msgs[j];
|
|
1442
|
+
if (next?.role === "assistant") break;
|
|
1443
|
+
if (next?.role === "tool" && next.tool_call_id === id) {
|
|
1444
|
+
next.tool_call_id = newId;
|
|
1445
|
+
}
|
|
1446
|
+
if (Array.isArray(next?.content)) {
|
|
1447
|
+
let contentCloned = false;
|
|
1448
|
+
for (let k = 0; k < next.content.length; k++) {
|
|
1449
|
+
const block = next.content[k];
|
|
1450
|
+
if (block?.type === "tool_result" && block.tool_use_id === id) {
|
|
1451
|
+
if (!contentCloned) {
|
|
1452
|
+
next.content = next.content.map((x) => x && typeof x === "object" ? { ...x } : x);
|
|
1453
|
+
contentCloned = true;
|
|
1454
|
+
}
|
|
1455
|
+
next.content[k].tool_use_id = newId;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
usedIds.add(newId);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
return msgs;
|
|
1464
|
+
};
|
|
1465
|
+
const normalizedMessages = ensureUniqueToolCallIds(
|
|
1466
|
+
normalizeBedrockToolPairing([...state.messages])
|
|
1467
|
+
);
|
|
1392
1468
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
1393
1469
|
let streamedText = "";
|
|
1394
1470
|
let streamedMessage;
|
|
@@ -2034,7 +2110,9 @@ function resolveToolApprovalState(state, resolution) {
|
|
|
2034
2110
|
// src/utils/utilTokens.ts
|
|
2035
2111
|
function countApproxTokens(text) {
|
|
2036
2112
|
if (!text) return 0;
|
|
2037
|
-
|
|
2113
|
+
const nonAsciiCount = (text.match(/[^\x00-\x7F]/g) || []).length;
|
|
2114
|
+
const asciiCount = text.length - nonAsciiCount;
|
|
2115
|
+
return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
|
|
2038
2116
|
}
|
|
2039
2117
|
|
|
2040
2118
|
// src/agent.ts
|
|
@@ -2137,7 +2215,8 @@ function createAgent(opts) {
|
|
|
2137
2215
|
let result = false;
|
|
2138
2216
|
try {
|
|
2139
2217
|
result = onStateChange(state);
|
|
2140
|
-
} catch {
|
|
2218
|
+
} catch (err) {
|
|
2219
|
+
console.warn("[agent-sdk] onStateChange callback error:", err);
|
|
2141
2220
|
result = false;
|
|
2142
2221
|
}
|
|
2143
2222
|
if (!result) return false;
|
|
@@ -2315,7 +2394,9 @@ function createAgent(opts) {
|
|
|
2315
2394
|
if (toolCallsAfter.length > 0) {
|
|
2316
2395
|
state = { ...state, ...await toolsNode(state) };
|
|
2317
2396
|
}
|
|
2318
|
-
} catch {
|
|
2397
|
+
} catch (err) {
|
|
2398
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2399
|
+
emit?.({ type: "metadata", error: `Structured output force-finalize failed: ${errMsg}` });
|
|
2319
2400
|
}
|
|
2320
2401
|
}
|
|
2321
2402
|
}
|
|
@@ -2333,13 +2414,15 @@ function createAgent(opts) {
|
|
|
2333
2414
|
const emit = (e) => {
|
|
2334
2415
|
try {
|
|
2335
2416
|
onEvent?.(e);
|
|
2336
|
-
} catch {
|
|
2417
|
+
} catch (err) {
|
|
2418
|
+
console.warn("[agent-sdk] onEvent callback error:", err);
|
|
2337
2419
|
}
|
|
2338
2420
|
};
|
|
2339
2421
|
const emitProgress = (progress) => {
|
|
2340
2422
|
try {
|
|
2341
2423
|
onProgress?.(progress);
|
|
2342
|
-
} catch {
|
|
2424
|
+
} catch (err) {
|
|
2425
|
+
console.warn("[agent-sdk] onProgress callback error:", err);
|
|
2343
2426
|
}
|
|
2344
2427
|
emit({ type: "progress", ...progress });
|
|
2345
2428
|
};
|
|
@@ -2849,6 +2932,12 @@ async function applyTokenLimits({
|
|
|
2849
2932
|
let total = messages.reduce((acc, m) => acc + countApproxTokens(String(m.content || "")), 0);
|
|
2850
2933
|
if (total <= budget) return state;
|
|
2851
2934
|
const newMessages = [...messages];
|
|
2935
|
+
while (total > budget && newMessages.length > 1) {
|
|
2936
|
+
const idx = newMessages.findIndex((m) => m.role !== "system");
|
|
2937
|
+
if (idx === -1) break;
|
|
2938
|
+
const removed = newMessages.splice(idx, 1)[0];
|
|
2939
|
+
total -= countApproxTokens(String(removed.content || ""));
|
|
2940
|
+
}
|
|
2852
2941
|
return { ...state, messages: newMessages };
|
|
2853
2942
|
}
|
|
2854
2943
|
function createContextTools(stateRef, opts) {
|
|
@@ -2950,19 +3039,7 @@ function needsSummarization(state, opts, summarizationEnabled) {
|
|
|
2950
3039
|
return "";
|
|
2951
3040
|
}).join("\n");
|
|
2952
3041
|
const tokenCount = countApproxTokens(allText);
|
|
2953
|
-
|
|
2954
|
-
if (process.env.DEBUG_SUMMARIZATION) {
|
|
2955
|
-
const msgCount = (state.messages || []).length;
|
|
2956
|
-
const toolMsgs = (state.messages || []).filter((m) => m.role === "tool");
|
|
2957
|
-
const toolDetails = toolMsgs.map((m, i) => {
|
|
2958
|
-
const contentStr = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
2959
|
-
return `[${i}] id:${m.tool_call_id?.slice(-8) || "none"} len:${contentStr.length} preview:"${contentStr.slice(0, 30)}..."`;
|
|
2960
|
-
});
|
|
2961
|
-
console.log(`[Summarization] Messages: ${msgCount}, Tool messages: ${toolMsgs.length}`);
|
|
2962
|
-
toolDetails.forEach((d) => console.log(` ${d}`));
|
|
2963
|
-
console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Needs summarization: ${needsSum}`);
|
|
2964
|
-
}
|
|
2965
|
-
return needsSum;
|
|
3042
|
+
return tokenCount > maxTok;
|
|
2966
3043
|
} catch (e) {
|
|
2967
3044
|
return false;
|
|
2968
3045
|
}
|