aws-runtime-bridge 1.9.40 → 1.9.45

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.
Files changed (119) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +31 -4
  2. package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
  3. package/dist/adapter/AcodeSdkAdapter.js +382 -57
  4. package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
  5. package/dist/adapter/ClaudeSdkAdapter.js +1 -0
  6. package/dist/adapter/OpencodeSdkAdapter.d.ts +19 -0
  7. package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
  8. package/dist/adapter/OpencodeSdkAdapter.js +62 -0
  9. package/dist/adapter/types.d.ts +21 -6
  10. package/dist/adapter/types.d.ts.map +1 -1
  11. package/dist/adapter/types.js +10 -1
  12. package/dist/index.js +11 -0
  13. package/dist/routes/ai-sources.js +4 -1
  14. package/dist/routes/dashboard.d.ts.map +1 -1
  15. package/dist/routes/dashboard.js +1 -1
  16. package/dist/routes/file-browser.d.ts.map +1 -1
  17. package/dist/routes/file-browser.js +47 -1
  18. package/dist/routes/processes.d.ts.map +1 -1
  19. package/dist/routes/processes.js +7 -0
  20. package/dist/routes/runtime-binding.d.ts.map +1 -1
  21. package/dist/routes/runtime-binding.js +6 -3
  22. package/dist/routes/sessions.js +93 -5
  23. package/dist/routes/sub-agents.js +15 -1
  24. package/dist/routes/terminal.d.ts +15 -0
  25. package/dist/routes/terminal.d.ts.map +1 -1
  26. package/dist/routes/terminal.js +162 -5
  27. package/dist/services/acode-package.d.ts +8 -1
  28. package/dist/services/acode-package.d.ts.map +1 -1
  29. package/dist/services/acode-package.js +33 -4
  30. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  31. package/dist/services/aws-client-agent-mcp.js +11 -4
  32. package/dist/services/fileSnapshotStore.js +1 -1
  33. package/dist/services/legacy-path-migration.d.ts +3 -0
  34. package/dist/services/legacy-path-migration.d.ts.map +1 -0
  35. package/dist/services/legacy-path-migration.js +66 -0
  36. package/dist/services/lifecycle-state.d.ts.map +1 -1
  37. package/dist/services/lifecycle-state.js +1 -1
  38. package/dist/services/runtime-binding.d.ts +5 -0
  39. package/dist/services/runtime-binding.d.ts.map +1 -1
  40. package/dist/services/runtime-binding.js +33 -1
  41. package/dist/services/session-output.d.ts +7 -1
  42. package/dist/services/session-output.d.ts.map +1 -1
  43. package/dist/services/session-output.js +16 -2
  44. package/dist/services/workspace-files.d.ts +48 -0
  45. package/dist/services/workspace-files.d.ts.map +1 -1
  46. package/dist/services/workspace-files.js +285 -0
  47. package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
  48. package/package/acode/dist/built-in-file-tools.js +504 -3
  49. package/package/acode/dist/compaction.d.ts +43 -7
  50. package/package/acode/dist/compaction.d.ts.map +1 -1
  51. package/package/acode/dist/compaction.js +286 -31
  52. package/package/acode/dist/runtime.d.ts +130 -0
  53. package/package/acode/dist/runtime.d.ts.map +1 -1
  54. package/package/acode/dist/runtime.js +972 -71
  55. package/package/acode/dist/sub-agent-manager.d.ts +96 -1
  56. package/package/acode/dist/sub-agent-manager.d.ts.map +1 -1
  57. package/package/acode/dist/sub-agent-manager.js +293 -3
  58. package/package/acode/dist/sub-agent-store.d.ts +8 -1
  59. package/package/acode/dist/sub-agent-store.d.ts.map +1 -1
  60. package/package/acode/dist/sub-agent-store.js +55 -0
  61. package/package/acode/dist/sub-agent-tools.d.ts.map +1 -1
  62. package/package/acode/dist/sub-agent-tools.js +5 -4
  63. package/package/acode/dist/sub-agent-types.d.ts +4 -0
  64. package/package/acode/dist/sub-agent-types.d.ts.map +1 -1
  65. package/package/acode/dist/types.d.ts +19 -0
  66. package/package/acode/dist/types.d.ts.map +1 -1
  67. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +9 -0
  68. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  69. package/package/aws-client-agent-mcp/dist/agent-client.js +69 -10
  70. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  71. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
  72. package/package/aws-client-agent-mcp/dist/config.js +4 -0
  73. package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
  74. package/package/aws-client-agent-mcp/dist/constants.d.ts +2 -0
  75. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
  76. package/package/aws-client-agent-mcp/dist/constants.js +3 -1
  77. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
  78. package/package/aws-client-agent-mcp/dist/context-manager.d.ts +4 -1
  79. package/package/aws-client-agent-mcp/dist/context-manager.d.ts.map +1 -1
  80. package/package/aws-client-agent-mcp/dist/context-manager.js +6 -2
  81. package/package/aws-client-agent-mcp/dist/context-manager.js.map +1 -1
  82. package/package/aws-client-agent-mcp/dist/context-manager.test.js +5 -0
  83. package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +1 -1
  84. package/package/aws-client-agent-mcp/dist/http-client.d.ts +5 -0
  85. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  86. package/package/aws-client-agent-mcp/dist/http-client.js +15 -1
  87. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  88. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +102 -34
  89. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  90. package/package/aws-client-agent-mcp/dist/mcp-server.js +637 -209
  91. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  92. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +151 -51
  93. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
  94. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +7 -0
  95. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
  96. package/package/aws-client-agent-mcp/dist/mcp-tools.js +18 -0
  97. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
  98. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +32 -9
  99. package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -1
  100. package/package/aws-client-agent-mcp/dist/memory-store.js +58 -19
  101. package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -1
  102. package/package/aws-client-agent-mcp/dist/memory-tools.js +3 -3
  103. package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -1
  104. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +21 -1
  105. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +1 -1
  106. package/package/aws-client-agent-mcp/dist/message-buffer.js +47 -21
  107. package/package/aws-client-agent-mcp/dist/message-buffer.js.map +1 -1
  108. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +13 -0
  109. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +1 -1
  110. package/package/aws-client-agent-mcp/dist/server-memory-store.js +18 -0
  111. package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +1 -1
  112. package/package/aws-client-agent-mcp/dist/types.d.ts +9 -0
  113. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  114. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  115. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +34 -1
  116. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  117. package/package/aws-client-agent-mcp/dist/websocket-client.js +146 -18
  118. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  119. package/package.json +1 -1
