@cognipeer/agent-sdk 0.4.7 → 0.4.9

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
@@ -1793,14 +1793,6 @@ var DEFAULT_PROFILE_CONFIGS = {
1793
1793
  schemaValidation: "strict",
1794
1794
  retryOnSchemaError: true,
1795
1795
  fallbackPolicy: "keep_structured"
1796
- },
1797
- watchdog: {
1798
- enabled: true,
1799
- tokenDriftThreshold: 1200,
1800
- overToolingSpikeThreshold: 0.7,
1801
- contextRotThreshold: 0.65,
1802
- autoCompaction: true,
1803
- autoReplanOnFailure: true
1804
1796
  }
1805
1797
  },
1806
1798
  balanced: {
@@ -1858,14 +1850,6 @@ var DEFAULT_PROFILE_CONFIGS = {
1858
1850
  schemaValidation: "strict",
1859
1851
  retryOnSchemaError: true,
1860
1852
  fallbackPolicy: "keep_structured"
1861
- },
1862
- watchdog: {
1863
- enabled: true,
1864
- tokenDriftThreshold: 1800,
1865
- overToolingSpikeThreshold: 0.6,
1866
- contextRotThreshold: 0.55,
1867
- autoCompaction: true,
1868
- autoReplanOnFailure: true
1869
1853
  }
1870
1854
  },
1871
1855
  deep: {
@@ -1923,14 +1907,6 @@ var DEFAULT_PROFILE_CONFIGS = {
1923
1907
  schemaValidation: "strict",
1924
1908
  retryOnSchemaError: true,
1925
1909
  fallbackPolicy: "keep_structured"
1926
- },
1927
- watchdog: {
1928
- enabled: true,
1929
- tokenDriftThreshold: 2200,
1930
- overToolingSpikeThreshold: 0.55,
1931
- contextRotThreshold: 0.5,
1932
- autoCompaction: true,
1933
- autoReplanOnFailure: true
1934
1910
  }
1935
1911
  },
1936
1912
  research: {
@@ -1988,14 +1964,6 @@ var DEFAULT_PROFILE_CONFIGS = {
1988
1964
  schemaValidation: "strict",
1989
1965
  retryOnSchemaError: true,
1990
1966
  fallbackPolicy: "keep_structured"
1991
- },
1992
- watchdog: {
1993
- enabled: true,
1994
- tokenDriftThreshold: 2600,
1995
- overToolingSpikeThreshold: 0.5,
1996
- contextRotThreshold: 0.45,
1997
- autoCompaction: true,
1998
- autoReplanOnFailure: true
1999
1967
  }
2000
1968
  }
2001
1969
  };
@@ -2072,11 +2040,6 @@ function normalizeSmartAgentOptions(opts) {
2072
2040
  ...opts.toolResponses?.toolResponseRetentionByTool || {}
2073
2041
  },
2074
2042
  criticalTools: opts.toolResponses?.criticalTools ?? customProfile.toolResponses?.criticalTools ?? preset.toolResponses.criticalTools
2075
- },
2076
- watchdog: {
2077
- ...preset.watchdog,
2078
- ...customProfile.watchdog || {},
2079
- ...opts.watchdog || {}
2080
2043
  }
2081
2044
  };
2082
2045
  }
