@cognipeer/agent-sdk 0.5.0 → 0.5.2

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"
2182
+ budget: { systemReserveTokens: 1e3, goalsReserveTokens: 900, recentTurnsReserveTokens: 3200, toolResponseReserveTokens: 1800 }
2130
2183
  },
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
2195
- },
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
- }
2290
- },
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
2215
+ budget: { systemReserveTokens: 1600, goalsReserveTokens: 1800, recentTurnsReserveTokens: 9e3, toolResponseReserveTokens: 4800 }
2309
2216
  },
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") {
@@ -3695,6 +3625,21 @@ function createAgent(opts) {
3695
3625
  }
3696
3626
  if (toolCalls.length === 0) {
3697
3627
  if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize) {
3628
+ if (soManager.strategy.kind === "native") {
3629
+ const assistantText = extractMessageText2(lastMsg);
3630
+ if (assistantText) {
3631
+ const parsed = soManager.parseFromContent(assistantText);
3632
+ if (parsed.success) {
3633
+ const ctx2 = {
3634
+ ...state.ctx || {},
3635
+ __finalizedDueToStructuredOutput: true,
3636
+ __structuredOutputParsed: parsed.data
3637
+ };
3638
+ state = { ...state, ctx: ctx2 };
3639
+ }
3640
+ }
3641
+ break;
3642
+ }
3698
3643
  const nudge = soManager.buildNudgeMessage(false);
3699
3644
  const ctx = { ...state.ctx || {}, __structuredOutputForceFinalize: true };
3700
3645
  state = { ...state, messages: [...state.messages, nudge], ctx };
@@ -3711,6 +3656,23 @@ function createAgent(opts) {
3711
3656
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
3712
3657
  }
3713
3658
  if (soManager && !state.ctx?.__finalizedDueToStructuredOutput) {
3659
+ const lastForParse = state.messages[state.messages.length - 1];
3660
+ if (lastForParse?.role === "assistant") {
3661
+ const assistantText = extractMessageText2(lastForParse);
3662
+ if (assistantText) {
3663
+ const parsed = soManager.parseFromContent(assistantText);
3664
+ if (parsed.success) {
3665
+ const ctx = {
3666
+ ...state.ctx || {},
3667
+ __finalizedDueToStructuredOutput: true,
3668
+ __structuredOutputParsed: parsed.data
3669
+ };
3670
+ state = { ...state, ctx };
3671
+ }
3672
+ }
3673
+ }
3674
+ }
3675
+ if (soManager && soManager.strategy.kind === "tool_based" && !state.ctx?.__finalizedDueToStructuredOutput) {
3714
3676
  const maxPostLoopRetries = soManager.maxRetries;
3715
3677
  for (let postRetry = 0; postRetry < maxPostLoopRetries; postRetry++) {
3716
3678
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
@@ -3819,7 +3781,7 @@ function createAgent(opts) {
3819
3781
  status: "success"
3820
3782
  });
3821
3783
  const finalAssistantMsg = getLastAssistantMessage(res.messages);
3822
- const content = getMessageText(finalAssistantMsg);
3784
+ const content = extractMessageText2(finalAssistantMsg);
3823
3785
  let parsed = void 0;
3824
3786
  let outputError = void 0;
3825
3787
  if (soManager) {
@@ -4019,13 +3981,6 @@ function createAgentNode(opts) {
4019
3981
  }
4020
3982
 
4021
3983
  // 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
3984
  function collectRecentTurns(messages, lastTurnsToKeep) {
4030
3985
  if (lastTurnsToKeep <= 0) return [];
4031
3986
  const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
@@ -4066,10 +4021,6 @@ function renderStructuredSummary(summary) {
4066
4021
  lines.push("Open questions:");
4067
4022
  lines.push(...summary.open_questions.map((question) => `- ${question}`));
4068
4023
  }
4069
- if (summary.discarded_obsolete.length > 0) {
4070
- lines.push("Discarded obsolete:");
4071
- lines.push(...summary.discarded_obsolete.map((item) => `- ${item}`));
4072
- }
4073
4024
  return lines.join("\n");
4074
4025
  }
4075
4026
  function renderMemoryBlock(facts) {
@@ -4082,7 +4033,7 @@ function renderMemoryBlock(facts) {
4082
4033
  function clampToBudget(messages, maxContextTokens) {
4083
4034
  let working = [...messages];
4084
4035
  while (working.length > 2) {
4085
- const tokenCount = countApproxTokens(working.map(messageText).join("\n"));
4036
+ const tokenCount = countApproxTokens(working.map(extractMessageText2).join("\n"));
4086
4037
  if (tokenCount <= maxContextTokens) return working;
4087
4038
  const firstNonSystem = working.findIndex((message, index) => !(index === 0 && message.role === "system"));
4088
4039
  if (firstNonSystem < 0) break;
@@ -4156,18 +4107,6 @@ function buildModelMessages(state, config) {
4156
4107
  // src/nodes/contextSummarize.ts
4157
4108
  var systemMessage = (content) => ({ role: "system", content });
4158
4109
  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
4110
  function validateMessageSequence(messages) {
4172
4111
  const validated = [];
4173
4112
  const pendingToolCallIds = /* @__PURE__ */ new Set();
@@ -4392,7 +4331,7 @@ function createContextSummarizeNode(opts) {
4392
4331
  (m) => {
4393
4332
  if (m.role !== "tool") return false;
4394
4333
  if (isSummarizedToolPlaceholder(m.content)) return false;
4395
- if (isSyntheticSummaryToolMessage(m)) return false;
4334
+ if (isSyntheticSummaryMessage(m)) return false;
4396
4335
  const histEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
4397
4336
  if (histEntry?.retentionPolicy === "keep_full") return false;
4398
4337
  if (!histEntry?.retentionPolicy) {
@@ -4405,15 +4344,14 @@ function createContextSummarizeNode(opts) {
4405
4344
  if (compressableMessages.length === 0) {
4406
4345
  return {};
4407
4346
  }
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);
4347
+ const tokenCountBefore = countMessagesTokens(messages);
4410
4348
  const summaryPromptMaxTokens = config.summaryPromptMaxTokens;
4411
4349
  const availableTokensForConversation = summaryPromptMaxTokens - 500;
4412
4350
  const messageTexts = [];
4413
4351
  let accumulatedTokens = 0;
4414
4352
  for (let i = messages.length - 1; i >= 0; i--) {
4415
4353
  const m = messages[i];
4416
- if (isSyntheticSummaryToolMessage(m) || isSyntheticSummaryAssistantMessage(m)) {
4354
+ if (isSyntheticSummaryMessage(m) || isSyntheticSummaryMessage(m)) {
4417
4355
  continue;
4418
4356
  }
4419
4357
  let content = "";
@@ -4434,13 +4372,13 @@ function createContextSummarizeNode(opts) {
4434
4372
  }
4435
4373
  let prefix = `${m.role.toUpperCase()}`;
4436
4374
  if (m.name) prefix += ` (${m.name})`;
4437
- const messageText2 = `${prefix}: ${content}`;
4438
- const messageTokens = countApproxTokens(messageText2);
4375
+ const messageText = `${prefix}: ${content}`;
4376
+ const messageTokens = countApproxTokens(messageText);
4439
4377
  if (accumulatedTokens + messageTokens > availableTokensForConversation) {
4440
4378
  messageTexts.unshift("[Earlier conversation history omitted for brevity]");
4441
4379
  break;
4442
4380
  }
4443
- messageTexts.unshift(messageText2);
4381
+ messageTexts.unshift(messageText);
4444
4382
  accumulatedTokens += messageTokens;
4445
4383
  }
4446
4384
  const conversationText = messageTexts.join("\n\n");
@@ -4582,7 +4520,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4582
4520
  const toolResponsesConfig = resolved.toolResponses;
4583
4521
  const newMessages = messages.map((m) => {
4584
4522
  if (m.role === "tool") {
4585
- if (isSyntheticSummaryToolMessage(m)) {
4523
+ if (isSyntheticSummaryMessage(m)) {
4586
4524
  return m;
4587
4525
  }
4588
4526
  const toolCallId = m.tool_call_id;
@@ -4640,8 +4578,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4640
4578
  const summaries = Array.isArray(state.summaries) ? [...state.summaries, summaryText] : [summaryText];
4641
4579
  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
4580
  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);
4581
+ const tokenCountAfter = countMessagesTokens(finalMessages);
4645
4582
  const summarizationEvent = {
4646
4583
  type: "summarization",
4647
4584
  summary: summaryText,
@@ -4692,25 +4629,6 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4692
4629
  };
4693
4630
  };
4694
4631
  }
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
4632
  var todoStatusSchema = zod.z.enum(["not-started", "in-progress", "completed", "blocked"]);
4715
4633
  var todoWriteItemSchema = zod.z.object({
4716
4634
  id: zod.z.number().int().min(1).describe("Sequential id starting from 1"),
@@ -4969,19 +4887,6 @@ function createContextTools(stateRef, opts) {
4969
4887
  }
4970
4888
 
4971
4889
  // 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
4890
  function needsSummarization(state, opts, summarizationEnabled) {
4986
4891
  if (!summarizationEnabled) {
4987
4892
  return false;
@@ -4995,30 +4900,9 @@ function needsSummarization(state, opts, summarizationEnabled) {
4995
4900
  }
4996
4901
  const maxTok = resolved.summarization.summaryTriggerTokens;
4997
4902
  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;
4903
+ const filtered = (state.messages || []).filter((message) => !isSyntheticSummaryMessage(message));
4904
+ const tokenCount = countMessagesTokens(filtered);
4905
+ return tokenCount > maxTok;
5022
4906
  } catch {
5023
4907
  return false;
5024
4908
  }
@@ -5147,13 +5031,6 @@ async function writeSummaryFactsToMemory(store, config, summary, sourceTurn) {
5147
5031
  }
5148
5032
  return store.get(config.memory.scope, { limit: config.context.lastTurnsToKeep + summary.stable_facts.length });
5149
5033
  }
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
5034
 
5158
5035
  // src/smart/index.ts
5159
5036
  function createSmartAgent(opts) {
@@ -5193,8 +5070,7 @@ function createSmartAgent(opts) {
5193
5070
  ].join("\n");
5194
5071
  function latestUserPrompt(messages) {
5195
5072
  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(" ") : "";
5073
+ return latest ? extractMessageText2(latest) : "";
5198
5074
  }
5199
5075
  async function syncMemory(state) {
5200
5076
  const query = latestUserPrompt(state.messages || []);
@@ -5234,6 +5110,18 @@ function createSmartAgent(opts) {
5234
5110
  );
5235
5111
  return { role: "system", content: sys };
5236
5112
  }
5113
+ async function trySummarize(currentState, currentRawMessages) {
5114
+ if (!summarizer) return { state: currentState, rawMessages: currentRawMessages, compressed: false };
5115
+ const delta = await summarizer(currentState);
5116
+ if (!delta || Object.keys(delta).length === 0) {
5117
+ const ctx2 = { ...currentState.ctx || {}, __summarizationExhausted: true };
5118
+ return { state: { ...currentState, ctx: ctx2 }, rawMessages: currentRawMessages, compressed: false };
5119
+ }
5120
+ const ctx = { ...currentState.ctx || {} };
5121
+ delete ctx.__summarizationExhausted;
5122
+ const updated = await persistLatestSummary(syncPlanState({ ...currentState, ...delta, ctx }));
5123
+ return { state: updated, rawMessages: [...updated.messages || currentRawMessages], compressed: true };
5124
+ }
5237
5125
  const instance = {
5238
5126
  invoke: async (input, config) => {
5239
5127
  stateRef.toolHistory = input.toolHistory;
@@ -5252,17 +5140,10 @@ function createSmartAgent(opts) {
5252
5140
  state = { ...state, messages: rawMessages };
5253
5141
  const next = summarizationEnabled ? decideBefore(state) : "agent";
5254
5142
  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
- }
5143
+ const result = await trySummarize(state, rawMessages);
5144
+ state = result.state;
5145
+ rawMessages = result.rawMessages;
5146
+ if (result.compressed) continue;
5266
5147
  }
5267
5148
  const modelMessages = buildModelMessages(state, resolved);
5268
5149
  const res = await base.invoke({ ...state, messages: modelMessages }, config);
@@ -5290,35 +5171,20 @@ function createSmartAgent(opts) {
5290
5171
  const ctx = { ...state.ctx || {} };
5291
5172
  delete ctx.__needsSummarization;
5292
5173
  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
- }
5174
+ const result = await trySummarize(state, rawMessages);
5175
+ state = result.state;
5176
+ rawMessages = result.rawMessages;
5177
+ continue;
5305
5178
  }
5306
5179
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
5307
5180
  if (opts.outputSchema && lastResult?.output != null) break;
5308
5181
  if (summarizationEnabled) {
5309
5182
  const after = decideAfter(state);
5310
5183
  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
- }
5184
+ const result = await trySummarize(state, rawMessages);
5185
+ state = result.state;
5186
+ rawMessages = result.rawMessages;
5187
+ if (result.compressed) continue;
5322
5188
  }
5323
5189
  }
5324
5190
  break;
@@ -5482,35 +5348,6 @@ async function runSmartAgentEvalHarness(params) {
5482
5348
  }
5483
5349
  return results;
5484
5350
  }
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
5351
  var Ajv = AjvModule__default.default?.default ?? AjvModule__default.default;
5515
5352
  var defaultAjv = new Ajv({ allErrors: true });
5516
5353
  defaultAjv.opts.strict = false;
@@ -7308,6 +7145,9 @@ function convertToJsonSchema(schema, strict = false) {
7308
7145
  function normalizeStrictSchema(schema) {
7309
7146
  if (!schema || typeof schema !== "object") return schema;
7310
7147
  const clone2 = { ...schema };
7148
+ if (typeof clone2.format === "string") {
7149
+ delete clone2.format;
7150
+ }
7311
7151
  if (clone2.type === "object" || clone2.properties) {
7312
7152
  if (!clone2.type) clone2.type = "object";
7313
7153
  if (clone2.properties && typeof clone2.properties === "object") {
@@ -7509,7 +7349,6 @@ exports.StructuredOutputManager = StructuredOutputManager;
7509
7349
  exports.ToolBasedStrategy = ToolBasedStrategy;
7510
7350
  exports.VertexProvider = VertexProvider;
7511
7351
  exports.agentVerdictRule = agentVerdictRule;
7512
- exports.applyTokenLimits = applyTokenLimits;
7513
7352
  exports.buildSystemPrompt = buildSystemPrompt;
7514
7353
  exports.captureSnapshot = captureSnapshot;
7515
7354
  exports.codePresenceRule = codePresenceRule;
@@ -7551,7 +7390,6 @@ exports.normalizeSmartAgentOptions = normalizeSmartAgentOptions;
7551
7390
  exports.otlpSink = otlpSink;
7552
7391
  exports.readMemoryFacts = readMemoryFacts;
7553
7392
  exports.regexRule = regexRule;
7554
- exports.renderMemoryFacts = renderMemoryFacts;
7555
7393
  exports.resolveMemoryStore = resolveMemoryStore;
7556
7394
  exports.resolveStrategy = resolveStrategy;
7557
7395
  exports.resolveToolApprovalState = resolveToolApprovalState;