@@ -15,8 +15,39 @@
15
15
  // ============ 常量(与 OpenCode compaction.ts 对齐) ============
16
16
  /** 压缩缓冲区:保留这么多 token 的空闲空间,避免压缩过程中溢出 */
17
17
  export const COMPACTION_BUFFER = 20_000;
18
- /** 基于实际累积 token 的触发比例:当累积量达到上下文窗口的此比例时触发压缩 */
18
+ /**
19
+ * 基础压缩触发比例(兜底默认值,仅用于 contextLimit <= 0 的异常场景)。
20
+ * 正常情况下通过 {@link getCompactionTriggerRatio} 按窗口大小动态分级。
21
+ */
19
22
  export const COMPACTION_TRIGGER_RATIO = 0.55;
23
+ /**
24
+ * 压缩触发比例的窗口分级表。
25
+ * 大窗口下压缩成本高(LLM 摘要调用 + 上下文丢失风险),应提高比例充分利用窗口;
26
+ * 小窗口下压缩成本低,可适当降低比例以及时释放空间。
27
+ *
28
+ * | 窗口大小 | 比例 |
29
+ * |---------------|-------|
30
+ * | < 32K | 0.70 |
31
+ * | 32K - 128K | 0.75 |
32
+ * | 128K - 512K | 0.80 |
33
+ * | ≥ 512K | 0.85 |
34
+ */
35
+ const COMPACTION_TRIGGER_RATIO_TIERS = [
36
+ [32_000, 0.70],
37
+ [128_000, 0.75],
38
+ [512_000, 0.80],
39
+ [Number.POSITIVE_INFINITY, 0.85],
40
+ ];
41
+ /** 按上下文窗口大小返回压缩触发比例(大窗口更高,充分利用空间)。 */
42
+ export function getCompactionTriggerRatio(contextLimit) {
43
+ if (contextLimit <= 0)
44
+ return COMPACTION_TRIGGER_RATIO;
45
+ for (const [limit, ratio] of COMPACTION_TRIGGER_RATIO_TIERS) {
46
+ if (contextLimit < limit)
47
+ return ratio;
48
+ }
49
+ return 0.85;
50
+ }
20
51
  /** Prune 保护线默认值:保留最近 PRUNE_PROTECT token 的工具输出完整。
21
52
  * 注意:实际使用时会按 contextLimit 比例调整(见 pruneToolOutputs),
22
53
  * 避免在小上下文窗口(如 60k)下保护线过高导致 prune 永不触发。
@@ -32,6 +63,57 @@ const PRUNE_PROTECT_RATIO = 0.5;
32
63
  const PRUNE_MINIMUM_RATIO = 0.1;
33
64
  /** Prune 白名单:这些工具的输出永远不会被裁剪 */
34
65
  const PRUNE_PROTECTED_TOOLS = new Set(["skill", "todo_write", "todo_read"]);
66
+ /**
67
+ * 工具重要性等级(数字越小越重要,越优先保护)。
68
+ * 用于 prune 时按重要性排序:裁剪时优先移除低重要性的工具输出。
69
+ */
70
+ const TOOL_IMPORTANCE = {
71
+ // 最高保护:文件读取和搜索类(结果包含关键上下文)
72
+ "read_file": 0,
73
+ "Read": 0,
74
+ "grep": 0,
75
+ "Grep": 0,
76
+ "glob": 0,
77
+ "Glob": 0,
78
+ "contextweaver_codebase-retrieval": 0,
79
+ // 高保护:文件写入和编辑(确认信息)
80
+ "Edit": 1,
81
+ "edit": 1,
82
+ "Write": 1,
83
+ "write": 1,
84
+ "write_file": 1,
85
+ // 中保护:网络请求
86
+ "webfetch": 2,
87
+ "WebFetch": 2,
88
+ "WebSearch": 2,
89
+ "websearch_web_search_exa": 2,
90
+ // 低保护:命令行执行(输出通常可丢弃)
91
+ "bash": 3,
92
+ "Bash": 3,
93
+ "run_terminal_command": 3,
94
+ // 最低保护:UI 操作
95
+ "playwright_browser_": 4,
96
+ };
97
+ /** 默认重要性(不在 TOOL_IMPORTANCE 中的工具) */
98
+ const DEFAULT_TOOL_IMPORTANCE = 2;
99
+ /**
100
+ * 获取工具的重要性等级。
101
+ * 支持前缀匹配(如 "playwright_browser_navigate" 匹配 "playwright_browser_")。
102
+ */
103
+ function getToolImportance(toolName) {
104
+ if (!toolName)
105
+ return DEFAULT_TOOL_IMPORTANCE;
106
+ if (TOOL_IMPORTANCE[toolName] !== undefined)
107
+ return TOOL_IMPORTANCE[toolName];
108
+ // 前缀匹配(按长度降序)
109
+ const matches = Object.keys(TOOL_IMPORTANCE)
110
+ .filter((key) => toolName.startsWith(key))
111
+ .sort((a, b) => b.length - a.length);
112
+ if (matches.length > 0) {
113
+ return TOOL_IMPORTANCE[matches[0]];
114
+ }
115
+ return DEFAULT_TOOL_IMPORTANCE;
116
+ }
35
117
  /** 默认上下文窗口上限(查找不到模型时使用) */