@@ -2307,7 +2270,7 @@ function createToolsNode(initialTools, opts) {
2307
2270
  if (toolCallId) {
2308
2271
  ctx.__toolSchemaError = { toolName, toolCallId, message };
2309
2272
  }
2310
- if (resolved.watchdog.autoReplanOnFailure) {
2273
+ if (resolved.planning.replanPolicy === "on_failure") {
2311
2274
  ctx.__planNeedsReplan = true;
2312
2275
  }
2313
2276
  state.ctx = ctx;
@@ -3194,7 +3157,23 @@ function createAgent(opts) {
3194
3157
  state = { ...state, ...await finalizeNode(state) };
3195
3158
  continue;
3196
3159
  }
3197
- if (toolCalls.length === 0) break;
3160
+ if (toolCalls.length === 0) {
3161
+ if (opts.outputSchema && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize) {
3162
+ const forceMsg = {
3163
+ role: "system",
3164
+ content: [
3165
+ "A structured output schema is active.",
3166
+ "You MUST now call tool `response` with the final JSON object that matches the schema.",
3167
+ "Do not write the JSON in the assistant message.",
3168
+ "Call `response` exactly once, then stop."
3169
+ ].join("\n")
3170
+ };
3171
+ const ctx = { ...state.ctx || {}, __structuredOutputForceFinalize: true };
3172
+ state = { ...state, messages: [...state.messages, forceMsg], ctx };
3173
+ continue;
3174
+ }
3175
+ break;
3176
+ }
3198
3177
  onProgress?.({ stage: "tools", message: "Running tools" });
3199
3178
  if (cancelIfRequested("before_tools")) break;
3200
3179
  state = { ...state, ...await toolsNode(state) };
@@ -3207,31 +3186,31 @@ function createAgent(opts) {
3207
3186
  const last = state.messages[state.messages.length - 1];
3208
3187
  const lastHasToolCalls = Array.isArray(last?.tool_calls) && last.tool_calls.length > 0;
3209
3188
  if (!lastHasToolCalls) {
3210
- const forceMsg = {
3211
- role: "system",
3212
- content: [
3213
- "A structured output schema is active.",
3214
- "You MUST now call tool `response` with the final JSON object that matches the schema.",
3215
- "Do not write the JSON in the assistant message.",
3216
- "Call `response` exactly once, then stop."
3217
- ].join("\n")
3218
- };
3219
3189
  const alreadyForced = Boolean(state.ctx?.__structuredOutputForceFinalize);
3220
- if (!alreadyForced) {
3221
- const ctx = { ...state.ctx || {}, __structuredOutputForceFinalize: true };
3222
- state = { ...state, messages: [...state.messages, forceMsg], ctx };
3223
- try {
3224
- state = { ...state, ...await agentCore(state) };
3225
- const lastAfter = state.messages[state.messages.length - 1];
3226
- const toolCallsAfter = Array.isArray(lastAfter?.tool_calls) ? lastAfter.tool_calls : [];
3227
- if (toolCallsAfter.length > 0) {
3228
- state = { ...state, ...await toolsNode(state) };
3229
- }
3230
- } catch (err) {
3231
- const errMsg = err instanceof Error ? err.message : String(err);
3232
- emit?.({ type: "metadata", error: `Structured output force-finalize failed: ${errMsg}` });
3233
- throw err;
3190
+ if (alreadyForced) {
3191
+ const finalNudge = {
3192
+ role: "system",
3193
+ content: [
3194
+ "A structured output schema is active.",
3195
+ "You MUST now call tool `response` with the final JSON object that matches the schema.",
3196
+ "Do not write the JSON in the assistant message.",
3197
+ "Call `response` exactly once, then stop.",
3198
+ "Do NOT call any other tools. Produce the response NOW based on whatever information you have gathered so far."
3199
+ ].join("\n")
3200
+ };
3201
+ state = { ...state, messages: [...state.messages, finalNudge] };
3202
+ }
3203
+ try {
3204
+ state = { ...state, ...await agentCore(state) };
3205
+ const lastAfter = state.messages[state.messages.length - 1];
3206
+ const toolCallsAfter = Array.isArray(lastAfter?.tool_calls) ? lastAfter.tool_calls : [];
3207
+ if (toolCallsAfter.length > 0) {
3208
+ state = { ...state, ...await toolsNode(state) };
3234
3209
  }
3210
+ } catch (err) {
3211
+ const errMsg = err instanceof Error ? err.message : String(err);
3212
+ emit?.({ type: "metadata", error: `Structured output force-finalize failed: ${errMsg}` });
3213
+ throw err;
3235
3214
  }
3236
3215
  }
3237
3216
  }
@@ -3606,15 +3585,6 @@ function buildModelMessages(state, config) {
3606
3585
  ];
3607
3586
  return clampToBudget(assembled, config.limits.maxContextTokens);
3608
3587
  }
3609
- function estimateContextRotScore(state) {
3610
- const summaryCount = state.summaryRecords?.length || 0;
3611
- const archivedCount = state.toolHistoryArchived?.length || 0;
3612
- const messageCount = state.messages?.length || 0;
3613
- const summarizedMessages = state.messages?.filter((message) => message.role === "tool" && typeof message.content === "string" && (message.content === "SUMMARIZED" || message.content.startsWith("SUMMARIZED_TOOL_RESPONSE"))).length || 0;
3614
- const numerator = summaryCount * 2 + archivedCount + summarizedMessages;
3615
- const denominator = Math.max(messageCount, 1);
3616
- return Number((numerator / denominator).toFixed(3));
3617
- }
3618
3588
 
3619
3589
  // src/nodes/contextSummarize.ts
3620
3590
  var systemMessage = (content) => ({ role: "system", content });
@@ -3759,6 +3729,9 @@ function findToolHistoryEntry(state, toolCallId, toolName) {
3759
3729
  }
3760
3730
  }
3761
3731
  }
3732
+ if (!toolName) {
3733
+ return void 0;
3734
+ }
3762
3735
  for (let index = entries.length - 1; index >= 0; index -= 1) {
3763
3736
  const entry = entries[index];
3764
3737
  if (entry?.toolName === toolName) {
@@ -3847,8 +3820,20 @@ function createContextSummarizeNode(opts) {
3847
3820
  const messages = state.messages || [];
3848
3821
  const onEvent = state.ctx?.__onEvent;
3849
3822
  const traceSession = state.ctx?.__traceSession;
3823
+ const toolResponsesConfigEarly = resolved.toolResponses;
3850
3824
  const compressableMessages = messages.filter(
3851
- (m) => m.role === "tool" && !isSummarizedToolPlaceholder(m.content) && !isSyntheticSummaryToolMessage(m)
3825
+ (m) => {
3826
+ if (m.role !== "tool") return false;
3827
+ if (isSummarizedToolPlaceholder(m.content)) return false;
3828
+ if (isSyntheticSummaryToolMessage(m)) return false;
3829
+ const histEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
3830
+ if (histEntry?.retentionPolicy === "keep_full") return false;
3831
+ if (!histEntry?.retentionPolicy) {
3832
+ const byTool = toolResponsesConfigEarly.toolResponseRetentionByTool?.[m.name || ""];
3833
+ if ((byTool || toolResponsesConfigEarly.defaultPolicy) === "keep_full") return false;
3834
+ }
3835
+ return true;
3836
+ }
3852
3837
  );
3853
3838
  if (compressableMessages.length === 0) {
3854
3839
  return {};
@@ -3869,6 +3854,13 @@ function createContextSummarizeNode(opts) {
3869
3854
  else if (Array.isArray(m.content)) {
3870
3855
  content = m.content.map((c) => c.text || JSON.stringify(c)).join(" ");
3871
3856
  }
3857
+ if (m.role === "tool" && isSummarizedToolPlaceholder(content)) {
3858
+ const historyEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
3859
+ if (historyEntry) {
3860
+ const original = historyEntry.rawOutput ?? historyEntry.output;
3861
+ content = typeof original === "string" ? original : JSON.stringify(original);
3862
+ }
3863
+ }
3872
3864
  const maxContentLength = 2e3;
3873
3865
  if (content.length > maxContentLength) {
3874
3866
  content = content.substring(0, maxContentLength) + "... [TRUNCATED]";
@@ -4004,6 +3996,23 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4004
3996
  });
4005
3997
  }
4006
3998
  });
3999
+ const protectedToolCallIds = /* @__PURE__ */ new Set();
4000
+ for (let i = messages.length - 1; i >= 0; i--) {
4001
+ const m = messages[i];
4002
+ if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
4003
+ const thisToolCallIds = new Set(m.tool_calls.map((tc) => tc.id).filter(Boolean));
4004
+ const otherCompressable = compressableMessages.filter(
4005
+ (cm) => !thisToolCallIds.has(cm.tool_call_id)
4006
+ );
4007
+ if (otherCompressable.length > 0) {
4008
+ for (const tc of m.tool_calls) {
4009
+ if (tc.id) protectedToolCallIds.add(tc.id);
4010
+ }
4011
+ }
4012
+ break;
4013
+ }
4014
+ }
4015
+ const toolResponsesConfig = resolved.toolResponses;
4007
4016
  const newMessages = messages.map((m) => {
4008
4017
  if (m.role === "tool") {
4009
4018
  if (isSyntheticSummaryToolMessage(m)) {
@@ -4014,6 +4023,16 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4014
4023
  return null;
4015
4024
  }
4016
4025
  if (isSummarizedToolPlaceholder(m.content)) return m;
4026
+ if (toolCallId && protectedToolCallIds.has(toolCallId)) return m;
4027
+ const toolName = m.name || "";
4028
+ const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
4029
+ const entryRetention = historyEntry?.retentionPolicy;
4030
+ if (entryRetention === "keep_full") return m;
4031
+ if (!entryRetention) {
4032
+ const byTool = toolResponsesConfig.toolResponseRetentionByTool?.[toolName];
4033
+ const configPolicy = byTool || toolResponsesConfig.defaultPolicy;
4034
+ if (configPolicy === "keep_full") return m;
4035
+ }
4017
4036
  return {
4018
4037
  ...m,
4019
4038
  content: buildSummarizedToolMessage(m, state)
@@ -4021,6 +4040,12 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4021
4040
  }
4022
4041
  return m;
4023
4042
  }).filter((m) => m !== null);
4043
+ const actuallyCompressed = newMessages.filter(
4044
+ (m) => m.role === "tool" && typeof m.content === "string" && m.content.startsWith("SUMMARIZED_TOOL_RESPONSE") && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
4045
+ );
4046
+ if (actuallyCompressed.length === 0) {
4047
+ return {};
4048
+ }
4024
4049
  const validatedMessages = validateMessageSequence(newMessages);
4025
4050
  const summaryToolCallId = `call_summary_${Date.now()}`;
4026
4051
  const assistantSummaryCall = {
@@ -4096,12 +4121,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4096
4121
  return {
4097
4122
  messages: finalMessages,
4098
4123
  summaries,
4099
- summaryRecords,
4100
- watchdog: {
4101
- ...state.watchdog || {},
4102
- compactions: (state.watchdog?.compactions || 0) + 1,
4103
- lastAction: "summarized"
4104
- }
4124
+ summaryRecords
4105
4125
  };
4106
4126
  };
4107
4127
  }
@@ -4400,8 +4420,7 @@ function needsSummarization(state, opts, summarizationEnabled) {
4400
4420
  return "";
4401
4421
  }).join("\n");
