@cognipeer/agent-sdk 0.2.6 → 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 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),
@@ -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);
@@ -1477,7 +1483,9 @@ function createAgentCoreNode(opts) {
1477
1483
  if (streamingEnabled && typeof modelWithTools.stream === "function") {
1478
1484
  let streamedText = "";
1479
1485
  let streamedMessage;
1480
- for await (const chunk of modelWithTools.stream(normalizedMessages, { signal: abortSignal, cancellationToken })) {
1486
+ const streamResult = modelWithTools.stream(normalizedMessages, { signal: abortSignal, cancellationToken });
1487
+ const stream = typeof streamResult?.then === "function" ? await streamResult : streamResult;
1488
+ for await (const chunk of stream) {
1481
1489
  if (cancellationToken && cancellationToken.isCancellationRequested || abortSignal?.aborted) {
1482
1490
  break;
1483
1491
  }
@@ -1522,7 +1530,7 @@ function createAgentCoreNode(opts) {
1522
1530
  ...state.messages,
1523
1531
  response
1524
1532
  ];
1525
- const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
1533
+ const rawUsage = response?.usage_metadata || response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
1526
1534
  const normalized = normalizeUsage(rawUsage);
1527
1535
  const modelName = getModelName(runtime.model || opts.model) || "unknown_model";
1528
1536
  const durationMs = Date.now() - start;
@@ -1613,41 +1621,6 @@ function createToolsNode(initialTools, opts) {
1613
1621
  const remaining = Math.max(0, limits.maxToolCalls - toolCount);
1614
1622
  const planned = toolCalls.slice(0, remaining);
1615
1623
  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
1624
  const isCancelled = () => {
1652
1625
  if (abortSignal?.aborted) return { cancelled: true, reason: "aborted" };
1653
1626
  if (cancellationToken && cancellationToken.isCancellationRequested) return { cancelled: true, reason: "cancelled" };
@@ -1888,6 +1861,42 @@ function createToolsNode(initialTools, opts) {
1888
1861
  break;
1889
1862
  }
1890
1863
  }
1864
+ for (const tc of skipped) {
1865
+ onEvent?.({ type: "tool_call", phase: "skipped", name: tc.name, id: tc.id, args: tc.args });
1866
+ const sanitizedArgs = sanitizeTracePayload(tc.args);
1867
+ const messageList = [
1868
+ {
1869
+ role: "assistant",
1870
+ name: tc.name,
1871
+ content: `Skipped tool due to tool-call limit: ${tc.name}`,
1872
+ tool_calls: [
1873
+ {
1874
+ id: tc.id,
1875
+ type: "function",
1876
+ function: {
1877
+ name: tc.name,
1878
+ arguments: sanitizedArgs
1879
+ }
1880
+ }
1881
+ ]
1882
+ }
1883
+ ];
1884
+ recordTraceEvent(traceSession, {
1885
+ type: "tool_call",
1886
+ label: `Tool Skipped - ${tc.name}`,
1887
+ actor: { scope: "tool", name: tc.name, role: "tool" },
1888
+ status: "skipped",
1889
+ toolExecutionId: tc.id,
1890
+ messageList
1891
+ });
1892
+ appended.push({
1893
+ role: "tool",
1894
+ content: `Skipped tool due to tool-call limit: ${tc.name}`,
1895
+ tool_call_id: tc.id || `${tc.name}_${appended.length}`,
1896
+ name: tc.name
1897
+ });
1898
+ toolCount += 1;
1899
+ }
1891
1900
  if (!awaitingApproval && state.ctx?.__awaitingApproval) {
1892
1901
  const ctx = { ...state.ctx };
1893
1902
  delete ctx.__awaitingApproval;
@@ -2123,6 +2132,59 @@ function countApproxTokens(text) {
2123
2132
  const asciiCount = text.length - nonAsciiCount;
2124
2133
  return Math.ceil(asciiCount / 4 + nonAsciiCount / 1.5);
2125
2134
  }
2135
+ function extractMessageText(m) {
2136
+ if (!m) return "";
2137
+ const parts = [];
2138
+ parts.push(m.role || "");
2139
+ if (m.name) parts.push(m.name);
2140
+ if (typeof m.content === "string") {
2141
+ parts.push(m.content);
2142
+ } else if (Array.isArray(m.content)) {
2143
+ for (const c of m.content) {
2144
+ if (typeof c === "string") parts.push(c);
2145
+ else if (c?.text) parts.push(c.text);
2146
+ else if (c?.content) parts.push(c.content);
2147
+ else if (c?.type === "tool_use" && c?.input) {
2148
+ parts.push(c.name || "");
2149
+ parts.push(typeof c.input === "string" ? c.input : JSON.stringify(c.input));
2150
+ } else if (c != null && typeof c === "object") {
2151
+ parts.push(JSON.stringify(c));
2152
+ }
2153
+ }
2154
+ } else if (m.content != null && typeof m.content === "object") {
2155
+ parts.push(JSON.stringify(m.content));
2156
+ }
2157
+ if (Array.isArray(m.tool_calls)) {
2158
+ for (const tc of m.tool_calls) {
2159
+ if (tc?.function?.name) parts.push(tc.function.name);
2160
+ if (tc?.function?.arguments) {
2161
+ parts.push(
2162
+ typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
2163
+ );
2164
+ }
2165
+ if (tc?.name && !tc?.function?.name) parts.push(tc.name);
2166
+ if (tc?.args && !tc?.function?.arguments) {
2167
+ parts.push(typeof tc.args === "string" ? tc.args : JSON.stringify(tc.args));
2168
+ }
2169
+ }
2170
+ }
2171
+ if (Array.isArray(m.additional_kwargs?.tool_calls)) {
2172
+ for (const tc of m.additional_kwargs.tool_calls) {
2173
+ if (tc?.function?.name) parts.push(tc.function.name);
2174
+ if (tc?.function?.arguments) {
2175
+ parts.push(
2176
+ typeof tc.function.arguments === "string" ? tc.function.arguments : JSON.stringify(tc.function.arguments)
2177
+ );
2178
+ }
2179
+ }
2180
+ }
2181
+ return parts.join("\n");
2182
+ }
2183
+ function countMessagesTokens(messages) {
2184
+ if (!Array.isArray(messages) || messages.length === 0) return 0;
2185
+ const allText = messages.map(extractMessageText).join("\n");
2186
+ return countApproxTokens(allText) + messages.length * 4;
2187
+ }
2126
2188
 
2127
2189
  // src/agent.ts
2128
2190
  function createAgent(opts) {
@@ -2292,8 +2354,7 @@ function createAgent(opts) {
2292
2354
  maxTok = 5e4;
2293
2355
  }
2294
2356
  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);
2357
+ const tokenCount = countMessagesTokens(state.messages || []);
2297
2358
  if (tokenCount > maxTok) {
2298
2359
  const ctx = { ...state.ctx || {}, __needsSummarization: true };
2299
2360
  state = { ...state, ctx };
@@ -2674,6 +2735,83 @@ function createAgentNode(opts) {
2674
2735
  };
2675
2736
  }
2676
2737
 
2738
+ // src/utils/traceSections.ts
2739
+ function formatMessageContent(content) {
2740
+ if (content == null) return "";
2741
+ if (typeof content === "string") return content;
2742
+ if (Array.isArray(content)) {
2743
+ return content.map((item) => {
2744
+ if (typeof item === "string") return item;
2745
+ if (item && typeof item === "object") {
2746
+ if (typeof item.text === "string") return item.text;
2747
+ if (typeof item.content === "string") return item.content;
2748
+ try {
2749
+ return JSON.stringify(item);
2750
+ } catch {
2751
+ return String(item);
2752
+ }
2753
+ }
2754
+ try {
2755
+ return JSON.stringify(item);
2756
+ } catch {
2757
+ return String(item);
2758
+ }
2759
+ }).filter(Boolean).join("\n");
2760
+ }
2761
+ if (typeof content === "object") {
2762
+ if (typeof content.text === "string") return content.text;
2763
+ if (typeof content.content === "string") return content.content;
2764
+ try {
2765
+ return JSON.stringify(content, null, 2);
2766
+ } catch {
2767
+ return String(content);
2768
+ }
2769
+ }
2770
+ return String(content);
2771
+ }
2772
+ function buildSummarizationSections(opts) {
2773
+ const sections = [];
2774
+ sections.push({
2775
+ kind: "summary",
2776
+ label: "Context Summary",
2777
+ content: opts.summaryText
2778
+ });
2779
+ const tokensSaved = opts.tokenCountBefore - opts.tokenCountAfter;
2780
+ const reductionPct = opts.tokenCountBefore > 0 ? Math.round(tokensSaved / opts.tokenCountBefore * 100) : 0;
2781
+ const metaData = {
2782
+ messagesCompressed: opts.messagesCompressed,
2783
+ tokenCountBefore: opts.tokenCountBefore,
2784
+ tokenCountAfter: opts.tokenCountAfter,
2785
+ tokensSaved,
2786
+ reductionPercent: reductionPct
2787
+ };
2788
+ if (opts.inputTokens !== void 0) metaData.inputTokens = opts.inputTokens;
2789
+ if (opts.outputTokens !== void 0) metaData.outputTokens = opts.outputTokens;
2790
+ if (opts.cachedInputTokens !== void 0) metaData.cachedInputTokens = opts.cachedInputTokens;
2791
+ if (opts.durationMs !== void 0) metaData.durationMs = opts.durationMs;
2792
+ if (opts.previousSummary) metaData.previousSummaryLength = opts.previousSummary.length;
2793
+ sections.push({
2794
+ kind: "metadata",
2795
+ label: "Summarization Stats",
2796
+ data: metaData
2797
+ });
2798
+ if (Array.isArray(opts.promptMessages) && opts.promptMessages.length > 0) {
2799
+ for (const msg of opts.promptMessages) {
2800
+ const role = typeof msg?.role === "string" ? msg.role : "system";
2801
+ const content = formatMessageContent(msg?.content ?? "");
2802
+ if (content) {
2803
+ sections.push({
2804
+ kind: "message",
2805
+ label: `Summarization Prompt (${role})`,
2806
+ role,
2807
+ content
2808
+ });
2809
+ }
2810
+ }
2811
+ }
2812
+ return sections;
2813
+ }
2814
+
2677
2815
  // src/nodes/contextSummarize.ts
2678
2816
  var systemMessage = (content) => ({ role: "system", content });
2679
2817
  var humanMessage = (content) => ({ role: "user", content });
@@ -2732,8 +2870,7 @@ function createContextSummarizeNode(opts) {
2732
2870
  if (compressableMessages.length === 0) {
2733
2871
  return {};
2734
2872
  }
2735
- 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");
2736
- const tokenCountBefore = countApproxTokens(allTextBefore);
2873
+ const tokenCountBefore = countMessagesTokens(messages);
2737
2874
  const summaryPromptMaxTokens = config.summaryPromptMaxTokens;
2738
2875
  const availableTokensForConversation = summaryPromptMaxTokens - 500;
2739
2876
  const messageTexts = [];
@@ -2796,7 +2933,7 @@ Summary:`;
2796
2933
  durationMs = Date.now() - startTime;
2797
2934
  summaryText = typeof response.content === "string" ? response.content : Array.isArray(response.content) ? response.content.map((c) => c.text || "").join("") : JSON.stringify(response.content);
2798
2935
  outputTokensEstimate = countApproxTokens(summaryText);
2799
- const rawUsage = response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
2936
+ const rawUsage = response?.usage_metadata || response?.usage || response?.response_metadata?.token_usage || response?.response_metadata?.tokenUsage || response?.response_metadata?.usage;
2800
2937
  const normalized = normalizeUsage(rawUsage);
2801
2938
  if (normalized) {
2802
2939
  inputTokensActual = normalized.prompt_tokens;
@@ -2828,7 +2965,16 @@ Summary:`;
2828
2965
  inputTokens: inputTokensEstimate,
2829
2966
  outputTokens: 0,
2830
2967
  error: { message: err?.message || String(err), stack: err?.stack },
2831
- messageList: sanitizeTracePayload(summaryPrompt)
2968
+ sections: buildSummarizationSections({
2969
+ summaryText: "",
2970
+ messagesCompressed: 0,
2971
+ tokenCountBefore,
2972
+ tokenCountAfter: tokenCountBefore,
2973
+ inputTokens: inputTokensEstimate,
2974
+ outputTokens: 0,
2975
+ durationMs,
2976
+ promptMessages: summaryPrompt
2977
+ })
2832
2978
  });
2833
2979
  return {};
2834
2980
  }
@@ -2882,8 +3028,7 @@ Summary:`;
2882
3028
  };
2883
3029
  const summaries = Array.isArray(state.summaries) ? [...state.summaries, summaryText] : [summaryText];
2884
3030
  const finalMessages = [...validatedMessages, assistantSummaryCall, toolSummaryResponse];
2885
- 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");
2886
- const tokenCountAfter = countApproxTokens(allTextAfter);
3031
+ const tokenCountAfter = countMessagesTokens(finalMessages);
2887
3032
  const summarizationEvent = {
2888
3033
  type: "summarization",
2889
3034
  summary: summaryText,
@@ -2910,10 +3055,21 @@ Summary:`;
2910
3055
  outputTokens: outputTokensActual ?? outputTokensEstimate,
2911
3056
  cachedInputTokens,
2912
3057
  totalTokens: totalTokensActual,
2913
- messageList: sanitizeTracePayload([
2914
- ...summaryPrompt,
2915
- { role: "assistant", content: summaryText, name: "summarization_result" }
2916
- ]),
3058
+ sections: buildSummarizationSections({
3059
+ summaryText,
3060
+ previousSummary: previousSummary || void 0,
3061
+ messagesCompressed: compressableMessages.length,
3062
+ tokenCountBefore,
3063
+ tokenCountAfter,
3064
+ inputTokens: inputTokensActual ?? inputTokensEstimate,
3065
+ outputTokens: outputTokensActual ?? outputTokensEstimate,
3066
+ cachedInputTokens,
3067
+ durationMs,
3068
+ promptMessages: sanitizeTracePayload([
3069
+ ...summaryPrompt,
3070
+ { role: "assistant", content: summaryText, name: "summarization_result" }
3071
+ ])
3072
+ }),
2917
3073
  debug: {
2918
3074
  messagesCompressed: compressableMessages.length,
2919
3075
  tokenCountBefore,
@@ -3037,17 +3193,7 @@ function needsSummarization(state, opts, summarizationEnabled) {
3037
3193
  maxTok = 5e4;
3038
3194
  }
3039
3195
  try {
3040
- const allText = (state.messages || []).map((m) => {
3041
- if (typeof m.content === "string") return m.content;
3042
- if (Array.isArray(m.content)) {
3043
- return m.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? JSON.stringify(c)).join("");
3044
- }
3045
- if (m.content && typeof m.content === "object") {
3046
- return JSON.stringify(m.content);
3047
- }
3048
- return "";
3049
- }).join("\n");
3050
- const tokenCount = countApproxTokens(allText);
3196
+ const tokenCount = countMessagesTokens(state.messages || []);
3051
3197
  return tokenCount > maxTok;
3052
3198
  } catch (e) {
3053
3199
  return false;
@@ -3454,6 +3600,7 @@ exports.captureSnapshot = captureSnapshot;
3454
3600
  exports.codePresenceRule = codePresenceRule;
3455
3601
  exports.cognipeerSink = cognipeerSink;
3456
3602
  exports.countApproxTokens = countApproxTokens;
3603
+ exports.countMessagesTokens = countMessagesTokens;
3457
3604
  exports.createAgent = createAgent;
3458
3605
  exports.createAgentNode = createAgentNode;
3459
3606
  exports.createCodeGuardrail = createCodeGuardrail;