36
118
  const DEFAULT_CONTEXT_LIMIT = 128_000;
37
119
  /** 默认最大输出 token */
@@ -76,19 +158,31 @@ export const COMPACTION_LLM_PROMPT_TEMPLATE = [
76
158
  "",
77
159
  "Output only the summary, no preamble.",
78
160
  ].join("\n");
79
- /** token 估算系数:约 3 字符/token(混合中英文) */
80
- const ESTIMATED_CHARS_PER_TOKEN = 3;
161
+ /** 中文字符 token 估算系数:约 1.5 字符/token */
162
+ const ESTIMATION_CJK_CHARS_PER_TOKEN = 1.5;
163
+ /** ASCII 字符 token 估算系数:约 4 字符/token */
164
+ const ESTIMATION_ASCII_CHARS_PER_TOKEN = 4;
165
+ /**
166
+ * Token 估算安全填充系数。
167
+ * 参考 Claude Code 的 ×4/3 策略:本地估算始终比实际 token 数偏小,
168
+ * 乘以安全系数确保估算值 >= 实际值,避免在溢出前来不及压缩。
169
+ */
170
+ const ESTIMATION_SAFE_PADDING = 1.15;
171
+ /** 图片/文档块固定 token 估算值(参考 Claude Code 的 2000 tokens/image) */
172
+ const ESTIMATION_IMAGE_TOKENS = 2000;
173
+ /** 工具调用 JSON 结构附加开销(tool_call_id + role 等) */
174
+ const ESTIMATION_TOOL_OVERHEAD = 8;
81
175
  /**
82
- * 计算压缩触发阈值:取 min(contextLimit × 55%, hardLimit - reserved)。
176
+ * 计算压缩触发阈值:取 min(contextLimit × 动态比例, hardLimit - reserved)。
83
177
  *
84
- * - ratioBased = contextLimit × COMPACTION_TRIGGER_RATIO(基于窗口比例的软阈值)
178
+ * - ratioBased = contextLimit × getCompactionTriggerRatio(contextLimit)(按窗口大小动态分级)
85
179
  * - hardLimit = inputLimit ?? contextLimit(provider 显式 inputLimit 优先)
86
180
  * - reserved = min(COMPACTION_BUFFER, maxOutput)(buffer 不超过输出上限)
87
181
  *
88
182
  * 取两者较小者,既避免小窗口下过早触发,又避免接近硬上限时来不及压缩。
89
183
  */
90
184
  export function calculateCompactionThreshold(contextLimit, maxOutput, inputLimit) {
91
- const ratioBased = Math.floor(contextLimit * COMPACTION_TRIGGER_RATIO);
185
+ const ratioBased = Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit));
92
186
  const hardLimit = inputLimit ?? contextLimit;
93
187
  const reserved = Math.min(COMPACTION_BUFFER, maxOutput);
94
188
  const hardLimitBased = hardLimit - reserved;
@@ -172,14 +266,55 @@ export function lookupModelLimits(modelName, configOverrides) {
172
266
  }
173
267
  // ============ Token 估算 ============
174
268
  /**
175
- * 粗略估算文本的 token 数。
176
- * 不使用真实 tokenizer(太慢),基于字符数乘经验系数。
177
- * 对纯 ASCII 约 4 字符/token,对中文约 1.5-2 字符/token,混合取 3 字符/token。
269
+ * 中英文分离的文本 token 估算。
270
+ * 对纯 ASCII 约 4 字符/token,对中文约 1.5 字符/token。
271
+ * 参考:context-manager.ts 的同名方法。
272
+ */
273
+ export function estimateTextTokens(text) {
274
+ if (!text)
275
+ return 0;
276
+ let cjkCount = 0;
277
+ let asciiCount = 0;
278
+ for (const ch of text) {
279
+ if (ch > "\u00ff") {
280
+ cjkCount++;
281
+ }
282
+ else {
283
+ asciiCount++;
284
+ }
285
+ }
286
+ return Math.ceil(cjkCount / ESTIMATION_CJK_CHARS_PER_TOKEN + asciiCount / ESTIMATION_ASCII_CHARS_PER_TOKEN);
287
+ }
288
+ /**
289
+ * 粗略估算文本的 token 数(保留向后兼容)。
290
+ * 使用 estimateTextTokens 的中英文分离 + 安全填充。
178
291
  */
