@cognipeer/agent-sdk 0.5.0 → 0.5.1

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
@@ -2090,235 +2090,134 @@ function createAgentCoreNode(opts) {
2090
2090
 
2091
2091
  // src/smart/runtimeConfig.ts
2092
2092
  var DEFAULT_CRITICAL_TOOLS = ["response", "manage_todo_list", "get_tool_response"];
2093
+ var BASE_DEFAULTS = {
2094
+ limits: { maxToolCalls: 8, maxParallelTools: 2, maxContextTokens: 24e3 },
2095
+ summarization: {
2096
+ enable: true,
2097
+ maxTokens: 24e3,
2098
+ summaryTriggerTokens: 17e3,
2099
+ summaryPromptMaxTokens: 7e3,
2100
+ summaryCompressionRatioTarget: 0.35,
2101
+ summaryMode: "incremental",
2102
+ promptTemplate: "",
2103
+ toolFreeCall: true,
2104
+ integrityCheck: true
2105
+ },
2106
+ context: {
2107
+ policy: "hybrid",
2108
+ lastTurnsToKeep: 8,
2109
+ toolResponsePolicy: "summarize_archive",
2110
+ archiveLargeToolResponses: true,
2111
+ retrieveArchivedToolResponseOnDemand: true,
2112
+ budget: {
2113
+ systemReserveTokens: 1200,
2114
+ goalsReserveTokens: 1200,
2115
+ recentTurnsReserveTokens: 5200,
2116
+ toolResponseReserveTokens: 2800
2117
+ }
2118
+ },
2119
+ planning: {
2120
+ mode: "off",
2121
+ replanPolicy: "on_failure",
2122
+ everyNSteps: 0
2123
+ },
2124
+ memory: {
2125
+ provider: "inMemory",
2126
+ scope: "session",
2127
+ writePolicy: "auto_important",
2128
+ readPolicy: "hybrid"
2129
+ },
2130
+ delegation: {
2131
+ mode: "role_based",
2132
+ maxDelegationDepth: 2,
2133
+ maxChildCalls: 4,
2134
+ maxParallelChild: 2,
2135
+ childContextPolicy: "scoped",
2136
+ requireJsonOutputContract: true
2137
+ },
2138
+ toolResponses: {
2139
+ maxToolResponseChars: 3600,
2140
+ maxToolResponseTokens: 1200,
2141
+ defaultPolicy: "keep_structured",
2142
+ largeResponsePolicy: "summarize_archive",
2143
+ toolResponseRetentionByTool: {},
2144
+ criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2145
+ schemaValidation: "strict",
2146
+ retryOnSchemaError: true,
2147
+ fallbackPolicy: "keep_structured"
2148
+ }
2149
+ };
2150
+ function buildProfile(overrides) {
2151
+ return {
2152
+ limits: { ...BASE_DEFAULTS.limits, ...overrides.limits },
2153
+ summarization: { ...BASE_DEFAULTS.summarization, ...overrides.summarization },
2154
+ context: {
2155
+ ...BASE_DEFAULTS.context,
2156
+ ...overrides.context,
2157
+ budget: { ...BASE_DEFAULTS.context.budget, ...overrides.context?.budget }
2158
+ },
2159
+ planning: { ...BASE_DEFAULTS.planning, ...overrides.planning },
2160
+ memory: { ...BASE_DEFAULTS.memory, ...overrides.memory },
2161
+ delegation: { ...BASE_DEFAULTS.delegation, ...overrides.delegation },
2162
+ toolResponses: {
2163
+ ...BASE_DEFAULTS.toolResponses,
2164
+ ...overrides.toolResponses,
2165
+ criticalTools: overrides.toolResponses?.criticalTools ?? [...DEFAULT_CRITICAL_TOOLS],
2166
+ toolResponseRetentionByTool: overrides.toolResponses?.toolResponseRetentionByTool ?? {}
2167
+ }
2168
+ };
2169
+ }
2093
2170
  var DEFAULT_PROFILE_CONFIGS = {
2094
- fast: {
2171
+ fast: buildProfile({
2095
2172
  limits: { maxToolCalls: 4, maxParallelTools: 1, maxContextTokens: 12e3 },
2096
2173
  summarization: {
2097
- enable: true,
2098
2174
  maxTokens: 12e3,
2099
2175
  summaryTriggerTokens: 9e3,
2100
2176
  summaryPromptMaxTokens: 5e3,
2101
- summaryCompressionRatioTarget: 0.4,
2102
- summaryMode: "incremental",
2103
- promptTemplate: "",
2104
- toolFreeCall: true,
2105
- integrityCheck: true
2177
+ summaryCompressionRatioTarget: 0.4
2106
2178
  },
2107
2179
  context: {
2108
- policy: "hybrid",
2109
2180
  lastTurnsToKeep: 6,
2110
2181
  toolResponsePolicy: "keep_structured",
2111
- archiveLargeToolResponses: true,
2112
- retrieveArchivedToolResponseOnDemand: true,
2113
- budget: {
2114
- systemReserveTokens: 1e3,
2115
- goalsReserveTokens: 900,
2116
- recentTurnsReserveTokens: 3200,
2117
- toolResponseReserveTokens: 1800
2118
- }
2119
- },
2120
- planning: {
2121
- mode: "off",
2122
- replanPolicy: "on_failure",
2123
- everyNSteps: 0
2124
- },
2125
- memory: {
2126
- provider: "inMemory",
2127
- scope: "session",
2128
- writePolicy: "auto_important",
2129
- readPolicy: "recent_only"
2130
- },
2131
- delegation: {
2132
- mode: "off",
2133
- maxDelegationDepth: 1,
2134
- maxChildCalls: 2,
2135
- maxParallelChild: 1,
2136
- childContextPolicy: "minimal",
2137
- requireJsonOutputContract: true
2138
- },
2139
- toolResponses: {
2140
- maxToolResponseChars: 2400,
2141
- maxToolResponseTokens: 800,
2142
- defaultPolicy: "keep_structured",
2143
- largeResponsePolicy: "summarize_archive",
2144
- toolResponseRetentionByTool: {},
2145
- criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2146
- schemaValidation: "strict",
2147
- retryOnSchemaError: true,
2148
- fallbackPolicy: "keep_structured"
2149
- }
2150
- },
2151
- balanced: {
2152
- limits: { maxToolCalls: 8, maxParallelTools: 2, maxContextTokens: 24e3 },
2153
- summarization: {
2154
- enable: true,
2155
- maxTokens: 24e3,
2156
- summaryTriggerTokens: 17e3,
2157
- summaryPromptMaxTokens: 7e3,
2158
- summaryCompressionRatioTarget: 0.35,
2159
- summaryMode: "incremental",
2160
- promptTemplate: "",
2161
- toolFreeCall: true,
2162
- integrityCheck: true
2163
- },
2164
- context: {
2165
- policy: "hybrid",
2166
- lastTurnsToKeep: 8,
2167
- toolResponsePolicy: "summarize_archive",
2168
- archiveLargeToolResponses: true,
2169
- retrieveArchivedToolResponseOnDemand: true,
2170
- budget: {
2171
- systemReserveTokens: 1200,
2172
- goalsReserveTokens: 1200,
2173
- recentTurnsReserveTokens: 5200,
2174
- toolResponseReserveTokens: 2800
2175
- }
2176
- },
2177
- planning: {
2178
- mode: "off",
2179
- replanPolicy: "on_failure",
2180
- everyNSteps: 0
2181
- },
2182
- memory: {
2183
- provider: "inMemory",
2184
- scope: "session",
2185
- writePolicy: "auto_important",
2186
- readPolicy: "hybrid"
2187
- },
2188
- delegation: {
2189
- mode: "role_based",
2190
- maxDelegationDepth: 2,
2191
- maxChildCalls: 4,
2192
- maxParallelChild: 2,
2193
- childContextPolicy: "scoped",
2194
- requireJsonOutputContract: true
2182
+ budget: { systemReserveTokens: 1e3, goalsReserveTokens: 900, recentTurnsReserveTokens: 3200, toolResponseReserveTokens: 1800 }
2195
2183
  },
2196
- toolResponses: {
2197
- maxToolResponseChars: 3600,
2198
- maxToolResponseTokens: 1200,
2199
- defaultPolicy: "keep_structured",
2200
- largeResponsePolicy: "summarize_archive",
2201
- toolResponseRetentionByTool: {},
2202
- criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2203
- schemaValidation: "strict",
2204
- retryOnSchemaError: true,
2205
- fallbackPolicy: "keep_structured"
2206
- }
2207
- },
2208
- deep: {
2184
+ memory: { readPolicy: "recent_only" },
2185
+ delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
2186
+ toolResponses: { maxToolResponseChars: 2400, maxToolResponseTokens: 800 }
2187
+ }),
2188
+ balanced: buildProfile({}),
2189
+ deep: buildProfile({
2209
2190
  limits: { maxToolCalls: 14, maxParallelTools: 3, maxContextTokens: 42e3 },
2210
2191
  summarization: {
2211
- enable: true,
2212
2192
  maxTokens: 42e3,
2213
2193
  summaryTriggerTokens: 3e4,
2214
2194
  summaryPromptMaxTokens: 9e3,
2215
- summaryCompressionRatioTarget: 0.3,
2216
- summaryMode: "incremental",
2217
- promptTemplate: "",
2218
- toolFreeCall: true,
2219
- integrityCheck: true
2195
+ summaryCompressionRatioTarget: 0.3
2220
2196
  },
2221
2197
  context: {
2222
- policy: "hybrid",
2223
2198
  lastTurnsToKeep: 12,
2224
- toolResponsePolicy: "summarize_archive",
2225
- archiveLargeToolResponses: true,
2226
- retrieveArchivedToolResponseOnDemand: true,
2227
- budget: {
2228
- systemReserveTokens: 1400,
2229
- goalsReserveTokens: 1600,
2230
- recentTurnsReserveTokens: 7e3,
2231
- toolResponseReserveTokens: 3600
2232
- }
2233
- },
2234
- planning: {
2235
- mode: "off",
2236
- replanPolicy: "on_failure",
2237
- everyNSteps: 0
2238
- },
2239
- memory: {
2240
- provider: "inMemory",
2241
- scope: "workspace",
2242
- writePolicy: "auto_important",
2243
- readPolicy: "hybrid"
2199
+ budget: { systemReserveTokens: 1400, goalsReserveTokens: 1600, recentTurnsReserveTokens: 7e3, toolResponseReserveTokens: 3600 }
2244
2200
  },
2245
- delegation: {
2246
- mode: "role_based",
2247
- maxDelegationDepth: 3,
2248
- maxChildCalls: 6,
2249
- maxParallelChild: 2,
2250
- childContextPolicy: "scoped",
2251
- requireJsonOutputContract: true
2252
- },
2253
- toolResponses: {
2254
- maxToolResponseChars: 5400,
2255
- maxToolResponseTokens: 1800,
2256
- defaultPolicy: "keep_structured",
2257
- largeResponsePolicy: "summarize_archive",
2258
- toolResponseRetentionByTool: {},
2259
- criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2260
- schemaValidation: "strict",
2261
- retryOnSchemaError: true,
2262
- fallbackPolicy: "keep_structured"
2263
- }
2264
- },
2265
- research: {
2201
+ memory: { scope: "workspace" },
2202
+ delegation: { maxDelegationDepth: 3, maxChildCalls: 6 },
2203
+ toolResponses: { maxToolResponseChars: 5400, maxToolResponseTokens: 1800 }
2204
+ }),
2205
+ research: buildProfile({
2266
2206
  limits: { maxToolCalls: 20, maxParallelTools: 4, maxContextTokens: 56e3 },
2267
2207
  summarization: {
2268
- enable: true,
2269
2208
  maxTokens: 56e3,
2270
2209
  summaryTriggerTokens: 42e3,
2271
2210
  summaryPromptMaxTokens: 1e4,
2272
- summaryCompressionRatioTarget: 0.28,
2273
- summaryMode: "incremental",
2274
- promptTemplate: "",
2275
- toolFreeCall: true,
2276
- integrityCheck: true
2211
+ summaryCompressionRatioTarget: 0.28
2277
2212
  },
2278
2213
  context: {
2279
- policy: "hybrid",
2280
2214
  lastTurnsToKeep: 20,
2281
- toolResponsePolicy: "summarize_archive",
2282
- archiveLargeToolResponses: true,
2283
- retrieveArchivedToolResponseOnDemand: true,
2284
- budget: {
2285
- systemReserveTokens: 1600,
2286
- goalsReserveTokens: 1800,
2287
- recentTurnsReserveTokens: 9e3,
2288
- toolResponseReserveTokens: 4800
2289
- }
2215
+ budget: { systemReserveTokens: 1600, goalsReserveTokens: 1800, recentTurnsReserveTokens: 9e3, toolResponseReserveTokens: 4800 }
2290
2216
  },
2291
- planning: {
2292
- mode: "off",
2293
- replanPolicy: "on_failure",
2294
- everyNSteps: 0
2295
- },
2296
- memory: {
2297
- provider: "inMemory",
2298
- scope: "workspace",
2299
- writePolicy: "auto_important",
2300
- readPolicy: "hybrid"
2301
- },
2302
- delegation: {
2303
- mode: "automatic",
2304
- maxDelegationDepth: 4,
2305
- maxChildCalls: 8,
2306
- maxParallelChild: 3,
2307
- childContextPolicy: "full",
2308
- requireJsonOutputContract: true
2309
- },
2310
- toolResponses: {
2311
- maxToolResponseChars: 7200,
2312
- maxToolResponseTokens: 2200,
2313
- defaultPolicy: "keep_structured",
2314
- largeResponsePolicy: "summarize_archive",
2315
- toolResponseRetentionByTool: {},
2316
- criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2317
- schemaValidation: "strict",
2318
- retryOnSchemaError: true,
2319
- fallbackPolicy: "keep_structured"
2320
- }
2321
- }
2217
+ memory: { scope: "workspace" },
2218
+ delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 8, maxParallelChild: 3, childContextPolicy: "full" },
2219
+ toolResponses: { maxToolResponseChars: 7200, maxToolResponseTokens: 2200 }
2220
+ })
2322
2221
  };
