@cognipeer/agent-sdk 0.2.6 → 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 CHANGED
@@ -192,7 +192,9 @@ function fromLangchainModel(lcModel) {
192
192
  stream: async function* (messages, options) {
193
193
  if (typeof lcModel.stream !== "function") return;
194
194
  const lcMessages = messages.map(toLC);
195
- for await (const chunk of lcModel.stream(lcMessages, options)) {
195
+ const streamResult = lcModel.stream(lcMessages, options);
196
+ const stream = typeof streamResult?.then === "function" ? await streamResult : streamResult;
197
+ for await (const chunk of stream) {
196
198
  yield chunk;
197
199
  }
198
200
  },
@@ -314,17 +316,17 @@ function normalizeUsage(raw) {
314
316
  raw.totalTokens,
315
317
  (typeof prompt === "number" ? prompt : 0) + (typeof completion === "number" ? completion : 0)
316
318
  );
317
- const promptDetailsSrc = raw.prompt_tokens_details || raw.promptTokensDetails || {};
318
- const completionDetailsSrc = raw.completion_tokens_details || raw.completionTokensDetails || {};
319
+ const promptDetailsSrc = raw.prompt_tokens_details || raw.promptTokensDetails || raw.input_token_details || raw.inputTokenDetails || {};
320
+ const completionDetailsSrc = raw.completion_tokens_details || raw.completionTokensDetails || raw.output_token_details || raw.outputTokenDetails || {};
319
321
  const normalized = {
320
322
  prompt_tokens: safe(prompt),
321
323
  completion_tokens: safe(completion),
322
324
  total_tokens: safe(total || (prompt || 0) + (completion || 0)),
323
325
  prompt_tokens_details: {
324
326
  cached_tokens: safe(
325
- promptDetailsSrc.cached_tokens || promptDetailsSrc.cached || raw.cached_input_tokens || raw.cached_prompt_tokens
327
+ promptDetailsSrc.cached_tokens || promptDetailsSrc.cached || promptDetailsSrc.cache_read || raw.cached_input_tokens || raw.cached_prompt_tokens || raw.cache_read_input_tokens
326
328
  ),
327
- audio_tokens: safe(promptDetailsSrc.audio_tokens)
329
+ audio_tokens: safe(promptDetailsSrc.audio_tokens || promptDetailsSrc.audio)
328
330
  },
329
331
  completion_tokens_details: {
330
332
  reasoning_tokens: safe(completionDetailsSrc.reasoning_tokens),
@@ -645,7 +647,7 @@ async function postStreamingSessionStart(baseUrl, headers, payload) {
645
647
  if (!fetchFn) {
646
648
  throw new Error("HTTP sink requires fetch to be available in this runtime.");
647
649
  }
648
- const url = `${baseUrl.replace(/\/$/, "")}/${payload.sessionId}/start`;
650
+ const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/start`;
649
651
  const finalHeaders = { ...headers || {} };
650
652
  if (!Object.keys(finalHeaders).some((key) => key.toLowerCase() === "content-type")) {
651
653
  finalHeaders["content-type"] = "application/json";
@@ -679,7 +681,7 @@ async function postStreamingEvent(baseUrl, headers, sessionId, event) {
679
681
  if (!fetchFn) {
680
682
  throw new Error("HTTP sink requires fetch to be available in this runtime.");
681
683
  }
682
- const url = `${baseUrl.replace(/\/$/, "")}/${sessionId}/events`;
684
+ const url = `${baseUrl.replace(/\/$/, "")}/stream/${sessionId}/events`;
683
685
  const finalHeaders = { ...headers || {} };
684
686
  if (!Object.keys(finalHeaders).some((key) => key.toLowerCase() === "content-type")) {
685
687
  finalHeaders["content-type"] = "application/json";
@@ -713,7 +715,7 @@ async function postStreamingSessionEnd(baseUrl, headers, payload) {
713
715
  if (!fetchFn) {
714
716
  throw new Error("HTTP sink requires fetch to be available in this runtime.");
715
717
  }
716
- const url = `${baseUrl.replace(/\/$/, "")}/${payload.sessionId}/end`;
718
+ const url = `${baseUrl.replace(/\/$/, "")}/stream/${payload.sessionId}/end`;
717
719
  const finalHeaders = { ...headers || {} };
718
720
  if (!Object.keys(finalHeaders).some((key) => key.toLowerCase() === "content-type")) {
719
721
  finalHeaders["content-type"] = "application/json";
@@ -1010,8 +1012,12 @@ function recordTraceEvent(session, event) {
1010
1012
  session.summary.eventCounts[event.type] = (session.summary.eventCounts[event.type] || 0) + 1;
1011
1013
  let sections;
1012
1014
  if (session.resolvedConfig.logData) {
1013
- const converted = convertMessageListToSections(event.messageList);
1014
- sections = ensureUniqueSections(id, converted);
1015
+ if (event.sections && event.sections.length > 0) {
1016
+ sections = ensureUniqueSections(id, event.sections);
1017
+ } else {
1018
+ const converted = convertMessageListToSections(event.messageList);
1019
+ sections = ensureUniqueSections(id, converted);
1020
+ }
1015
1021
  }
1016
1022
  const resolvedModel = event.model ?? inferModelFromMessages(event.messageList);
1017
1023
  const resolvedProvider = event.provider ?? inferProviderFromMessages(event.messageList);
@@ -1274,18 +1280,7 @@ function createAgentCoreNode(opts) {
1274
1280
  outputSchema: opts.outputSchema,
1275
1281
  tracing: opts.tracing
1276
1282
  };
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
- }
1283
+ const tools = runtime.tools ?? [];
1289
1284
  const modelWithTools = runtime.model?.bindTools ? runtime.model.bindTools(tools) : runtime.model;
1290
1285
  const traceSession = state.ctx?.__traceSession;
1291
1286
  const actorName = runtime.name ?? opts.name ?? "agent";
@@ -1338,6 +1333,26 @@ function createAgentCoreNode(opts) {
1338
1333
  }
1339
1334
  return filteredMsgs;
1340
1335
  };
1336
+ const debugToolPairing = (messagesToSend) => {
1337
+ try {
1338
+ const msgs = Array.isArray(messagesToSend) ? messagesToSend : [];
1339
+ const toolUseIds = [];
1340
+ const missingResults = [];
1341
+ for (let i = 0; i < msgs.length; i++) {
1342
+ const m = msgs[i];
1343
+ if (m?.role === "assistant") {
1344
+ for (const tu of extractToolUses(m)) {
1345
+ toolUseIds.push(tu.id);
1346
+ const next = msgs[i + 1];
1347
+ if (!(next && next.role === "tool" && (next.tool_call_id === tu.id || next.tool_call_id === m?.tool_call_id))) {
1348
+ missingResults.push({ id: tu.id, atIndex: i, tool: tu.name });
1349
+ }
1350
+ }
1351
+ }
1352
+ }
1353
+ } catch (e) {
1354
+ }
1355
+ };
1341
1356
  const onEvent = state.ctx?.__onEvent;
1342
1357
  const onStream = state.ctx?.__onStream;
1343
1358
  const streamingEnabled = Boolean(state.ctx?.__streaming);
@@ -1356,124 +1371,8 @@ function createAgentCoreNode(opts) {
1356
1371
  };
1357
1372
  let response;
1358
1373
  try {
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
- );
1374
+ const normalizedMessages = normalizeBedrockToolPairing([...state.messages]);
1375
+ debugToolPairing(normalizedMessages);
1477
1376
  if (streamingEnabled && typeof modelWithTools.stream === "function") {
1478
1377
  let streamedText = "";
1479
1378
  let streamedMessage;
@@ -1613,41 +1512,6 @@ function createToolsNode(initialTools, opts) {
1613
1512
  const remaining = Math.max(0, limits.maxToolCalls - toolCount);
1614
1513
  const planned = toolCalls.slice(0, remaining);
1615
1514
  const skipped = toolCalls.slice(remaining);
1616
- for (const tc of skipped) {
1617
- onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
1618
- const sanitizedArgs = sanitizeTracePayload(tc.args);
1619
- const messageList = [
1620
- {
1621
- role: "assistant",
1622
- name: tc.name,
1623
- content: `Skipped tool due to tool-call limit: ${tc.name}`,
1624
- tool_calls: [
1625
- {
1626
- id: tc.id,
1627
- type: "function",
1628
- function: {
1629
- name: tc.name,
1630
- arguments: sanitizedArgs
1631
- }
1632
- }
1633
- ]
1634
- }
1635
- ];
1636
- recordTraceEvent(traceSession, {
1637
- type: "tool_call",
1638
- label: `Tool Skipped - ${tc.name}`,
1639
- actor: { scope: "tool", name: tc.name, role: "tool" },
1640
- status: "skipped",
1641
- toolExecutionId: tc.id,
1642
- messageList
1643
- });
1644
- appended.push({
1645
- role: "tool",
1646
- content: `Skipped tool due to tool-call limit: ${tc.name}`,
1647
- tool_call_id: tc.id || `${tc.name}_${appended.length}`,
1648
- name: tc.name
1649
- });
1650
- }
1651
1515
  const isCancelled = () => {
1652
1516
  if (abortSignal?.aborted) return { cancelled: true, reason: "aborted" };
1653
1517
  if (cancellationToken && cancellationToken.isCancellationRequested) return { cancelled: true, reason: "cancelled" };
@@ -1888,6 +1752,42 @@ function createToolsNode(initialTools, opts) {
1888
1752
  break;
1889
1753
  }
1890
1754
  }
1755
+ for (const tc of skipped) {
1756
+ onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
1757
+ const sanitizedArgs = sanitizeTracePayload(tc.args);
1758
+ const messageList = [
1759
+ {
1760
+ role: "assistant",
1761
+ name: tc.name,
1762
+ content: `Skipped tool due to tool-call limit: ${tc.name}`,
1763
+ tool_calls: [
1764
+ {
1765
+ id: tc.id,
1766
+ type: "function",
1767
+ function: {
1768
+ name: tc.name,
1769
+ arguments: sanitizedArgs
1770
+ }
1771
+ }
1772
+ ]
1773
+ }
1774
+ ];
1775
+ recordTraceEvent(traceSession, {
1776
+ type: "tool_call",
1777
+ label: `Tool Skipped - ${tc.name}`,
1778
+ actor: { scope: "tool", name: tc.name, role: "tool" },
1779
+ status: "skipped",
1780
+ toolExecutionId: tc.id,
1781
+ messageList
1782
+ });
1783
+ appended.push({
1784
+ role: "tool",
1785
+ content: `Skipped tool due to tool-call limit: ${tc.name}`,
1786
+ tool_call_id: tc.id || `${tc.name}_${appended.length}`,
1787
+ name: tc.name
1788
+ });
1789
+ toolCount += 1;
1790
+ }
1891
1791
  if (!awaitingApproval && state.ctx?.__awaitingApproval) {
1892
1792
  const ctx = { ...state.ctx };
1893
1793
  delete ctx.__awaitingApproval;
@@ -2123,6 +2023,59 @@ function countApproxTokens(text) {
2123
2023
  const asciiCount = text.length - nonAsciiCount;
2124
2024
  return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
2125
2025
  }
2026
+ function extractMessageText(m) {
2027
+ if (!m) return "";
2028
+ const parts = [];
2029
+ parts.push(m.role || "");
2030
+ if (m.name) parts.push(m.name);
2031
+ if (typeof m.content === "string") {
2032
+ parts.push(m.content);
2033
+ } else if (Array.isArray(m.content)) {
2034
+ for (const c of m.content) {
2035
+ if (typeof c === "string") parts.push(c);
2036
+ else if (c?.text) parts.push(c.text);
2037
+ else if (c?.content) parts.push(c.content);
2038
+ else if (c?.type === "tool_use" && c?.input) {
2039
+ parts.push(c.name || "");
2040
+ parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
2041
+ } else if (c != null && typeof c === "object") {
2042
+ parts.push(JSON.stringify(c));
2043
+ }
2044
+ }
2045
+ } else if (m.content != null && typeof m.content === "object") {
2046
+ parts.push(JSON.stringify(m.content));
2047
+ }
2048
+ if (Array.isArray(m.tool_calls)) {
2049
+ for (const tc of m.tool_calls) {
2050
+ if (tc?.function?.name) parts.push(tc.function.name);
2051
+ if (tc?.function?.arguments) {
2052
+ parts.push(
2053
+ typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
2054
+ );
2055
+ }
2056
+ if (tc?.name && !tc?.function?.name) parts.push(tc.name);
2057
+ if (tc?.args && !tc?.function?.arguments) {
2058
+ parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
2059
+ }
2060
+ }
2061
+ }
2062
+ if (Array.isArray(m.additional_kwargs?.tool_calls)) {
2063
+ for (const tc of m.additional_kwargs.tool_calls) {
2064
+ if (tc?.function?.name) parts.push(tc.function.name);
2065
+ if (tc?.function?.arguments) {
2066
+ parts.push(
2067
+ typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
2068
+ );
2069
+ }
2070
+ }
2071
+ }
2072
+ return parts.join("\n");
2073
+ }
2074
+ function countMessagesTokens(messages) {
2075
+ if (!Array.isArray(messages) || messages.length === 0) return 0;
2076
+ const allText = messages.map(extractMessageText).join("\n");
2077
+ return countApproxTokens(allText) + messages.length * 4;
2078
+ }
2126
2079
 
2127
2080
  // src/agent.ts
2128
2081
  function createAgent(opts) {
@@ -2292,8 +2245,7 @@ function createAgent(opts) {
2292
2245
  maxTok = 5e4;
2293
2246
  }
2294
2247
  if (maxTok) {
2295
- const allText = (state.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");
2296
- const tokenCount = countApproxTokens(allText);
2248
+ const tokenCount = countMessagesTokens(state.messages || []);
2297
2249
  if (tokenCount > maxTok) {
2298
2250
  const ctx = { ...state.ctx || {}, __needsSummarization: true };
2299
2251
  state = { ...state, ctx };
@@ -3048,7 +3000,19 @@ function needsSummarization(state, opts, summarizationEnabled) {
3048
3000
  return "";
3049
3001
  }).join("\n");
3050
3002
  const tokenCount = countApproxTokens(allText);
3051
- return tokenCount > maxTok;
3003
+ const needsSum = tokenCount > maxTok;
3004
+ if (process.env.DEBUG_SUMMARIZATION) {
3005
+ const msgCount = (state.messages || []).length;
3006
+ const toolMsgs = (state.messages || []).filter((m) => m.role === "tool");
3007
+ const toolDetails = toolMsgs.map((m, i) => {
3008
+ const contentStr = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
3009
+ return `[${i}] id:${m.tool_call_id?.slice(-8) || "none"} len:${contentStr.length} preview:"${contentStr.slice(0, 30)}..."`;
3010
+ });
3011
+ console.log(`[Summarization] Messages: ${msgCount}, Tool messages: ${toolMsgs.length}`);
3012
+ toolDetails.forEach((d) => console.log(` ${d}`));
3013
+ console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Needs summarization: ${needsSum}`);
3014
+ }
3015
+ return needsSum;
3052
3016
  } catch (e) {
3053
3017
  return false;
3054
3018
  }
@@ -3454,6 +3418,7 @@ exports.captureSnapshot = captureSnapshot;
3454
3418
  exports.codePresenceRule = codePresenceRule;
3455
3419
  exports.cognipeerSink = cognipeerSink;
3456
3420
  exports.countApproxTokens = countApproxTokens;
3421
+ exports.countMessagesTokens = countMessagesTokens;
3457
3422
  exports.createAgent = createAgent;
3458
3423
  exports.createAgentNode = createAgentNode;
3459
3424
  exports.createCodeGuardrail = createCodeGuardrail;