179
292
  export function estimateTokens(text) {
180
293
  if (!text)
181
294
  return 0;
182
- return Math.ceil(text.length / ESTIMATED_CHARS_PER_TOKEN);
295
+ // × ESTIMATION_SAFE_PADDING 确保估算始终偏大(安全侧)
296
+ // 参考 Claude Code 的 estimateMessageTokens 的 ×4/3 策略
297
+ return Math.ceil(estimateTextTokens(text) * ESTIMATION_SAFE_PADDING);
298
+ }
299
+ /**
300
+ * 块级内容 token 估算:识别 text/image_url 等不同块类型分别定价。
301
+ */
302
+ function estimateContentBlock(block) {
303
+ if (typeof block === "object" && block !== null) {
304
+ const record = block;
305
+ if (record.type === "text" && typeof record.text === "string") {
306
+ return estimateTokens(record.text);
307
+ }
308
+ if (record.type === "image_url" || record.type === "document") {
309
+ return ESTIMATION_IMAGE_TOKENS;
310
+ }
311
+ // 其他类型(tool_result 嵌套等):JSON 估算
312
+ return Math.ceil(JSON.stringify(block).length / ESTIMATION_ASCII_CHARS_PER_TOKEN);
313
+ }
314
+ if (typeof block === "string") {
315
+ return estimateTokens(block);
316
+ }
317
+ return 0;
183
318
  }
184
319
  /**
185
320
  * 估算单条消息的字节大小。
@@ -206,28 +341,25 @@ function estimateMessageBytes(message) {
206
341
  }
207
342
  /**
208
343
  * 估算整个对话的 token 数。
344
+ * 使用块级识别 + 中英文分离 + 安全填充。
209
345
  */
210
346
  export function estimateConversationTokens(messages) {
211
- let totalChars = 0;
347
+ let total = 0;
212
348
  for (const msg of messages) {
213
349
  if (typeof msg.content === "string") {
214
- totalChars += msg.content.length;
350
+ total += estimateTokens(msg.content);
215
351
  }
216
352
  else if (Array.isArray(msg.content)) {
217
353
  for (const part of msg.content) {
218
- if (typeof part === "object" && part !== null) {
219
- totalChars += JSON.stringify(part).length;
220
- }
354
+ total += estimateContentBlock(part);
221
355
  }
222
356
  }
357
+ // tool_calls 结构开销
223
358
  if (msg.tool_calls) {
224
- totalChars += JSON.stringify(msg.tool_calls).length;
225
- }
226
- if (msg.tool_call_id) {
227
- totalChars += msg.tool_call_id.length;
359
+ total += ESTIMATION_TOOL_OVERHEAD + Math.ceil(JSON.stringify(msg.tool_calls).length / ESTIMATION_ASCII_CHARS_PER_TOKEN);
228
360
  }
229
361
  }
230
- return Math.ceil(totalChars / ESTIMATED_CHARS_PER_TOKEN);
362
+ return total;
231
363
  }