2323
2222
  function mergeLimits(base, override) {
2324
2223
  return {
@@ -2461,16 +2360,52 @@ function countMessagesTokens(messages) {
2461
2360
  return countApproxTokens(allText) + messages.length * 4;
2462
2361
  }
2463
2362
 
2464
- // src/smart/toolResponses.ts
2465
- function safeStringify(value) {
2363
+ // src/utils/content.ts
2364
+ function contentToString(content) {
2365
+ try {
2366
+ if (content == null) return "";
2367
+ if (typeof content === "string") return content;
2368
+ if (Array.isArray(content)) {
2369
+ return content.map((p) => {
2370
+ if (!p || typeof p !== "object") return String(p);
2371
+ if (p.type === "text") return String(p.text ?? "");
2372
+ if (p.type === "image_url") {
2373
+ const img = p.image_url;
2374
+ const url = typeof img === "string" ? img : img?.url;
2375
+ const detail = typeof img === "string" ? void 0 : img?.detail;
2376
+ return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
2377
+ }
2378
+ return JSON.stringify(p);
2379
+ }).join("\n");
2380
+ }
2381
+ return JSON.stringify(content);
2382
+ } catch {
2383
+ return String(content);
2384
+ }
2385
+ }
2386
+ function mergeContentsToString(contents) {
2387
+ return contents.map((c) => contentToString(c)).join("\n");
2388
+ }
2389
+ function safeStringify(value, pretty = false) {
2390
+ if (value == null) return "";
2466
2391
  if (typeof value === "string") return value;
2467
2392
  try {
2468
- const serialized = JSON.stringify(value);
2469
- return typeof serialized === "string" ? serialized : String(value);
2393
+ return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
2470
2394
  } catch {
2471
2395
  return String(value);
2472
2396
  }
2473
2397
  }
2398
+ function extractMessageText2(message) {
2399
+ if (!message) return "";
2400
+ const content = message.content;
2401
+ if (typeof content === "string") return content;
2402
+ if (Array.isArray(content)) {
2403
+ return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
2404
+ }
2405
+ return "";
2406
+ }
2407
+
2408
+ // src/smart/toolResponses.ts
2474
2409
  function summarizeObject(value) {
2475
2410
  if (value == null) return "null";
2476
2411
  if (typeof value === "string") {
@@ -3234,6 +3169,21 @@ function resolveToolApprovalState(state, resolution) {
3234
3169
  };
3235
3170
  }
3236
3171
 
3172
+ // src/utils/syntheticMessages.ts
3173
+ function isSyntheticSummaryMessage(message) {
3174
+ if (!message) return false;
3175
+ if (message.role === "tool" && message.name === "summarize_context") {
3176
+ return true;
3177
+ }
3178
+ if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
3179
+ return message.tool_calls.some((toolCall) => {
3180
+ const toolName = toolCall?.function?.name || toolCall?.name;
3181
+ return toolName === "summarize_context";
3182
+ });
3183
+ }
3184
+ return false;
3185
+ }
3186
+
3237
3187
  // src/structuredOutput/manager.ts
3238
3188
  var StructuredOutputManager = class {
3239
3189
  constructor(schema, strategy, config) {
@@ -3382,26 +3332,6 @@ var StructuredOutputManager = class {
3382
3332
  };
3383
3333
 
3384
3334
  // src/agent.ts
3385
- function isSyntheticSummaryMessage(message) {
3386
- if (!message) return false;
3387
- if (message.role === "tool" && message.name === "summarize_context") {
3388
- return true;
3389
- }
3390
- if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
3391
- return message.tool_calls.some((toolCall) => {
3392
- const toolName = toolCall?.function?.name || toolCall?.name;
3393
- return toolName === "summarize_context";
3394
- });
3395
- }
3396
- return false;
3397
- }
3398
- function getMessageText(message) {
3399
- if (typeof message?.content === "string") return message.content;
3400
- if (Array.isArray(message?.content)) {
3401
- return message.content.map((chunk) => typeof chunk === "string" ? chunk : chunk?.text ?? chunk?.content ?? "").join("");
3402
- }
3403
- return "";
3404
- }
3405
3335
  function getLastAssistantMessage(messages) {
3406
3336
  for (let index = messages.length - 1; index >= 0; index -= 1) {
3407
3337
  if (messages[index]?.role === "assistant") {
@@ -3819,7 +3749,7 @@ function createAgent(opts) {
3819
3749
  status: "success"
3820
3750
  });
3821
3751
  const finalAssistantMsg = getLastAssistantMessage(res.messages);
3822
- const content = getMessageText(finalAssistantMsg);
3752
+ const content = extractMessageText2(finalAssistantMsg);
3823
3753
  let parsed = void 0;
3824
3754
  let outputError = void 0;
3825
3755
  if (soManager) {
@@ -4019,13 +3949,6 @@ function createAgentNode(opts) {
4019
3949
  }
4020
3950
 
4021
3951
  // src/smart/contextPolicy.ts
4022
- function messageText(message) {
4023
- if (typeof message.content === "string") return message.content;
4024
- if (Array.isArray(message.content)) {
4025
- return message.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? JSON.stringify(part)).join(" ");
4026
- }
4027
- return "";
4028
- }
4029
3952
  function collectRecentTurns(messages, lastTurnsToKeep) {
4030
3953
  if (lastTurnsToKeep <= 0) return [];
4031
3954
  const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
@@ -4066,10 +3989,6 @@ function renderStructuredSummary(summary) {
4066
3989
  lines.push("Open questions:");
4067
3990
  lines.push(...summary.open_questions.map((question) => `- ${question}`));
4068
3991
  }
4069
- if (summary.discarded_obsolete.length > 0) {
4070
- lines.push("Discarded obsolete:");
4071
- lines.push(...summary.discarded_obsolete.map((item) => `- ${item}`));
4072
- }
4073
3992
  return lines.join("\n");
4074
3993
  }
4075
3994
  function renderMemoryBlock(facts) {
@@ -4082,7 +4001,7 @@ function renderMemoryBlock(facts) {
4082
4001
  function clampToBudget(messages, maxContextTokens) {
4083
4002
  let working = [...messages];
4084
4003
  while (working.length > 2) {
4085
- const tokenCount = countApproxTokens(working.map(messageText).join("\n"));
4004
+ const tokenCount = countApproxTokens(working.map(extractMessageText2).join("\n"));
4086
4005
  if (tokenCount <= maxContextTokens) return working;
4087
4006
  const firstNonSystem = working.findIndex((message, index) => !(index === 0 && message.role === "system"));
4088
4007
  if (firstNonSystem < 0) break;
@@ -4156,18 +4075,6 @@ function buildModelMessages(state, config) {
4156
4075
  // src/nodes/contextSummarize.ts
4157
4076
  var systemMessage = (content) => ({ role: "system", content });
4158
4077
  var humanMessage = (content) => ({ role: "user", content });
4159
- function isSyntheticSummaryToolMessage(message) {
4160
- return message.role === "tool" && message.name === "summarize_context";
4161
- }
4162
- function isSyntheticSummaryAssistantMessage(message) {
4163
- if (message.role !== "assistant" || !Array.isArray(message.tool_calls)) {
4164
- return false;
4165
- }
4166
- return message.tool_calls.some((toolCall) => {
4167
- const toolName = toolCall?.function?.name || toolCall?.name;
4168
- return toolName === "summarize_context";
4169
- });
4170
- }
4171
4078
  function validateMessageSequence(messages) {
4172
4079
  const validated = [];
4173
4080
  const pendingToolCallIds = /* @__PURE__ */ new Set();
@@ -4392,7 +4299,7 @@ function createContextSummarizeNode(opts) {
4392
4299
  (m) => {
4393
4300
  if (m.role !== "tool") return false;
4394
4301
  if (isSummarizedToolPlaceholder(m.content)) return false;
4395
- if (isSyntheticSummaryToolMessage(m)) return false;
4302
+ if (isSyntheticSummaryMessage(m)) return false;
4396
4303
  const histEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
4397
4304
  if (histEntry?.retentionPolicy === "keep_full") return false;
4398
4305
  if (!histEntry?.retentionPolicy) {
@@ -4405,15 +4312,14 @@ function createContextSummarizeNode(opts) {
4405
4312
  if (compressableMessages.length === 0) {
4406
4313
  return {};
4407
4314
  }
4408
- 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");
4409
- const tokenCountBefore = countApproxTokens(allTextBefore);
4315
+ const tokenCountBefore = countMessagesTokens(messages);
4410
4316
  const summaryPromptMaxTokens = config.summaryPromptMaxTokens;
4411
4317
  const availableTokensForConversation = summaryPromptMaxTokens - 500;
4412
4318
  const messageTexts = [];
4413
4319
  let accumulatedTokens = 0;
4414
4320
  for (let i = messages.length - 1; i >= 0; i--) {
4415
4321
  const m = messages[i];
4416
- if (isSyntheticSummaryToolMessage(m) || isSyntheticSummaryAssistantMessage(m)) {
4322
+ if (isSyntheticSummaryMessage(m) || isSyntheticSummaryMessage(m)) {
4417
4323
  continue;
4418
4324
  }
4419
4325
  let content = "";
@@ -4434,13 +4340,13 @@ function createContextSummarizeNode(opts) {
4434
4340
  }
4435
4341
  let prefix = `${m.role.toUpperCase()}`;
4436
4342
  if (m.name) prefix += ` (${m.name})`;
4437
- const messageText2 = `${prefix}: ${content}`;
4438
- const messageTokens = countApproxTokens(messageText2);
4343
+ const messageText = `${prefix}: ${content}`;
4344
+ const messageTokens = countApproxTokens(messageText);
4439
4345
  if (accumulatedTokens + messageTokens > availableTokensForConversation) {
4440
4346
  messageTexts.unshift("[Earlier conversation history omitted for brevity]");
4441
4347
  break;
4442
4348
  }
4443
- messageTexts.unshift(messageText2);
4349
+ messageTexts.unshift(messageText);
4444
4350
  accumulatedTokens += messageTokens;
4445
4351
  }
4446
4352
  const conversationText = messageTexts.join("\n\n");
@@ -4582,7 +4488,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4582
4488
  const toolResponsesConfig = resolved.toolResponses;
4583
4489
  const newMessages = messages.map((m) => {
4584
4490
  if (m.role === "tool") {
4585
- if (isSyntheticSummaryToolMessage(m)) {
4491
+ if (isSyntheticSummaryMessage(m)) {
4586
4492
  return m;
4587
4493
  }
4588
4494
  const toolCallId = m.tool_call_id;
@@ -4640,8 +4546,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4640
4546
  const summaries = Array.isArray(state.summaries) ? [...state.summaries, summaryText] : [summaryText];
4641
4547
  const summaryRecords = Array.isArray(state.summaryRecords) ? [...state.summaryRecords, { ...structuredSummary || normalizeStructuredSummary(void 0, summaryText), integrity, createdAt: (/* @__PURE__ */ new Date()).toISOString() }] : [{ ...structuredSummary || normalizeStructuredSummary(void 0, summaryText), integrity, createdAt: (/* @__PURE__ */ new Date()).toISOString() }];
4642
4548
  const finalMessages = [...validatedMessages, assistantSummaryCall, toolSummaryResponse];
4643
- 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");
4644
- const tokenCountAfter = countApproxTokens(allTextAfter);
4549
+ const tokenCountAfter = countMessagesTokens(finalMessages);
4645
4550
  const summarizationEvent = {
4646
4551
  type: "summarization",
4647
4552
  summary: summaryText,
@@ -4692,25 +4597,6 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4692
4597
  };
4693
4598
  };
4694
4599
  }
4695
-
4696
- // src/utils/tokenManager.ts
4697
- async function applyTokenLimits({
4698
- state,
4699
- limits
4700
- }) {
4701
- const messages = state.messages || [];
4702
- const budget = limits.contextTokenLimit;
4703
- let total = messages.reduce((acc, m) => acc + countApproxTokens(String(m.content || "")), 0);
4704
- if (total <= budget) return state;
4705
- const newMessages = [...messages];
4706
- while (total > budget && newMessages.length > 1) {
4707
- const idx = newMessages.findIndex((m) => m.role !== "system");
4708
- if (idx === -1) break;
4709
- const removed = newMessages.splice(idx, 1)[0];
4710
- total -= countApproxTokens(String(removed.content || ""));
4711
- }
4712
- return { ...state, messages: newMessages };
4713
- }
4714
4600
  var todoStatusSchema = zod.z.enum(["not-started", "in-progress", "completed", "blocked"]);
4715
4601
  var todoWriteItemSchema = zod.z.object({
4716
4602
  id: zod.z.number().int().min(1).describe("Sequential id starting from 1"),
@@ -4969,19 +4855,6 @@ function createContextTools(stateRef, opts) {
4969
4855
  }
4970
4856
 
4971
4857
  // src/graph/decisions.ts
4972
- function isSyntheticSummaryMessage2(message) {
4973
- if (!message) return false;
4974
- if (message.role === "tool" && message.name === "summarize_context") {
4975
- return true;
4976
- }
4977
- if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
4978
- return message.tool_calls.some((toolCall) => {
4979
- const toolName = toolCall?.function?.name || toolCall?.name;
4980
- return toolName === "summarize_context";
4981
- });
4982
- }
4983
- return false;
4984
- }
4985
4858
  function needsSummarization(state, opts, summarizationEnabled) {
4986
4859
  if (!summarizationEnabled) {
4987
4860
  return false;
@@ -4995,30 +4868,9 @@ function needsSummarization(state, opts, summarizationEnabled) {
4995
4868
  }
4996
4869
  const maxTok = resolved.summarization.summaryTriggerTokens;
4997
4870
  try {
4998
- const allText = (state.messages || []).filter((message) => !isSyntheticSummaryMessage2(message)).map((m) => {
4999
- if (typeof m.content === "string") return m.content;
5000
- if (Array.isArray(m.content)) {
5001
- return m.content.map((c) => typeof c === "string" ? c : c?.text ?? c?.content ?? JSON.stringify(c)).join("");
5002
- }
5003
- if (m.content && typeof m.content === "object") {
5004
- return JSON.stringify(m.content);
5005
- }
5006
- return "";
5007
- }).join("\n");
5008
- const tokenCount = countApproxTokens(allText);
5009
- const needsSum = tokenCount > maxTok;
5010
- if (process.env.DEBUG_SUMMARIZATION) {
5011
- const msgCount = (state.messages || []).length;
5012
- const toolMsgs = (state.messages || []).filter((m) => m.role === "tool");
5013
- const toolDetails = toolMsgs.map((m, i) => {
5014
- const contentStr = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
5015
- return `[${i}] id:${m.tool_call_id?.slice(-8) || "none"} len:${contentStr.length} preview:"${contentStr.slice(0, 30)}..."`;
5016
- });
5017
- console.log(`[Summarization] Messages: ${msgCount}, Tool messages: ${toolMsgs.length}`);
5018
- toolDetails.forEach((d) => console.log(` ${d}`));
5019
- console.log(`[Summarization] Token count: ${tokenCount}, Max: ${maxTok}, Needs summarization: ${needsSum}`);
5020
- }
5021
- return needsSum;
4871
+ const filtered = (state.messages || []).filter((message) => !isSyntheticSummaryMessage(message));
4872
+ const tokenCount = countMessagesTokens(filtered);
4873
+ return tokenCount > maxTok;
5022
4874
  } catch {
5023
4875
  return false;
5024
4876
  }
@@ -5147,13 +4999,6 @@ async function writeSummaryFactsToMemory(store, config, summary, sourceTurn) {
5147
4999
  }
5148
5000
  return store.get(config.memory.scope, { limit: config.context.lastTurnsToKeep + summary.stable_facts.length });
5149
5001
  }
5150
- function renderMemoryFacts(facts) {
5151
- if (facts.length === 0) return "";
5152
- return [
5153
- "Memory facts:",
5154
- ...facts.map((fact) => `- ${fact.key}: ${fact.value} (confidence ${fact.confidence.toFixed(2)})`)
5155
- ].join("\n");
5156
- }
5157
5002
 
5158
5003
  // src/smart/index.ts
5159
5004
  function createSmartAgent(opts) {
@@ -5193,8 +5038,7 @@ function createSmartAgent(opts) {
5193
5038
  ].join("\n");
5194
5039
  function latestUserPrompt(messages) {
5195
5040
  const latest = [...messages].reverse().find((message) => message.role === "user");
5196
- if (!latest) return "";
5197
- return typeof latest.content === "string" ? latest.content : Array.isArray(latest.content) ? latest.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join(" ") : "";
5041
+ return latest ? extractMessageText2(latest) : "";
5198
5042
  }
5199
5043
  async function syncMemory(state) {
5200
5044
  const query = latestUserPrompt(state.messages || []);
@@ -5234,6 +5078,18 @@ function createSmartAgent(opts) {
5234
5078
  );
5235
5079
  return { role: "system", content: sys };
5236
5080
  }
5081
+ async function trySummarize(currentState, currentRawMessages) {
5082
+ if (!summarizer) return { state: currentState, rawMessages: currentRawMessages, compressed: false };
5083
+ const delta = await summarizer(currentState);
5084
+ if (!delta || Object.keys(delta).length === 0) {
5085
+ const ctx2 = { ...currentState.ctx || {}, __summarizationExhausted: true };
5086
+ return { state: { ...currentState, ctx: ctx2 }, rawMessages: currentRawMessages, compressed: false };
5087
+ }
5088
+ const ctx = { ...currentState.ctx || {} };
5089
+ delete ctx.__summarizationExhausted;
5090
+ const updated = await persistLatestSummary(syncPlanState({ ...currentState, ...delta, ctx }));
5091
+ return { state: updated, rawMessages: [...updated.messages || currentRawMessages], compressed: true };
5092
+ }
5237
5093
  const instance = {
5238
5094
  invoke: async (input, config) => {
5239
5095
  stateRef.toolHistory = input.toolHistory;
@@ -5252,17 +5108,10 @@ function createSmartAgent(opts) {
5252
5108
  state = { ...state, messages: rawMessages };
5253
5109
  const next = summarizationEnabled ? decideBefore(state) : "agent";
5254
5110
  if (next === "contextSummarize" && summarizer) {
5255
- const delta = await summarizer(state);
5256
- if (!delta || Object.keys(delta).length === 0) {
5257
- const ctx = { ...state.ctx || {}, __summarizationExhausted: true };
5258
- state = { ...state, ctx };
5259
- } else {
5260
- const ctx = { ...state.ctx || {} };
5261
- delete ctx.__summarizationExhausted;
5262
- state = await persistLatestSummary(syncPlanState({ ...state, ...delta, ctx }));
5263
- rawMessages = [...state.messages || rawMessages];
5264
- continue;
5265
- }
5111
+ const result = await trySummarize(state, rawMessages);
5112
+ state = result.state;
5113
+ rawMessages = result.rawMessages;
5114
+ if (result.compressed) continue;
5266
5115
  }
5267
5116
  const modelMessages = buildModelMessages(state, resolved);
5268
5117
  const res = await base.invoke({ ...state, messages: modelMessages }, config);
@@ -5290,35 +5139,20 @@ function createSmartAgent(opts) {
5290
5139
  const ctx = { ...state.ctx || {} };
5291
5140
  delete ctx.__needsSummarization;
5292
5141
  state = { ...state, ctx };
5293
- const delta = await summarizer(state);
5294
- if (delta && Object.keys(delta).length > 0) {
5295
- const successCtx = { ...state.ctx || {} };
5296
- delete successCtx.__summarizationExhausted;
5297
- state = await persistLatestSummary(syncPlanState({ ...state, ...delta, ctx: successCtx }));
5298
- rawMessages = [...state.messages || rawMessages];
5299
- continue;
5300
- } else {
5301
- const exhaustedCtx = { ...state.ctx || {}, __summarizationExhausted: true };
5302
- state = { ...state, ctx: exhaustedCtx };
5303
- continue;
5304
- }
5142
+ const result = await trySummarize(state, rawMessages);
5143
+ state = result.state;
5144
+ rawMessages = result.rawMessages;
5145
+ continue;
5305
5146
  }
5306
5147
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
5307
5148
  if (opts.outputSchema && lastResult?.output != null) break;
5308
5149
  if (summarizationEnabled) {
5309
5150
  const after = decideAfter(state);
5310
5151
  if (after === "contextSummarize" && summarizer) {
5311
- const delta = await summarizer(state);
5312
- if (delta && Object.keys(delta).length > 0) {
5313
- const successCtx = { ...state.ctx || {} };
5314
- delete successCtx.__summarizationExhausted;
5315
- state = await persistLatestSummary(syncPlanState({ ...state, ...delta, ctx: successCtx }));
5316
- rawMessages = [...state.messages || rawMessages];
5317
- continue;
5318
- } else {
5319
- const exhaustedCtx = { ...state.ctx || {}, __summarizationExhausted: true };
5320
- state = { ...state, ctx: exhaustedCtx };
5321
- }
5152
+ const result = await trySummarize(state, rawMessages);
5153
+ state = result.state;
5154
+ rawMessages = result.rawMessages;
5155
+ if (result.compressed) continue;
5322
5156
  }
5323
5157
  }
5324
5158
  break;
@@ -5482,35 +5316,6 @@ async function runSmartAgentEvalHarness(params) {
5482
5316
  }
5483
5317
  return results;
5484
5318
  }
5485
-
5486
- // src/utils/content.ts
5487
- function contentToString(content) {
5488
- try {
5489
- if (content == null) return "";
5490
- if (typeof content === "string") return content;
5491
- if (Array.isArray(content)) {
5492
- return content.map((p) => {
5493
- if (!p || typeof p !== "object") return String(p);
5494
- if (p.type === "text") return String(p.text ?? "");
5495
- if (p.type === "image_url") {
5496
- const img = p.image_url;
5497
- const url = typeof img === "string" ? img : img?.url;
5498
- const detail = typeof img === "string" ? void 0 : img?.detail;
5499
- return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
5500
- }
5501
- return JSON.stringify(p);
5502
- }).join("\n");
5503
- }
5504
- return JSON.stringify(content);
5505
- } catch {
5506
- return String(content);
5507
- }
5508
- }
5509
- function mergeContentsToString(contents) {
5510
- return contents.map((c) => contentToString(c)).join("\n");
5511
- }
5512
-
5513
- // src/guardrails/checks.ts
5514
5319
  var Ajv = AjvModule__default.default?.default ?? AjvModule__default.default;
5515
5320
  var defaultAjv = new Ajv({ allErrors: true });
5516
5321
  defaultAjv.opts.strict = false;
@@ -7509,7 +7314,6 @@ exports.StructuredOutputManager = StructuredOutputManager;
7509
7314
  exports.ToolBasedStrategy = ToolBasedStrategy;
7510
7315
  exports.VertexProvider = VertexProvider;
7511
7316
  exports.agentVerdictRule = agentVerdictRule;
7512
- exports.applyTokenLimits = applyTokenLimits;
7513
7317
  exports.buildSystemPrompt = buildSystemPrompt;
7514
7318
  exports.captureSnapshot = captureSnapshot;
7515
7319
  exports.codePresenceRule = codePresenceRule;
@@ -7551,7 +7355,6 @@ exports.normalizeSmartAgentOptions = normalizeSmartAgentOptions;
7551
7355
  exports.otlpSink = otlpSink;
7552
7356
  exports.readMemoryFacts = readMemoryFacts;
7553
7357
  exports.regexRule = regexRule;
7554
- exports.renderMemoryFacts = renderMemoryFacts;
7555
7358
  exports.resolveMemoryStore = resolveMemoryStore;
7556
7359
  exports.resolveStrategy = resolveStrategy;
7557
7360
  exports.resolveToolApprovalState = resolveToolApprovalState;