4402
4422
  const tokenCount = countApproxTokens(allText);
4403
- const contextRotScore = state.watchdog?.contextRotScore || 0;
4404
- const needsSum = tokenCount > maxTok || resolved.watchdog.enabled && resolved.watchdog.autoCompaction && contextRotScore >= resolved.watchdog.contextRotThreshold;
4423
+ const needsSum = tokenCount > maxTok;
4405
4424
  if (process.env.DEBUG_SUMMARIZATION) {
4406
4425
  const msgCount = (state.messages || []).length;
4407
4426
  const toolMsgs = (state.messages || []).filter((m) => m.role === "tool");
@@ -4411,7 +4430,7 @@ function needsSummarization(state, opts, summarizationEnabled) {
4411
4430
  });
4412
4431
  console.log(`[Summarization] Messages: ${msgCount}, Tool messages: ${toolMsgs.length}`);
4413
4432
  toolDetails.forEach((d) => console.log(` ${d}`));
4414
- console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Context rot: ${contextRotScore}, Needs summarization: ${needsSum}`);
4433
+ console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Needs summarization: ${needsSum}`);
4415
4434
  }
4416
4435
  return needsSum;
4417
4436
  } catch {
@@ -4565,7 +4584,6 @@ function createSmartAgent(opts) {
4565
4584
  delegation: resolved.delegation,
4566
4585
  memory: { ...resolved.memory, store: memoryStore },
4567
4586
  toolResponses: resolved.toolResponses,
4568
- watchdog: resolved.watchdog,
4569
4587
  useTodoList: planningEnabled
4570
4588
  };
4571
4589
  const stateRef = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
@@ -4648,7 +4666,6 @@ function createSmartAgent(opts) {
4648
4666
  let rawMessages = [...seedMessages];
4649
4667
  const effectiveMaxToolCalls = config?.limits?.maxToolCalls ?? resolved.limits.maxToolCalls ?? 10;
4650
4668
  const iterationLimit = Math.max(effectiveMaxToolCalls * 3 + 5, 30);
4651
- let previousTokenCount = countApproxTokens(rawMessages.map((message) => typeof message.content === "string" ? message.content : JSON.stringify(message.content)).join("\n"));
4652
4669
  for (let i = 0; i < iterationLimit; i++) {
4653
4670
  state = { ...state, messages: rawMessages };
4654
4671
  const next = summarizationEnabled ? decideBefore(state) : "agent";
@@ -4682,27 +4699,6 @@ function createSmartAgent(opts) {
4682
4699
  state = syncPlanState(await syncMemory(state));
4683
4700
  stateRef.toolHistory = state.toolHistory;
4684
4701
  stateRef.toolHistoryArchived = state.toolHistoryArchived;
4685
- const currentTokenCount = countApproxTokens(rawMessages.map((message) => typeof message.content === "string" ? message.content : JSON.stringify(message.content)).join("\n"));
4686
- const tokenDrift = Math.max(0, currentTokenCount - previousTokenCount);
4687
- const toolMessagesThisTurn = appendedMessages.filter((message) => message.role === "tool").length;
4688
- const overToolingRate = appendedMessages.length === 0 ? 0 : Number((toolMessagesThisTurn / appendedMessages.length).toFixed(2));
4689
- state = {
4690
- ...state,
4691
- watchdog: {
4692
- tokenDrift,
4693
- contextRotScore: estimateContextRotScore(state),
4694
- overToolingRate,
4695
- compactions: state.watchdog?.compactions || 0,
4696
- lastAction: appendedMessages.length > 0 ? "agent_turn" : state.watchdog?.lastAction
4697
- }
4698
- };
4699
- previousTokenCount = currentTokenCount;
4700
- if (resolved.watchdog.enabled && resolved.watchdog.autoCompaction) {
4701
- const shouldCompact = tokenDrift >= resolved.watchdog.tokenDriftThreshold || (state.watchdog?.overToolingRate || 0) >= resolved.watchdog.overToolingSpikeThreshold || (state.watchdog?.contextRotScore || 0) >= resolved.watchdog.contextRotThreshold;
4702
- if (shouldCompact) {
4703
- state = { ...state, ctx: { ...state.ctx || {}, __needsSummarization: true } };
4704
- }
4705
- }
4706
4702
  if (state.ctx?.__needsSummarization && summarizer) {
4707
4703
  const ctx = { ...state.ctx || {} };
4708
4704
  delete ctx.__needsSummarization;
@@ -4734,12 +4730,12 @@ function createSmartAgent(opts) {
4734
4730
  }
4735
4731
  if (state.summaries && state.summaries.length > 0) {
4736
4732
  if (lastResult.state) {
4737
- lastResult = { ...lastResult, state: { ...lastResult.state, summaries: state.summaries, summaryRecords: state.summaryRecords, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, watchdog: state.watchdog, messages: rawMessages } };
4733
+ lastResult = { ...lastResult, state: { ...lastResult.state, summaries: state.summaries, summaryRecords: state.summaryRecords, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, messages: rawMessages } };
4738
4734
  } else {
4739
- lastResult = { ...lastResult, state: { ...state, summaries: state.summaries, summaryRecords: state.summaryRecords, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, watchdog: state.watchdog, messages: rawMessages } };
4735
+ lastResult = { ...lastResult, state: { ...state, summaries: state.summaries, summaryRecords: state.summaryRecords, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, messages: rawMessages } };
4740
4736
  }
4741
4737
  } else if (lastResult.state) {
4742
- lastResult = { ...lastResult, state: { ...lastResult.state, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, watchdog: state.watchdog, messages: rawMessages } };
4738
+ lastResult = { ...lastResult, state: { ...lastResult.state, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, messages: rawMessages } };
4743
4739
  }
4744
4740
  return lastResult;
4745
4741
  },