232
364
  /**
233
365
  * 计算对话的 KB 大小。
@@ -251,7 +383,7 @@ export function isOverflow(messages, contextLimit, _maxOutput) {
251
383
  if (contextLimit <= 0)
252
384
  return false;
253
385
  const totalUsed = estimateConversationTokens(messages);
254
- const ratioThreshold = Math.floor(contextLimit * COMPACTION_TRIGGER_RATIO);
386
+ const ratioThreshold = Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit));
255
387
  return totalUsed >= ratioThreshold;
256
388
  }
257
389
  /**
@@ -260,7 +392,7 @@ export function isOverflow(messages, contextLimit, _maxOutput) {
260
392
  * provider 每次请求都会返回实际 token 计数(input + output),
261
393
  * 这个计数比基于文本的估算(estimateConversationTokens)要准确得多。
262
394
  *
263
- * 触发条件:累积 tokens >= contextLimit * COMPACTION_TRIGGER_RATIO
395
+ * 触发条件:累积 tokens >= contextLimit * getCompactionTriggerRatio(contextLimit)
264
396
  * 使用显式传入的 contextLimit,不依赖模型名查找表。
265
397
  *
266
398
  * @param accumulatedInput provider 实际累积的 input tokens
@@ -271,7 +403,7 @@ export function isOverflowByActualUsage(accumulatedInput, accumulatedOutput, con
271
403
  if (contextLimit <= 0)
272
404
  return false;
273
405
  const totalUsed = accumulatedInput + accumulatedOutput;
274
- const ratioThreshold = Math.floor(contextLimit * COMPACTION_TRIGGER_RATIO);
406
+ const ratioThreshold = Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit));
275
407
  return totalUsed >= ratioThreshold;
276
408
  }
277
409
  // ============ Prune 策略 ============
@@ -335,9 +467,12 @@ export function pruneToolOutputs(messages, contextLimit = DEFAULT_CONTEXT_LIMIT)
335
467
  // 按比例调整保护线和最小收益阈值
336
468
  const protectLine = Math.min(PRUNE_PROTECT, Math.floor(contextLimit * PRUNE_PROTECT_RATIO));
337
469
  const minimumGain = Math.min(PRUNE_MINIMUM, Math.floor(contextLimit * PRUNE_MINIMUM_RATIO));
338
- let total = 0;
339
- let freedTokens = 0;
340
- const toPrune = [];
470
+ // 阶段 1:收集所有候选(按重要性分组)
471
+ // 在保护线内的工具输出(最近 N 轮),无论重要性如何都保留。
472
+ // 超过保护线的输出,按重要性排序,优先裁剪低重要性的。
473
+ let accumulatedTokens = 0;
474
+ const lowImportanceCandidates = [];
475
+ const highImportanceCandidates = [];
341
476
  let turns = 0;
342
477
  // 从最新往旧遍历
343
478
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -353,10 +488,41 @@ export function pruneToolOutputs(messages, contextLimit = DEFAULT_CONTEXT_LIMIT)
353
488
  continue;
354
489
  const contentStr = typeof msg.content === "string" ? msg.content : "";
355
490
  const estimate = estimateTokens(contentStr);
356
- total += estimate;
357
- if (total > protectLine) {
358
- freedTokens += estimate;
359
- toPrune.push(msg);
491
+ accumulatedTokens += estimate;
492
+ if (accumulatedTokens > protectLine) {
493
+ // 超过保护线,按重要性分组
494
+ const importance = toolName ? getToolImportance(toolName) : DEFAULT_TOOL_IMPORTANCE;
495
+ const candidate = { msg, tokens: estimate, name: toolName ?? "" };
496
+ if (importance <= 1) {
497
+ // 高重要性(Read/Grep/Edit 等):暂不优先裁剪
498
+ highImportanceCandidates.push(candidate);
499
+ }
500
+ else {
501
+ // 低重要性(Bash/WebSearch 等):优先裁剪
502
+ lowImportanceCandidates.push(candidate);
503
+ }
504
+ }
505
+ }
506
+ // 阶段 2:按重要性排序,低重要性优先裁剪
507
+ // 低重要性按 token 数降序(先裁大的),高重要性按 token 数升序(尽量保留)
508
+ lowImportanceCandidates.sort((a, b) => b.tokens - a.tokens);
509
+ highImportanceCandidates.sort((a, b) => a.tokens - b.tokens);
510
+ const toPrune = [];
511
+ let freedTokens = 0;
512
+ // 先裁低重要性
513
+ for (const c of lowImportanceCandidates) {
514
+ if (freedTokens >= minimumGain)
515
+ break;
516
+ freedTokens += c.tokens;
517
+ toPrune.push(c.msg);
518
+ }
519
+ // 如果低重要性不够,再裁高重要性(从最小的开始)
520
+ if (freedTokens < minimumGain) {
521
+ for (const c of highImportanceCandidates) {
522
+ freedTokens += c.tokens;
523
+ toPrune.push(c.msg);
524
+ if (freedTokens >= minimumGain)
525
+ break;
360
526
  }
361
527
  }
362
528
  if (freedTokens < minimumGain) {
@@ -569,6 +735,69 @@ export async function summarizeConversation(messages, options) {
569
735
  messages.push(...keptMessages);
570
736
  return removableCount;
571
737
  }
738
+ // ============ 配对不变量保护 ============
739
+ /**
740
+ * Snip:删除最旧的一组消息(从第一个非 system 消息到下一个 user 消息之前)。
741
+ *
742
+ * 作为压缩的最终手段——当 prune 和 summarize 都无法释放足够空间时使用。
743
+ * 能确保:
744
+ * 1. 不删除 system 消息
745
+ * 2. 删除的组不跨 user 边界(保证一个完整轮次)
746
+ * 3. 删除后至少保留 1 组非 system 消息
747
+ *
748
+ * @param messages 对话消息数组(会被原地修改,通过 splice 删除)
749
+ * @returns 删除的消息数
750
+ */
751
+ export function snipOldestMessageGroup(messages) {
752
+ if (messages.length <= 1)
753
+ return 0;
754
+ // 找到第一个非 system 消息的索引
755
+ let startIdx = 0;
756
+ while (startIdx < messages.length && messages[startIdx].role === "system") {
757
+ startIdx++;
758
+ }
759
+ if (startIdx >= messages.length)
760
+ return 0;
761
+ // 找到下一个 user 消息的索引(作为删除组的结束边界)
762
+ let groupEnd = messages.length;
763
+ for (let i = startIdx + 1; i < messages.length; i++) {
764
+ if (messages[i].role === "user") {
765
+ groupEnd = i;
766
+ break;
767
+ }
768
+ }
769
+ // 不能删除全部非 system 消息(至少保留一组)
770
+ if (groupEnd >= messages.length)
771
+ return 0;
772
+ // 收集删除范围内 assistant 发起的 tool_call_id
773
+ const removedToolCallIds = new Set();
774
+ for (let i = startIdx; i < groupEnd; i++) {
775
+ const msg = messages[i];
776
+ if (msg.role === "assistant" && Array.isArray(msg.tool_calls)) {
777
+ for (const tc of msg.tool_calls) {
778
+ if (typeof tc === "object" && tc !== null && typeof tc.id === "string") {
779
+ removedToolCallIds.add(tc.id);
780
+ }
781
+ }
782
+ }
783
+ }
784
+ // 删除主组 [startIdx, groupEnd)
785
+ const removedCount = groupEnd - startIdx;
786
+ messages.splice(startIdx, removedCount);
787
+ // 清理孤儿 tool_result:其对应的 tool_call 已在上一步删除,但 tool_result 可能落在下一轮(groupEnd 之后)。
788
+ // 不能用连续 splice 扩展范围(会误删中间的 user 消息),故采用逆向遍历逐个删除孤儿 tool_result。
789
+ let orphanRemoved = 0;
790
+ if (removedToolCallIds.size > 0) {
791
+ for (let i = messages.length - 1; i >= startIdx; i--) {
792
+ const msg = messages[i];
793
+ if (msg.role === "tool" && msg.tool_call_id && removedToolCallIds.has(msg.tool_call_id)) {
794
+ messages.splice(i, 1);
795
+ orphanRemoved++;
796
+ }
797
+ }
798
+ }
799
+ return removedCount + orphanRemoved;
800
+ }
572
801
  // ============ 完整压缩流程 ============
573
802
  /**
574
803
  * 执行完整压缩流程:Prune → 若仍溢出则 Summarize。
@@ -610,7 +839,16 @@ export async function performCompaction(messages, contextLimit, maxOutput = DEFA
610
839
  });
611
840
  }
612
841
  // 阶段 2: 若仍溢出,执行 Summarize
613
- if (isOverflow(messages, contextLimit, maxOutput)) {
842
+ //
843
+ // ★ 使用 effectiveUsed(文本估算与 actual 的较大值)而非仅文本估算:
844
+ // provider 实际 token 计数往往高于基于字符的估算,若仅依赖文本估算,
845
+ // 可能因估算值低于阈值而导致"假阴性"——实际已溢出但 isOverflow 返回 false,
846
+ // summarize 被直接跳过,最终策略为 "none"。
847
+ const tokensAfterPrune = estimateConversationTokens(messages);
848
+ const postPruneEffective = options?.actualUsedTokens
849
+ ? Math.max(tokensAfterPrune, Math.max(options.actualUsedTokens, tokensBefore) - freedTokens)
850
+ : tokensAfterPrune;
851
+ if (postPruneEffective >= Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit))) {
614
852
  if (options?.onPhase) {
615
853
  options.onPhase({ phase: "summarize_start", messageCount: messages.length });
616
854
  }
@@ -629,6 +867,18 @@ export async function performCompaction(messages, contextLimit, maxOutput = DEFA
629
867
  m.content.includes("summarized by LLM"));
630
868
  usedLLM = Boolean(summaryMsg);
631
869
  }
870
+ else {
871
+ // ★ 阶段 2b: Summarize 失败降级 → Snip 最旧消息组(最终手段)
872
+ // 当 summarize 返回 0(无法找到干净边界或清理后 kept 为空),
873
+ // 尝试直接删除最旧的一组非 system 消息。
874
+ const sniped = snipOldestMessageGroup(messages);
875
+ if (sniped > 0) {
876
+ strategy = strategy === "prune" ? "prune+summarize" : "summarize";
877
+ summarizedMessages = sniped;
878
+ const tokensAfter = estimateConversationTokens(messages);
879
+ freedTokens = Math.max(freedTokens, tokensBefore - tokensAfter);
880
+ }
881
+ }
632
882
  if (options?.onPhase) {
633
883
  options.onPhase({
634
884
  phase: "summarize_end",
@@ -639,12 +889,15 @@ export async function performCompaction(messages, contextLimit, maxOutput = DEFA
639
889
  }
640
890
  const sizeAfterKB = conversationSizeKB(messages);
641
891
  const messageCountAfter = messages.length;
892
+ const tokensAfter = estimateConversationTokens(messages);
642
893
  if (strategy === "none") {
643
894
  return {
644
895
  strategy: "none",
645
896
  freedTokens: 0,
646
897
  sizeBeforeKB,
647
898
  sizeAfterKB: sizeBeforeKB,
899
+ tokensBefore,
900
+ tokensAfter,
648
901
  messageCountBefore,
649
902
  messageCountAfter,
650
903
  prunedToolMessages: 0,
@@ -656,6 +909,8 @@ export async function performCompaction(messages, contextLimit, maxOutput = DEFA
656
909
  freedTokens,
657
910
  sizeBeforeKB,
658
911
  sizeAfterKB,
912
+ tokensBefore,
913
+ tokensAfter,
659
914
  messageCountBefore,
660
915
  messageCountAfter,
661
916
  prunedToolMessages,
@@ -1,11 +1,42 @@
1
1
  import { EventEmitter } from "node:events";
2
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
+ import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
4
+ import { type JsonObject } from "./built-in-file-tools.js";
2
5
  import type { ACodeRuntimeConfig } from "./types.js";
6
+ export interface ACodeMcpConnection {
7
+ serverName: string;
8
+ client: Client;
9
+ transport: Transport;
10
+ tools: ACodeMcpTool[];
11
+ }
12
+ interface ACodeMcpTool {
13
+ kind: "mcp";
14
+ serverName: string;
15
+ toolName: string;
16
+ exposedName: string;
17
+ description?: string;
18
+ inputSchema: JsonObject;
19
+ }
3
20
  export declare class ACodeRuntime extends EventEmitter {
4
21
  private readonly config;
5
22
  private readonly hookBus;
6
23
  private initialConversation;
7
24
  private state;
8
25
  private abortController;
26
+ /**
27
+ * 正在处理中的 memory 子 agent 跟踪表。
28
+ * key = memory URI,value = subId(用于防止同一 memory 被重复委托)。
29
+ * 子 agent 完成后通过 SubAgentManager 事件回调移除对应 URI。
30
+ */
31
+ private readonly pendingMemorySubAgents;
32
+ /**
33
+ * memory 委托冷却表(「已解决/已处理」守卫,区别于 pendingMemorySubAgents 的「进行中」守卫)。
34
+ * key = memory URI,value = 冷却到期时间戳(ms)。
35
+ * 子 agent 进入终态时写入;冷却期内即使 memory 仍待处理也不再 spawn 新子任务。
36
+ * 这是切断「委托完成→复发」循环的关键:原实现只有进行中守卫,子 agent 一结束 URI 立即释放,
37
+ * 导致下一轮 poll 对 sticky 的 updating memory 再次委托。
38
+ */
39
+ private readonly memoryDelegateCooldownUntil;
9
40
  private submitQueue;
10
41
  private activeTurn;
11
42
  private abortRequested;
@@ -29,6 +60,8 @@ export declare class ACodeRuntime extends EventEmitter {
29
60
  */
30
61
  private readonly questionWaiters;
31
62
  constructor(config: ACodeRuntimeConfig);
63
+ /** 获取当前已暴露的工具名称列表(供 SubAgentManager 记录) */
64
+ getAvailableTools(): string[];
32
65
  private emitAcodeEvent;
33
66
  /**
34
67
  * 发射压缩子事件(phase 事件)到面板时间线。
@@ -168,6 +201,92 @@ export declare class ACodeRuntime extends EventEmitter {
168
201
  private readChatCompletionStream;
169
202
  private handleToolCalls;
170
203
  private callMcpToolWithTimeout;
204
+ /**
205
+ * 将子 agent 终态通知转为 poll_message 格式的合成 DirectMessage。
206
+ * 主流程:构建符合 MCP poll_message 返回格式的 JSON 字符串。
207
+ */
208
+ private static formatSubAgentCompletionAsPollResult;
209
+ /**
210
+ * 将子 agent 终态通知合并到已有的 MCP poll_message 返回结果中。
211
+ * 主流程:解析 MCP 返回的 JSON -> 将通知转为 DirectMessage 插入到 directMessages 前面 -> 重新序列化。
212
+ */
213
+ private static mergeSubAgentCompletionsIntoMcpResult;
214
+ /**
215
+ * Memory 自动委托 sub-agent 完成一轮后的外部重新检查。
216
+ *
217
+ * 查询服务端 memory 真实状态(通过 MCP 工具直接调用,非 LLM 自报),
218
+ * 判断 sub-agent 是否真正完成了处理:
219
+ * - memory_file_change:检查每条 memory 的 memory_status 是否已回到 normal
220
+ * - memory_expiration:检查每条 memory 是否已续期(expiresAt 在未来)或已清理(read 返回 null)
221
+ * - memory_cleanup:检查 get_memory_stats 中对应类型/域是否仍 exceeded
222
+ *
223
+ * 若仍有未完成项,返回 { done: false, continueMessage } 包含 "经检查,未完成对xxx的处理,请继续"
224
+ * 及具体未完成列表,由 SubAgentManager 注入同一 sub-agent 的下一轮 submit。
225
+ *
226
+ * recheck 自身出错(MCP 连接不可用、工具调用超时等)时返回 { done: true },不阻塞 sub-agent 结束。
227
+ */
228
+ private recheckMemoryDelegate;
229
+ /**
230
+ * 通过 MCP read_memory 工具读取单条 memory 记录。
231
+ * 注入 _aws_sub_agent=true 避免状态上报污染父 agent 时间线。
232
+ * 返回 null 表示 memory 明确不存在(服务端返回 null/undefined 或非对象)。
233
+ * 读取/解析异常(网络抖动、超时、服务端错误)会向上抛出,交由 recheckMemoryDelegate
234
+ * 统一判定为「未完成」,避免被误当作「已处理」。
235
+ */
236
+ private readMemoryViaMcp;
237
+ /** recheck memory_file_change:检查 memory_status 是否仍为 updating */
238
+ private recheckMemoryFileChange;
239
+ /** recheck memory_expiration:检查 expiresAt 是否仍过期 或 memory_status 是否仍为 recalling */
240
+ private recheckMemoryExpiration;
241
+ /** recheck memory_cleanup:检查 get_memory_stats 中对应类型/域是否仍 exceeded */
242
+ private recheckMemoryCleanup;
243
+ /**
244
+ * 构造 memory 自动委托子 agent 的 prompt。
245
+ * 主流程:根据 delegate 类型(过期整理/文件变更更新)生成自包含指令。
246
+ */
247
+ private buildMemoryDelegatePrompt;
248
+ /**
249
+ * 处理 poll_message 结果中的 memory 自动委托标记 (_acodeAutoDelegate)。
250
+ * 主流程:解析 MCP 返回 -> 识别标记 -> spawn 子 agent -> 返回简化结果。
251
+ * 非 ACode 运行时(无 subAgentManager)直接透传原结果,不受影响。
252
+ * 返回 null 表示全部消息已被委托,调用方应重新 poll_message 继续等待真正的消息。
253
+ */
254
+ private processMemoryAutoDelegates;
255
+ /**
256
+ * poll_message MCP 工具调用的子 agent 完成事件 race 包装器。
257
+ *
258
+ * 主流程:
259
+ * 1. 先检查 completionQueue 中是否有已完成的子 agent -> 有则直接返回合成结果(不调 MCP)
260
+ * 2. 启动 MCP poll_message 调用与 waitForAnyCompletion 的 race
261
+ * 3. 子 agent 先完成 -> 返回合成结果(MCP 调用被放弃但仍在运行,下次 poll_message 会复用 pendingPollMessage)
262
+ * 4. MCP 先返回 -> 合并新完成的子 agent 事件后返回
263
+ *
264
+ * 设计说明:
265
+ * - MCP server 的 poll_message 内部有 while(true) 永久阻塞,只在有消息时返回
266
+ * - 子 agent 完成事件由 SubAgentManager 在同进程内产生,通过 completionQueue 传递
267
+ * - 当子 agent 先完成时,MCP 调用被放弃(Promise 不再被 await),MCP server 侧的
268
+ * pendingPollMessage 仍在运行,下次 poll_message 调用会通过 pendingPollMessage 复用
269
+ */
270
+ private callPollMessageWithSubAgentRace;
271
+ /**
272
+ * 检查 poll_message 结果是否包含实际消息(directMessages 或 groupMessages 非空)。
273
+ * 用于循环中过滤空结果,确保 poll_message 只在有消息时返回。
274
+ */
275
+ private pollResultHasMessages;
276
+ /**
277
+ * 在 memory 委托消息被全部处理后,等待一段时间再重新 poll_message。
278
+ *
279
+ * 背景:MCP doPollMessage 对 updating memory 每次都返回通知(无去重),
280
+ * 而 processMemoryAutoDelegates 因 URI 已在 pendingMemorySubAgents 中而返回 null,
281
+ * 导致 while(true) 无延迟重 poll,每轮触发 handleToolCall 的 reportToolUse/reportThinking
282
+ * 状态上报,引发"思考→MCP→跳过"快速循环,最终连接丢失。
283
+ *
284
+ * 等待策略:
285
+ * 1. 固定延迟 DELEGATE_REPOLL_DELAY_MS(5s),给子 agent 时间完成 memory 更新
286
+ * 2. 可被 runtime stop 中断(通过 createRuntimeStopWaiter)
287
+ * 3. 不消费 completionQueue(下一轮 takeCompletedSubAgents 会取到)
288
+ */
289
+ private waitForDelegateRepoll;
171
290
  /**
172
291
  * Build a one-shot waiter that rejects long-running MCP calls when the runtime stops.
173
292
  * Main flow: register a stop callback -> race it with the SDK call -> remove it after either side settles.
@@ -180,6 +299,16 @@ export declare class ACodeRuntime extends EventEmitter {
180
299
  private notifyRuntimeStop;
181
300
  private appendSyntheticMultimodalUserMessage;
182
301
  private appendToolFailureResult;
302
+ /**
303
+ * 为子 agent 过滤共享 MCP 连接:只保留 memory 工具。
304
+ *
305
+ * 原 MCP server 进程通过 AWS_SUB_AGENT=true 限制子 agent 只能调用 memory 工具,
306
+ * 共享连接后绕过了该机制。此方法在 ACode runtime 层重新施加限制:
307
+ * - 复用同一 client/transport(不创建新连接)
308
+ * - 仅暴露 MEMORY_TOOL_NAMES 中的工具
309
+ * - 防止子 agent 调用 poll_message(与父 agent 冲突)、send_group 等
310
+ */
311
+ private filterSharedMcpConnectionsForSubAgent;
183
312
  private connectMcpServers;
184
313
  private createMcpTransport;
185
314
  /**
@@ -196,4 +325,5 @@ export declare class ACodeRuntime extends EventEmitter {
196
325
  private extractProfileFromToolResult;
197
326
  private disconnectMcpServers;
198
327
  }
328
+ export {};
199
329
  //# sourceMappingURL=runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA+C3C,OAAO,KAAK,EAOV,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AA4oCpB,qBAAa,YAAa,SAAQ,YAAY;IAgEhC,OAAO,CAAC,QAAQ,CAAC,MAAM;IA/DnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,KAAK,CAsBX;IAEF,OAAO,CAAC,eAAe,CAAgC;IAEvD,OAAO,CAAC,WAAW,CAAoC;IAEvD,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,4BAA4B;IAC5B,OAAO,CAAC,oBAAoB,CAA+C;IAC3E,0DAA0D;IAC1D,OAAO,CAAC,SAAS,CAA+B;IAChD,mCAAmC;IACnC,OAAO,CAAC,aAAa,CAAsB;IAC3C,oCAAoC;IACpC,OAAO,CAAC,iBAAiB,CAA8C;IACvE,uBAAuB;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAO;IAExD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAOlB;gBAEe,MAAM,EAAE,kBAAkB;IAevD,OAAO,CAAC,cAAc;IAatB;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;IAgB3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAqB7B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsK5B;;;;;;;;;;OAUG;YACW,aAAa;IA+C3B;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAU5B;;;;;;;;OAQG;YACW,aAAa;IAuC3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAqD/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;;;OAIG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC,OAAO,CAAC,gBAAgB;YAIV,aAAa;IAgP3B,oDAAoD;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAuBhC;;;;;;;;;OASG;IACH,OAAO,CAAC,qBAAqB;IA4E7B;;;OAGG;IACH,oBAAoB,CAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO;IAeV;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAQhC,uCAAuC;IACjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4C3B,OAAO,CAAC,kBAAkB;YAaZ,YAAY;IA4K1B;;;;;;;;;;;;;;;;;OAiBG;YACW,4BAA4B;YAwE5B,qBAAqB;YA2TrB,wBAAwB;YAsFxB,eAAe;YAwSf,sBAAsB;IA6CpC;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAiC/B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;YAQX,oCAAoC;IA0DlD,OAAO,CAAC,uBAAuB;YA0BjB,iBAAiB;IA2C/B,OAAO,CAAC,kBAAkB;IA2B1B;;;;;OAKG;YACW,kBAAkB;IAgChC;;;OAGG;IACH,OAAO,CAAC,4BAA4B;YA4BtB,oBAAoB;CAiBnC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}