@xagent-ai/cli 1.2.2 → 1.3.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.
Files changed (602) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/release.yml +76 -0
  4. package/.github/workflows/ci.yml +75 -0
  5. package/.github/workflows/release.yml +103 -0
  6. package/.gitmodules +3 -3
  7. package/README.md +326 -280
  8. package/README_CN.md +325 -279
  9. package/dist/agents.d.ts.map +1 -1
  10. package/dist/agents.js +7 -3
  11. package/dist/agents.js.map +1 -1
  12. package/dist/ai-client/factory.d.ts +40 -0
  13. package/dist/ai-client/factory.d.ts.map +1 -0
  14. package/dist/ai-client/factory.js +100 -0
  15. package/dist/ai-client/factory.js.map +1 -0
  16. package/dist/ai-client/index.d.ts +20 -0
  17. package/dist/ai-client/index.d.ts.map +1 -0
  18. package/dist/ai-client/index.js +49 -0
  19. package/dist/ai-client/index.js.map +1 -0
  20. package/dist/ai-client/providers/anthropic.d.ts +57 -0
  21. package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
  22. package/dist/ai-client/providers/anthropic.js +406 -0
  23. package/dist/ai-client/providers/anthropic.js.map +1 -0
  24. package/dist/ai-client/providers/openai.d.ts +57 -0
  25. package/dist/ai-client/providers/openai.d.ts.map +1 -0
  26. package/dist/ai-client/providers/openai.js +290 -0
  27. package/dist/ai-client/providers/openai.js.map +1 -0
  28. package/dist/ai-client/providers/remote.d.ts +110 -0
  29. package/dist/ai-client/providers/remote.d.ts.map +1 -0
  30. package/dist/ai-client/providers/remote.js +352 -0
  31. package/dist/ai-client/providers/remote.js.map +1 -0
  32. package/dist/ai-client/registry.d.ts +51 -0
  33. package/dist/ai-client/registry.d.ts.map +1 -0
  34. package/dist/ai-client/registry.js +81 -0
  35. package/dist/ai-client/registry.js.map +1 -0
  36. package/dist/ai-client/types.d.ts +274 -0
  37. package/dist/ai-client/types.d.ts.map +1 -0
  38. package/dist/ai-client/types.js +90 -0
  39. package/dist/ai-client/types.js.map +1 -0
  40. package/dist/ai-client-factory.d.ts +62 -0
  41. package/dist/ai-client-factory.d.ts.map +1 -0
  42. package/dist/ai-client-factory.js +157 -0
  43. package/dist/ai-client-factory.js.map +1 -0
  44. package/dist/auth.d.ts +23 -1
  45. package/dist/auth.d.ts.map +1 -1
  46. package/dist/auth.js +164 -174
  47. package/dist/auth.js.map +1 -1
  48. package/dist/cancellation.d.ts +5 -4
  49. package/dist/cancellation.d.ts.map +1 -1
  50. package/dist/cancellation.js +53 -32
  51. package/dist/cancellation.js.map +1 -1
  52. package/dist/checkpoint.d.ts +2 -1
  53. package/dist/checkpoint.d.ts.map +1 -1
  54. package/dist/checkpoint.js +39 -6
  55. package/dist/checkpoint.js.map +1 -1
  56. package/dist/cli.js +742 -29
  57. package/dist/cli.js.map +1 -1
  58. package/dist/config.d.ts +10 -4
  59. package/dist/config.d.ts.map +1 -1
  60. package/dist/config.js +62 -25
  61. package/dist/config.js.map +1 -1
  62. package/dist/context-compressor.d.ts +82 -18
  63. package/dist/context-compressor.d.ts.map +1 -1
  64. package/dist/context-compressor.js +718 -154
  65. package/dist/context-compressor.js.map +1 -1
  66. package/dist/conversation.d.ts +1 -1
  67. package/dist/conversation.d.ts.map +1 -1
  68. package/dist/conversation.js +8 -7
  69. package/dist/conversation.js.map +1 -1
  70. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
  71. package/dist/gui-subagent/action-parser/actionParser.js +6 -4
  72. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  73. package/dist/gui-subagent/agent/gui-agent.d.ts +39 -2
  74. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  75. package/dist/gui-subagent/agent/gui-agent.js +189 -74
  76. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  77. package/dist/gui-subagent/index.d.ts +23 -1
  78. package/dist/gui-subagent/index.d.ts.map +1 -1
  79. package/dist/gui-subagent/index.js +6 -0
  80. package/dist/gui-subagent/index.js.map +1 -1
  81. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
  82. package/dist/gui-subagent/operator/base-operator.js +0 -1
  83. package/dist/gui-subagent/operator/base-operator.js.map +1 -1
  84. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  85. package/dist/gui-subagent/operator/computer-operator.js +31 -8
  86. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  87. package/dist/gui-subagent/types/actions.d.ts +1 -1
  88. package/dist/gui-subagent/types/actions.d.ts.map +1 -1
  89. package/dist/gui-subagent/types/actions.js +0 -1
  90. package/dist/gui-subagent/types/actions.js.map +1 -1
  91. package/dist/gui-subagent/types/operator.d.ts +1 -1
  92. package/dist/gui-subagent/types/operator.d.ts.map +1 -1
  93. package/dist/index.d.ts +1 -2
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +1 -2
  96. package/dist/index.js.map +1 -1
  97. package/dist/input-processor.d.ts.map +1 -1
  98. package/dist/input-processor.js +8 -5
  99. package/dist/input-processor.js.map +1 -1
  100. package/dist/logger.d.ts.map +1 -1
  101. package/dist/logger.js +1 -1
  102. package/dist/logger.js.map +1 -1
  103. package/dist/mcp.d.ts +7 -1
  104. package/dist/mcp.d.ts.map +1 -1
  105. package/dist/mcp.js +157 -49
  106. package/dist/mcp.js.map +1 -1
  107. package/dist/memory.d.ts.map +1 -1
  108. package/dist/memory.js +3 -3
  109. package/dist/memory.js.map +1 -1
  110. package/dist/output-util.d.ts +27 -0
  111. package/dist/output-util.d.ts.map +1 -0
  112. package/dist/output-util.js +74 -0
  113. package/dist/output-util.js.map +1 -0
  114. package/dist/retry.js +1 -1
  115. package/dist/retry.js.map +1 -1
  116. package/dist/ripgrep.d.ts +29 -0
  117. package/dist/ripgrep.d.ts.map +1 -0
  118. package/dist/ripgrep.js +294 -0
  119. package/dist/ripgrep.js.map +1 -0
  120. package/dist/sdk-output-adapter.d.ts +34 -1
  121. package/dist/sdk-output-adapter.d.ts.map +1 -1
  122. package/dist/sdk-output-adapter.js +67 -2
  123. package/dist/sdk-output-adapter.js.map +1 -1
  124. package/dist/sdk-session.d.ts.map +1 -1
  125. package/dist/sdk-session.js +2 -0
  126. package/dist/sdk-session.js.map +1 -1
  127. package/dist/session-manager.js +3 -3
  128. package/dist/session-manager.js.map +1 -1
  129. package/dist/session.d.ts +116 -6
  130. package/dist/session.d.ts.map +1 -1
  131. package/dist/session.js +1416 -448
  132. package/dist/session.js.map +1 -1
  133. package/dist/shell.d.ts +33 -0
  134. package/dist/shell.d.ts.map +1 -0
  135. package/dist/shell.js +126 -0
  136. package/dist/shell.js.map +1 -0
  137. package/dist/skill-installer.d.ts +38 -0
  138. package/dist/skill-installer.d.ts.map +1 -0
  139. package/dist/skill-installer.js +447 -0
  140. package/dist/skill-installer.js.map +1 -0
  141. package/dist/skill-invoker.d.ts +8 -2
  142. package/dist/skill-invoker.d.ts.map +1 -1
  143. package/dist/skill-invoker.js +36 -15
  144. package/dist/skill-invoker.js.map +1 -1
  145. package/dist/skill-loader.d.ts +8 -3
  146. package/dist/skill-loader.d.ts.map +1 -1
  147. package/dist/skill-loader.js +51 -48
  148. package/dist/skill-loader.js.map +1 -1
  149. package/dist/skill-manager.d.ts +85 -0
  150. package/dist/skill-manager.d.ts.map +1 -0
  151. package/dist/skill-manager.js +341 -0
  152. package/dist/skill-manager.js.map +1 -0
  153. package/dist/slash-commands.d.ts +39 -2
  154. package/dist/slash-commands.d.ts.map +1 -1
  155. package/dist/slash-commands.js +934 -305
  156. package/dist/slash-commands.js.map +1 -1
  157. package/dist/smart-approval.d.ts +20 -1
  158. package/dist/smart-approval.d.ts.map +1 -1
  159. package/dist/smart-approval.js +125 -56
  160. package/dist/smart-approval.js.map +1 -1
  161. package/dist/system-prompt-generator.d.ts +6 -0
  162. package/dist/system-prompt-generator.d.ts.map +1 -1
  163. package/dist/system-prompt-generator.js +86 -36
  164. package/dist/system-prompt-generator.js.map +1 -1
  165. package/dist/terminal.d.ts +28 -0
  166. package/dist/terminal.d.ts.map +1 -0
  167. package/dist/terminal.js +82 -0
  168. package/dist/terminal.js.map +1 -0
  169. package/dist/theme.d.ts.map +1 -1
  170. package/dist/theme.js +8 -7
  171. package/dist/theme.js.map +1 -1
  172. package/dist/tools.d.ts +38 -7
  173. package/dist/tools.d.ts.map +1 -1
  174. package/dist/tools.js +1249 -617
  175. package/dist/tools.js.map +1 -1
  176. package/dist/truncate.d.ts +55 -0
  177. package/dist/truncate.d.ts.map +1 -0
  178. package/dist/truncate.js +130 -0
  179. package/dist/truncate.js.map +1 -0
  180. package/dist/types.d.ts +84 -9
  181. package/dist/types.d.ts.map +1 -1
  182. package/dist/types.js +49 -0
  183. package/dist/types.js.map +1 -1
  184. package/dist/update.d.ts.map +1 -1
  185. package/dist/update.js +28 -36
  186. package/dist/update.js.map +1 -1
  187. package/dist/workflow.d.ts +5 -1
  188. package/dist/workflow.d.ts.map +1 -1
  189. package/dist/workflow.js +61 -49
  190. package/dist/workflow.js.map +1 -1
  191. package/docs/architecture/mcp-integration-guide.md +304 -194
  192. package/docs/architecture/overview.md +169 -169
  193. package/docs/architecture/tool-system-design.md +134 -134
  194. package/docs/cli/commands.md +349 -238
  195. package/docs/smart-mode.md +281 -281
  196. package/docs/third-party-models.md +440 -439
  197. package/find-skills/SKILL.md +133 -0
  198. package/package.json +91 -90
  199. package/scripts/install-ripgrep.js +241 -0
  200. package/src/agents.ts +7 -3
  201. package/src/ai-client/factory.ts +116 -0
  202. package/src/ai-client/index.ts +61 -0
  203. package/src/ai-client/providers/anthropic.ts +475 -0
  204. package/src/ai-client/providers/openai.ts +348 -0
  205. package/src/ai-client/providers/remote.ts +439 -0
  206. package/src/ai-client/registry.ts +97 -0
  207. package/src/ai-client/types.ts +364 -0
  208. package/src/ai-client-factory.ts +204 -0
  209. package/src/auth.ts +661 -614
  210. package/src/cancellation.ts +202 -176
  211. package/src/checkpoint.ts +255 -219
  212. package/src/cli.ts +1523 -743
  213. package/src/config.ts +341 -297
  214. package/src/context-compressor.ts +987 -290
  215. package/src/conversation.ts +290 -288
  216. package/src/gui-subagent/action-parser/actionParser.ts +318 -315
  217. package/src/gui-subagent/action-parser/constants.ts +14 -14
  218. package/src/gui-subagent/action-parser/index.ts +8 -8
  219. package/src/gui-subagent/action-parser/types.ts +31 -31
  220. package/src/gui-subagent/agent/gui-agent.ts +1234 -1089
  221. package/src/gui-subagent/agent/index.ts +5 -5
  222. package/src/gui-subagent/index.ts +185 -163
  223. package/src/gui-subagent/operator/base-operator.ts +244 -245
  224. package/src/gui-subagent/operator/computer-operator.ts +541 -520
  225. package/src/gui-subagent/operator/index.ts +6 -6
  226. package/src/gui-subagent/types/actions.ts +260 -262
  227. package/src/gui-subagent/types/index.ts +6 -6
  228. package/src/gui-subagent/types/operator.ts +106 -106
  229. package/src/gui-subagent/utils.ts +51 -51
  230. package/src/index.ts +17 -18
  231. package/src/input-processor.ts +8 -5
  232. package/src/logger.ts +436 -438
  233. package/src/mcp.ts +793 -682
  234. package/src/memory.ts +343 -344
  235. package/src/output-util.ts +80 -0
  236. package/src/retry.ts +1 -1
  237. package/src/ripgrep.ts +370 -0
  238. package/src/sdk-output-adapter.ts +842 -0
  239. package/src/sdk-session.ts +62 -0
  240. package/src/session-manager.ts +308 -308
  241. package/src/session.ts +1775 -573
  242. package/src/shell.ts +134 -0
  243. package/src/skill-installer.ts +518 -0
  244. package/src/skill-invoker.ts +959 -935
  245. package/src/skill-loader.ts +501 -496
  246. package/src/skill-manager.ts +385 -0
  247. package/src/slash-commands.ts +2189 -1389
  248. package/src/smart-approval.ts +193 -74
  249. package/src/system-prompt-generator.ts +91 -36
  250. package/src/terminal.ts +96 -0
  251. package/src/theme.ts +739 -738
  252. package/src/tools.ts +1790 -931
  253. package/src/truncate.ts +173 -0
  254. package/src/types.ts +337 -198
  255. package/src/update.ts +33 -40
  256. package/src/workflow.ts +521 -508
  257. package/test/cli-launch.test.ts +279 -0
  258. package/tsconfig.json +22 -22
  259. package/vitest.config.ts +21 -19
  260. package/dist/ai-client.d.ts +0 -86
  261. package/dist/ai-client.d.ts.map +0 -1
  262. package/dist/ai-client.js +0 -1372
  263. package/dist/ai-client.js.map +0 -1
  264. package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
  265. package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
  266. package/dist/gui-subagent/operator/browser-operator.js +0 -306
  267. package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
  268. package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
  269. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
  270. package/dist/gui-subagent/operator/desktop-operator.js +0 -527
  271. package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
  272. package/dist/hook.d.ts +0 -73
  273. package/dist/hook.d.ts.map +0 -1
  274. package/dist/hook.js +0 -156
  275. package/dist/hook.js.map +0 -1
  276. package/dist/input-history.d.ts +0 -24
  277. package/dist/input-history.d.ts.map +0 -1
  278. package/dist/input-history.js +0 -94
  279. package/dist/input-history.js.map +0 -1
  280. package/dist/keyboard-manager.d.ts +0 -151
  281. package/dist/keyboard-manager.d.ts.map +0 -1
  282. package/dist/keyboard-manager.js +0 -396
  283. package/dist/keyboard-manager.js.map +0 -1
  284. package/dist/print-system-prompt.d.ts +0 -2
  285. package/dist/print-system-prompt.d.ts.map +0 -1
  286. package/dist/print-system-prompt.js +0 -40
  287. package/dist/print-system-prompt.js.map +0 -1
  288. package/dist/remote-ai-client.d.ts +0 -104
  289. package/dist/remote-ai-client.d.ts.map +0 -1
  290. package/dist/remote-ai-client.js +0 -552
  291. package/dist/remote-ai-client.js.map +0 -1
  292. package/dist/sdk-session-v2.d.ts +0 -13
  293. package/dist/sdk-session-v2.d.ts.map +0 -1
  294. package/dist/sdk-session-v2.js +0 -46
  295. package/dist/sdk-session-v2.js.map +0 -1
  296. package/dist/test-boundary-conditions.d.ts.map +0 -1
  297. package/dist/test-boundary-conditions.js.map +0 -1
  298. package/dist/test-cancellation-fix.d.ts.map +0 -1
  299. package/dist/test-cancellation-fix.js.map +0 -1
  300. package/dist/test-input-history.d.ts.map +0 -1
  301. package/dist/test-input-history.js.map +0 -1
  302. package/dist/test-interaction-flow.d.ts.map +0 -1
  303. package/dist/test-interaction-flow.js.map +0 -1
  304. package/dist/test-quick.d.ts.map +0 -1
  305. package/dist/test-quick.js.map +0 -1
  306. package/dist/test-user-interaction.d.ts.map +0 -1
  307. package/dist/test-user-interaction.js.map +0 -1
  308. package/dist/tools/edit-diff.d.ts +0 -32
  309. package/dist/tools/edit-diff.d.ts.map +0 -1
  310. package/dist/tools/edit-diff.js +0 -185
  311. package/dist/tools/edit-diff.js.map +0 -1
  312. package/dist/tools/edit.d.ts +0 -11
  313. package/dist/tools/edit.d.ts.map +0 -1
  314. package/dist/tools/edit.js +0 -129
  315. package/dist/tools/edit.js.map +0 -1
  316. package/dist/unified-session.d.ts +0 -42
  317. package/dist/unified-session.d.ts.map +0 -1
  318. package/dist/unified-session.js +0 -271
  319. package/dist/unified-session.js.map +0 -1
  320. package/skills/.claude-plugin/marketplace.json +0 -45
  321. package/skills/README.md +0 -94
  322. package/skills/THIRD_PARTY_NOTICES.md +0 -405
  323. package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
  324. package/skills/skills/algorithmic-art/SKILL.md +0 -405
  325. package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
  326. package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
  327. package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
  328. package/skills/skills/brand-guidelines/SKILL.md +0 -73
  329. package/skills/skills/canvas-design/LICENSE.txt +0 -202
  330. package/skills/skills/canvas-design/SKILL.md +0 -130
  331. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  332. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  333. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  334. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  335. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  336. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  337. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  338. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  339. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  340. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  341. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  342. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  343. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  344. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  345. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  346. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  347. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  348. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  349. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  350. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  351. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  352. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  353. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  354. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  355. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  356. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  357. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  358. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  359. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  360. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  361. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  362. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  363. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  364. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  365. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  366. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  367. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  368. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  369. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  370. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  371. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  372. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  373. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  374. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  375. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  376. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  377. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  378. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  379. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  380. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  381. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  382. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  383. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  384. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  385. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  386. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  387. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  388. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  389. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  390. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  391. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  392. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  393. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  394. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  395. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  396. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  397. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  398. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  399. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  400. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  401. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  402. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  403. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  404. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  405. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  406. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  407. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  408. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  409. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  410. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  411. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  412. package/skills/skills/doc-coauthoring/SKILL.md +0 -375
  413. package/skills/skills/docx/LICENSE.txt +0 -30
  414. package/skills/skills/docx/SKILL.md +0 -197
  415. package/skills/skills/docx/docx-js.md +0 -350
  416. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  417. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  418. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  419. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  420. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  421. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  422. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  423. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  424. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  425. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  426. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  427. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  428. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  429. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  430. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  431. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  432. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  433. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  434. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  435. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  436. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  437. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  438. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  439. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  440. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  441. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  442. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  443. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  444. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  445. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  446. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  447. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  448. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  449. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  450. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  451. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  452. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  453. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  454. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  455. package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
  456. package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
  457. package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
  458. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  459. package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
  460. package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  461. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  462. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  463. package/skills/skills/docx/ooxml.md +0 -610
  464. package/skills/skills/docx/scripts/__init__.py +0 -1
  465. package/skills/skills/docx/scripts/document.py +0 -1276
  466. package/skills/skills/docx/scripts/templates/comments.xml +0 -3
  467. package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  468. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  469. package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
  470. package/skills/skills/docx/scripts/templates/people.xml +0 -3
  471. package/skills/skills/docx/scripts/utilities.py +0 -374
  472. package/skills/skills/frontend-design/LICENSE.txt +0 -177
  473. package/skills/skills/frontend-design/SKILL.md +0 -42
  474. package/skills/skills/internal-comms/LICENSE.txt +0 -202
  475. package/skills/skills/internal-comms/SKILL.md +0 -32
  476. package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
  477. package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
  478. package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
  479. package/skills/skills/internal-comms/examples/general-comms.md +0 -16
  480. package/skills/skills/mcp-builder/LICENSE.txt +0 -202
  481. package/skills/skills/mcp-builder/SKILL.md +0 -236
  482. package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
  483. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  484. package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  485. package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  486. package/skills/skills/mcp-builder/scripts/connections.py +0 -151
  487. package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
  488. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  489. package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
  490. package/skills/skills/pdf/LICENSE.txt +0 -30
  491. package/skills/skills/pdf/SKILL.md +0 -294
  492. package/skills/skills/pdf/forms.md +0 -205
  493. package/skills/skills/pdf/reference.md +0 -612
  494. package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  495. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  496. package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
  497. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  498. package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
  499. package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
  500. package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  501. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  502. package/skills/skills/pptx/LICENSE.txt +0 -30
  503. package/skills/skills/pptx/SKILL.md +0 -484
  504. package/skills/skills/pptx/html2pptx.md +0 -625
  505. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  506. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  507. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  508. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  509. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  510. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  511. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  512. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  513. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  514. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  515. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  516. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  517. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  518. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  519. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  520. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  521. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  522. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  523. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  524. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  525. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  526. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  527. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  528. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  529. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  530. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  531. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  532. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  533. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  534. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  535. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  536. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  537. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  538. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  539. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  540. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  541. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  542. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  543. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  544. package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
  545. package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
  546. package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
  547. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  548. package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  549. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  550. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  551. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  552. package/skills/skills/pptx/ooxml.md +0 -427
  553. package/skills/skills/pptx/scripts/html2pptx.js +0 -979
  554. package/skills/skills/pptx/scripts/inventory.py +0 -1020
  555. package/skills/skills/pptx/scripts/rearrange.py +0 -231
  556. package/skills/skills/pptx/scripts/replace.py +0 -385
  557. package/skills/skills/pptx/scripts/thumbnail.py +0 -450
  558. package/skills/skills/skill-creator/LICENSE.txt +0 -202
  559. package/skills/skills/skill-creator/SKILL.md +0 -356
  560. package/skills/skills/skill-creator/references/output-patterns.md +0 -82
  561. package/skills/skills/skill-creator/references/workflows.md +0 -28
  562. package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
  563. package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
  564. package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
  565. package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
  566. package/skills/skills/slack-gif-creator/SKILL.md +0 -254
  567. package/skills/skills/slack-gif-creator/core/easing.py +0 -234
  568. package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
  569. package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
  570. package/skills/skills/slack-gif-creator/core/validators.py +0 -136
  571. package/skills/skills/slack-gif-creator/requirements.txt +0 -4
  572. package/skills/skills/theme-factory/LICENSE.txt +0 -202
  573. package/skills/skills/theme-factory/SKILL.md +0 -59
  574. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  575. package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
  576. package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
  577. package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
  578. package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
  579. package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
  580. package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
  581. package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
  582. package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
  583. package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
  584. package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
  585. package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
  586. package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
  587. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  588. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  589. package/skills/skills/webapp-testing/LICENSE.txt +0 -202
  590. package/skills/skills/webapp-testing/SKILL.md +0 -96
  591. package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
  592. package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
  593. package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
  594. package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
  595. package/skills/skills/xlsx/LICENSE.txt +0 -30
  596. package/skills/skills/xlsx/SKILL.md +0 -289
  597. package/skills/skills/xlsx/recalc.py +0 -178
  598. package/skills/spec/agent-skills-spec.md +0 -3
  599. package/skills/template/SKILL.md +0 -6
  600. package/src/ai-client.ts +0 -1560
  601. package/src/remote-ai-client.ts +0 -664
  602. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
@@ -1,112 +1,538 @@
1
- import { AIClient } from './ai-client.js';
1
+ import { getCancellationManager } from './cancellation.js';
2
+ import { createAIClient } from './ai-client-factory.js';
3
+ import { output as logOutput } from './output-util.js';
4
+ /**
5
+ * Model context window sizes (in tokens)
6
+ * Add models here as needed
7
+ */
8
+ const MODEL_CONTEXT_WINDOWS = {
9
+ // OpenAI
10
+ 'gpt-4': 8192,
11
+ 'gpt-4-32k': 32768,
12
+ 'gpt-4-turbo': 128000,
13
+ 'gpt-4o': 128000,
14
+ 'gpt-4o-mini': 128000,
15
+ 'gpt-5': 200000,
16
+ // Anthropic Claude
17
+ 'claude-sonnet-4-20250514': 200000,
18
+ 'claude-sonnet-4': 200000,
19
+ 'claude-opus-4': 200000,
20
+ 'claude-3-5-sonnet': 200000,
21
+ 'claude-3-opus': 200000,
22
+ // Google
23
+ 'gemini-pro': 32768,
24
+ 'gemini-ultra': 1000000,
25
+ // DeepSeek
26
+ 'deepseek-chat': 128000,
27
+ 'deepseek-coder': 128000,
28
+ 'deepseek-reasoner': 128000,
29
+ // Qwen (Tongyi Qianwen)
30
+ 'qwen-max': 32768,
31
+ 'qwen-plus': 64000,
32
+ 'qwen-turbo': 8000,
33
+ 'qwen-long': 100000,
34
+ 'qwen-vl-max': 128000,
35
+ 'Qwen3-Coder': 32768,
36
+ // Zhipu AI (GLM)
37
+ 'glm-4': 128000,
38
+ 'glm-4-plus': 128000,
39
+ 'glm-4-air': 128000,
40
+ 'glm-4.7': 200000,
41
+ 'glm-5': 200000,
42
+ // MiniMax
43
+ 'MiniMax-M2': 200000,
44
+ 'MiniMax-M2.1': 200000,
45
+ 'MiniMax-M2.5': 200000,
46
+ // Moonshot (Kimi)
47
+ 'moonshot-v1-8k': 8192,
48
+ 'moonshot-v1-32k': 32768,
49
+ 'moonshot-v1-128k': 131072,
50
+ // Doubao
51
+ 'doubao-seed-1-8-251228': 256000,
52
+ 'doubao-1-5-ui-tars-250428': 256000,
53
+ // Default fallback
54
+ 'default': 200000
55
+ };
56
+ // Compression ratio constants - easier to tune and maintain
57
+ const COMPRESSION_RATIO = {
58
+ RESERVE_RATIO: 0.50, // Reserve 50% of context window for system prompt and recent messages
59
+ SUMMARY_THRESHOLD_RATIO: 0.15, // Use 15% of available space for summary
60
+ MAX_TOKENS_RATIO: 0.8, // Use 80% of reserved tokens for compression
61
+ SUMMARY_MAX_TOKENS_RATIO: 0.5, // Use 50% of reserved tokens for summary
62
+ MIN_SUMMARY_TOKENS: 800 // Minimum tokens for summary
63
+ };
64
+ /**
65
+ * Get the context window for a model
66
+ */
67
+ export function getModelContextWindow(modelName) {
68
+ if (!modelName)
69
+ return MODEL_CONTEXT_WINDOWS['default'];
70
+ // Try exact match first
71
+ if (MODEL_CONTEXT_WINDOWS[modelName]) {
72
+ return MODEL_CONTEXT_WINDOWS[modelName];
73
+ }
74
+ // Try case-insensitive match
75
+ const lowerName = modelName.toLowerCase();
76
+ for (const [key, value] of Object.entries(MODEL_CONTEXT_WINDOWS)) {
77
+ if (key.toLowerCase() === lowerName) {
78
+ return value;
79
+ }
80
+ }
81
+ // Try partial match (e.g., "claude" matches "claude-sonnet-4")
82
+ for (const [key, value] of Object.entries(MODEL_CONTEXT_WINDOWS)) {
83
+ if (lowerName.includes(key.toLowerCase()) || key.toLowerCase().includes(lowerName)) {
84
+ return value;
85
+ }
86
+ }
87
+ return MODEL_CONTEXT_WINDOWS['default'];
88
+ }
89
+ const SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.
90
+
91
+ Use this EXACT format:
92
+
93
+ ## Goal
94
+ [What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]
95
+
96
+ ## Constraints & Preferences
97
+ - [Any constraints, preferences, or requirements mentioned by user]
98
+ - [Or "(none)" if none were mentioned]
99
+
100
+ ## Progress
101
+ ### Done
102
+ - [x] [Completed tasks/changes]
103
+
104
+ ### In Progress
105
+ - [ ] [Current work]
106
+
107
+ ### Blocked
108
+ - [Issues preventing progress, if any]
109
+
110
+ ## Key Decisions
111
+ - **[Decision]**: [Brief rationale]
112
+
113
+ ## Next Steps
114
+ 1. [Ordered list of what should happen next]
115
+
116
+ ## Critical Context
117
+
118
+ ### Key Files & Code
119
+ - [File path]: [Brief description of key content/structure]
120
+ - [File path]: [Brief description of key content/structure]
121
+
122
+ ### Execution Results
123
+ - **Files**: [What files were read, written, or edited and key findings]
124
+ - **Commands**: [Key commands run and their outputs]
125
+ - **Search/Analysis**: [Key findings from code search or analysis]
126
+
127
+ ### Project Context
128
+ - [Architecture patterns identified]
129
+ - [Important configurations]
130
+ - [Dependencies or libraries relevant to the task]
131
+
132
+ Keep each section concise. Preserve exact file paths, function names, and error messages.`;
133
+ const UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.
134
+
135
+ Update the existing structured summary with new information. RULES:
136
+ - PRESERVE all existing information from the previous summary
137
+ - ADD new progress, decisions, and context from the new messages
138
+ - UPDATE the Progress section: move items from "In Progress" to "Done" when completed
139
+ - UPDATE "Next Steps" based on what was accomplished
140
+ - PRESERVE exact file paths, function names, and error messages
141
+ - If something is no longer relevant, you may remove it
142
+
143
+ Use this EXACT format:
144
+
145
+ ## Goal
146
+ [Preserve existing goals, add new ones if the task expanded]
147
+
148
+ ## Constraints & Preferences
149
+ - [Preserve existing, add new ones discovered]
150
+
151
+ ## Progress
152
+ ### Done
153
+ - [x] [Include previously done items AND newly completed items]
154
+
155
+ ### In Progress
156
+ - [ ] [Current work - update based on progress]
157
+
158
+ ### Blocked
159
+ - [Current blockers - remove if resolved]
160
+
161
+ ## Key Decisions
162
+ - **[Decision]**: [Brief rationale] (preserve all previous, add new)
163
+
164
+ ## Next Steps
165
+ 1. [Update based on current state]
166
+
167
+ ## Critical Context
168
+
169
+ ### Key Files & Code
170
+ - [Preserve existing file info, add new files read]
171
+ - [Include brief descriptions of key code structures]
172
+
173
+ ### Execution Results
174
+ - **Files**: [Preserve file list, add new files read/written/edited]
175
+ - **Commands**: [Preserve outputs, add new command results]
176
+ - **Search/Analysis**: [Preserve findings, add new search results]
177
+
178
+ ### Project Context
179
+ - [Preserve architecture info, add new patterns discovered]
180
+ - [Preserve configs, add new relevant dependencies]
181
+
182
+ Keep each section concise. Preserve exact file paths, function names, and error messages.`;
183
+ const TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.
184
+
185
+ Summarize the prefix to provide context for the retained suffix:
186
+
187
+ ## Original Request
188
+ [What did the user ask for in this turn?]
189
+
190
+ ## Early Progress
191
+ - [Key decisions and work done in the prefix]
192
+
193
+ ## Critical Context
194
+
195
+ ### Key Files & Code
196
+ - [File path]: [Brief description of key content/structure]
197
+
198
+ ### Execution Results
199
+ - **Files**: [What files were read, written, or edited in this prefix]
200
+ - **Commands**: [Key commands run and outputs]
201
+
202
+ ### Context for Suffix
203
+ - [Information needed to understand the retained recent work]
204
+
205
+ Be concise. Focus on what's needed to understand the kept suffix.`;
2
206
  export class ContextCompressor {
3
207
  aiClient = null;
4
208
  defaultConfig = {
5
- enabled: true,
6
- maxMessages: 50,
7
- maxContextSize: 150000,
8
- preserveRecentMessages: 0,
9
- enableSummary: true
209
+ enabled: true
10
210
  };
11
211
  constructor(authConfig) {
12
212
  if (authConfig) {
13
- this.aiClient = new AIClient(authConfig);
213
+ this.aiClient = createAIClient(authConfig);
14
214
  }
15
215
  }
16
216
  setAIClient(aiClient) {
17
217
  this.aiClient = aiClient;
18
218
  }
19
219
  /**
20
- * Check if compression is needed
220
+ * Check if compression is needed based on token budget and model context window
221
+ * @param messages - Conversation messages
222
+ * @param config - Compression config
223
+ * @param modelName - Optional model name to determine context window
21
224
  */
22
- needsCompression(messages, config) {
23
- const cfg = { ...this.defaultConfig, ...config };
24
- const userMessageCount = messages.filter(m => m.role === 'user').length;
25
- const contextSize = this.calculateContextSize(messages);
26
- if (userMessageCount > cfg.maxMessages) {
225
+ needsCompression(messages, config, modelName) {
226
+ const _cfg = { ...this.defaultConfig, ...config };
227
+ const _messageCount = messages.length;
228
+ const tokenCount = this.estimateContextTokens(messages);
229
+ // Get model context window
230
+ const contextWindow = getModelContextWindow(modelName);
231
+ // Calculate threshold using compression ratio constants
232
+ const reserveTokens = Math.floor(contextWindow * COMPRESSION_RATIO.RESERVE_RATIO);
233
+ const threshold = contextWindow - reserveTokens;
234
+ if (tokenCount > threshold) {
27
235
  return {
28
236
  needsCompression: true,
29
- reason: `User message count (${userMessageCount}) exceeds maximum (${cfg.maxMessages})`
237
+ reason: `Token count (${tokenCount}) exceeds ${modelName ? `${modelName}` : ''} context budget (${threshold}, contextWindow: ${contextWindow})`,
238
+ tokenCount
30
239
  };
31
240
  }
32
- if (contextSize > cfg.maxContextSize) {
33
- return {
34
- needsCompression: true,
35
- reason: `Context size (${contextSize} chars) exceeds maximum (${cfg.maxContextSize} chars)`
36
- };
241
+ return { needsCompression: false, reason: '', tokenCount };
242
+ }
243
+ /**
244
+ * Estimate token count for a single message using message-type-aware heuristic
245
+ */
246
+ estimateMessageTokens(message) {
247
+ let chars = 0;
248
+ switch (message.role) {
249
+ case 'user':
250
+ case 'system':
251
+ case 'tool': {
252
+ chars = message.content.length;
253
+ break;
254
+ }
255
+ case 'assistant': {
256
+ if (message.reasoning_content) {
257
+ chars += message.reasoning_content.length;
258
+ }
259
+ const toolCalls = message.tool_calls;
260
+ if (toolCalls && toolCalls.length > 0) {
261
+ for (const toolCall of toolCalls) {
262
+ chars += JSON.stringify(toolCall).length;
263
+ }
264
+ }
265
+ chars += message.content.length;
266
+ break;
267
+ }
37
268
  }
38
- return { needsCompression: false, reason: '' };
269
+ return Math.ceil(chars / 4);
39
270
  }
40
271
  /**
41
- * Calculate context size(字符数)
272
+ * Estimate total token count for a conversation
42
273
  */
43
- calculateContextSize(messages) {
44
- return messages.reduce((total, msg) => {
45
- return total + msg.content.length + (msg.role.length + 10);
46
- }, 0);
274
+ estimateContextTokens(messages) {
275
+ let total = 0;
276
+ for (const msg of messages) {
277
+ total += this.estimateMessageTokens(msg);
278
+ }
279
+ return total;
47
280
  }
48
281
  /**
49
- * Compress conversation history
282
+ * Find valid cut points: indices of messages that can be cut at
283
+ * Never cut at tool results (they must follow their tool call)
50
284
  */
51
- async compressContext(messages, systemPrompt, config) {
52
- const cfg = { ...this.defaultConfig, ...config };
53
- const originalMessageCount = messages.length;
54
- const originalSize = this.calculateContextSize(messages);
55
- // Separate system messages、用户消息和助手消息
56
- const systemMessages = messages.filter(m => m.role === 'system');
57
- const nonSystemMessages = messages.filter(m => m.role !== 'system');
58
- // 如果消息数量和大小都在限制内,不需要压缩
59
- const { needsCompression } = this.needsCompression(nonSystemMessages, config);
60
- if (!needsCompression) {
61
- return {
62
- compressedMessages: messages,
63
- wasCompressed: false,
64
- originalMessageCount,
65
- compressedMessageCount: messages.length,
66
- originalSize,
67
- compressedSize: originalSize,
68
- compressionMethod: 'none'
69
- };
285
+ findValidCutPoints(messages, startIndex, endIndex) {
286
+ const cutPoints = [];
287
+ for (let i = startIndex; i < endIndex; i++) {
288
+ const msg = messages[i];
289
+ switch (msg.role) {
290
+ case 'user':
291
+ case 'assistant':
292
+ case 'system':
293
+ cutPoints.push(i);
294
+ break;
295
+ case 'tool':
296
+ // Tool results cannot be cut at (they must follow their tool call)
297
+ break;
298
+ }
299
+ }
300
+ return cutPoints;
301
+ }
302
+ /**
303
+ * Find the user message that starts the turn containing the given index
304
+ */
305
+ findTurnStartIndex(messages, entryIndex, startIndex) {
306
+ for (let i = entryIndex; i >= startIndex; i--) {
307
+ const role = messages[i].role;
308
+ if (role === 'user') {
309
+ return i;
310
+ }
311
+ }
312
+ return -1;
313
+ }
314
+ /**
315
+ * Find the cut point that keeps approximately keepRecentTokens
316
+ * Walks backwards from newest, accumulating estimated message sizes
317
+ */
318
+ findCutPoint(messages, startIndex, endIndex, keepRecentTokens) {
319
+ const cutPoints = this.findValidCutPoints(messages, startIndex, endIndex);
320
+ if (cutPoints.length === 0) {
321
+ return { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };
70
322
  }
71
- // Use AI to generate summary压缩全部历史对话
72
- const compressedMessages = await this.summarizeAllMessages(nonSystemMessages, systemPrompt, cfg);
73
- // 注意:不再保留原始的 systemMessages,因为 generateResponse 会自动添加系统提示
74
- // 压缩后的消息只includes摘要(role: assistant),避免重复的 system 消息导致 API 报错
75
- const finalMessages = [...compressedMessages];
323
+ // Walk backwards from newest, accumulating estimated message sizes
324
+ let accumulatedTokens = 0;
325
+ let cutIndex = cutPoints[cutPoints.length - 1]; // Start with the last cut point
326
+ for (let i = endIndex - 1; i >= startIndex; i--) {
327
+ const messageTokens = this.estimateMessageTokens(messages[i]);
328
+ accumulatedTokens += messageTokens;
329
+ if (accumulatedTokens >= keepRecentTokens) {
330
+ // Find the closest valid cut point at or after this entry
331
+ // Search from the END of cutPoints array (closest to i)
332
+ for (let c = cutPoints.length - 1; c >= 0; c--) {
333
+ if (cutPoints[c] >= i) {
334
+ cutIndex = cutPoints[c];
335
+ }
336
+ else {
337
+ // Since cutPoints is sorted ascending, no need to continue
338
+ break;
339
+ }
340
+ }
341
+ break;
342
+ }
343
+ }
344
+ // Determine if this is a split turn
345
+ const isUserMessage = messages[cutIndex].role === 'user';
346
+ const turnStartIndex = isUserMessage ? -1 : this.findTurnStartIndex(messages, cutIndex, startIndex);
76
347
  return {
77
- compressedMessages: finalMessages,
78
- wasCompressed: true,
79
- originalMessageCount,
80
- compressedMessageCount: finalMessages.length,
81
- originalSize,
82
- compressedSize: this.calculateContextSize(finalMessages),
83
- compressionMethod: 'summary'
348
+ firstKeptEntryIndex: cutIndex,
349
+ turnStartIndex,
350
+ isSplitTurn: !isUserMessage && turnStartIndex !== -1
84
351
  };
85
352
  }
86
353
  /**
87
- * Use AI to generate summary来压缩全部对话历史
354
+ * Extract file operations from messages by analyzing tool calls
88
355
  */
89
- async summarizeAllMessages(messages, systemPrompt, config) {
90
- // 生成完整对话的摘要
91
- const summary = await this.generateSummary(messages, systemPrompt);
92
- // 构建压缩后的对话:只有摘要作为 system 消息
93
- const compressed = [];
94
- // 添加摘要作为 assistant 消息,避免与系统提示重复导致 API 报错
95
- compressed.push({
96
- role: 'assistant',
97
- content: `[Conversation Summary - ${messages.length} messages compressed]\n\n${summary}`,
98
- timestamp: Date.now()
99
- });
100
- return compressed;
356
+ extractFileOperations(messages) {
357
+ const fileOps = {
358
+ read: new Set(),
359
+ modified: new Set()
360
+ };
361
+ let _totalToolCalls = 0;
362
+ let _matchedToolCalls = 0;
363
+ // Normalize tool name (handle both API format and internal format)
364
+ const isReadTool = (name) => name === 'read_file' || name === 'Read';
365
+ const isWriteTool = (name) => name === 'write_file' || name === 'Write';
366
+ const isEditTool = (name) => name === 'Edit';
367
+ const isDeleteTool = (name) => name === 'DeleteFile';
368
+ const getFilePath = (args) => {
369
+ return args.filePath || args.absolute_path || args.path || '';
370
+ };
371
+ for (const msg of messages) {
372
+ // Case 1: assistant with tool_calls field
373
+ if (msg.role === 'assistant' && msg.tool_calls) {
374
+ for (const toolCall of msg.tool_calls) {
375
+ _totalToolCalls++;
376
+ const toolName = toolCall.function?.name || '';
377
+ let args = {};
378
+ try {
379
+ args = JSON.parse(toolCall.function?.arguments || '{}');
380
+ }
381
+ catch {
382
+ continue;
383
+ }
384
+ const filePath = getFilePath(args);
385
+ if (!filePath)
386
+ continue;
387
+ if (isReadTool(toolName)) {
388
+ fileOps.read.add(filePath);
389
+ _matchedToolCalls++;
390
+ }
391
+ else if (isWriteTool(toolName) || isEditTool(toolName) || isDeleteTool(toolName)) {
392
+ fileOps.modified.add(filePath);
393
+ _matchedToolCalls++;
394
+ }
395
+ }
396
+ }
397
+ // Case 2: tool role with JSON content (like {"name":"Read","parameters":...})
398
+ if (msg.role === 'tool' && typeof msg.content === 'string') {
399
+ try {
400
+ const content = JSON.parse(msg.content);
401
+ _totalToolCalls++;
402
+ const toolName = content.name || '';
403
+ const args = content.parameters || {};
404
+ const filePath = getFilePath(args);
405
+ if (!filePath)
406
+ continue;
407
+ if (isReadTool(toolName)) {
408
+ fileOps.read.add(filePath);
409
+ _matchedToolCalls++;
410
+ }
411
+ else if (isWriteTool(toolName) || isEditTool(toolName) || isDeleteTool(toolName)) {
412
+ fileOps.modified.add(filePath);
413
+ _matchedToolCalls++;
414
+ }
415
+ }
416
+ catch {
417
+ // Not JSON, skip
418
+ }
419
+ }
420
+ }
421
+ return fileOps;
422
+ }
423
+ /**
424
+ * Merge file operations from previous compaction
425
+ */
426
+ mergeFileOps(ops1, ops2) {
427
+ return {
428
+ read: new Set([...ops1.read, ...ops2.read]),
429
+ modified: new Set([...ops1.modified, ...ops2.modified])
430
+ };
431
+ }
432
+ /**
433
+ * Format file operations for inclusion in summary
434
+ */
435
+ formatFileOperations(fileOps) {
436
+ const readFiles = Array.from(fileOps.read);
437
+ const modifiedFiles = Array.from(fileOps.modified);
438
+ if (readFiles.length === 0 && modifiedFiles.length === 0) {
439
+ return '';
440
+ }
441
+ let formatted = '\n\n## File Operations\n\n';
442
+ if (readFiles.length > 0) {
443
+ formatted += '### Files read_file\n';
444
+ for (const file of readFiles) {
445
+ formatted += `- ${file}\n`;
446
+ }
447
+ }
448
+ if (modifiedFiles.length > 0) {
449
+ formatted += '\n### Files Modified\n';
450
+ for (const file of modifiedFiles) {
451
+ formatted += `- ${file}\n`;
452
+ }
453
+ }
454
+ return formatted;
455
+ }
456
+ /**
457
+ * Prepare compaction - calculate cut point and extract messages to summarize
458
+ */
459
+ prepareCompaction(messages, keepRecentTokens) {
460
+ if (messages.length === 0) {
461
+ return undefined;
462
+ }
463
+ // Check if last message already contains a compression summary
464
+ const lastMsg = messages[messages.length - 1];
465
+ const isAlreadyCompressed = lastMsg.role === 'user' &&
466
+ lastMsg.content.includes('[Previous conversation summarized');
467
+ if (isAlreadyCompressed) {
468
+ return undefined;
469
+ }
470
+ const startIndex = 0;
471
+ const endIndex = messages.length;
472
+ // Find cut point
473
+ const cutPoint = this.findCutPoint(messages, startIndex, endIndex, keepRecentTokens);
474
+ // Extract messages to summarize
475
+ const historyEnd = cutPoint.firstKeptEntryIndex;
476
+ const messagesToSummarize = [];
477
+ for (let i = startIndex; i < historyEnd; i++) {
478
+ messagesToSummarize.push(messages[i]);
479
+ }
480
+ // Extract turn prefix messages if splitting (disabled for simplicity)
481
+ const turnPrefixMessages = [];
482
+ if (cutPoint.isSplitTurn) {
483
+ for (let i = cutPoint.turnStartIndex; i < cutPoint.firstKeptEntryIndex; i++) {
484
+ turnPrefixMessages.push(messages[i]);
485
+ }
486
+ }
487
+ // Get previous summary if exists (look for embedded summary in user messages)
488
+ let previousSummary;
489
+ for (let i = messages.length - 1; i >= 0; i--) {
490
+ const msg = messages[i];
491
+ if (msg.role === 'user' && msg.content.includes('[Previous conversation summarized')) {
492
+ // Extract the summary part from the content
493
+ const match = msg.content.match(/\[Previous conversation summarized.*?\]\n(.+?)(?=\n\n---\n\n|\n\n\[)/s);
494
+ if (match) {
495
+ previousSummary = match[1];
496
+ }
497
+ else {
498
+ previousSummary = msg.content;
499
+ }
500
+ break;
501
+ }
502
+ }
503
+ // Extract file operations
504
+ const fileOps = this.extractFileOperations(messagesToSummarize);
505
+ // Also extract from turn prefix
506
+ if (cutPoint.isSplitTurn) {
507
+ const prefixOps = this.extractFileOperations(turnPrefixMessages);
508
+ return {
509
+ firstKeptEntryIndex: cutPoint.firstKeptEntryIndex,
510
+ messagesToSummarize,
511
+ turnPrefixMessages,
512
+ isSplitTurn: cutPoint.isSplitTurn,
513
+ tokensBefore: this.estimateContextTokens(messagesToSummarize),
514
+ previousSummary,
515
+ fileOps: this.mergeFileOps(fileOps, prefixOps)
516
+ };
517
+ }
518
+ return {
519
+ firstKeptEntryIndex: cutPoint.firstKeptEntryIndex,
520
+ messagesToSummarize,
521
+ turnPrefixMessages,
522
+ isSplitTurn: cutPoint.isSplitTurn,
523
+ tokensBefore: this.estimateContextTokens(messagesToSummarize),
524
+ previousSummary,
525
+ fileOps
526
+ };
101
527
  }
102
528
  /**
103
- * Generate conversation summary
529
+ * Generate summary using AI
104
530
  */
105
- async generateSummary(messages, systemPrompt) {
531
+ async generateSummary(messages, systemPrompt, reserveTokens, previousSummary, customInstructions) {
106
532
  if (!this.aiClient) {
107
533
  throw new Error('AI client not initialized for summarization');
108
534
  }
109
- // Extract all conversation content
535
+ // Serialize conversation
110
536
  const conversationText = messages
111
537
  .map((m, idx) => {
112
538
  const role = m.role === 'user' ? 'User' :
@@ -115,91 +541,235 @@ export class ContextCompressor {
115
541
  return `[${idx + 1}] ${role}:\n${m.content}`;
116
542
  })
117
543
  .join('\n\n' + '='.repeat(50) + '\n\n');
118
- const summaryPrompt = `You are an expert at summarizing conversations. Please create a comprehensive summary of the following conversation.
119
-
120
- ## Instructions
121
- 1. Analyze ALL messages in the conversation
122
- 2. Create a detailed summary that captures:
123
- - Complete context and background
124
- - All topics discussed
125
- - All decisions made
126
- - All files created, modified, or analyzed
127
- - All code changes and implementations
128
- - All problems solved
129
- - Current state and progress
130
- - Any pending or ongoing tasks
131
- 3. Be extremely thorough - this summary will replace the entire conversation history
132
- 4. Include specific details like file paths, code snippets, command outputs, etc.
133
-
134
- ## Conversation to summarize
135
- ${conversationText}
136
-
137
- ## Output Format
138
- Provide a detailed, comprehensive summary in the following format:
139
-
140
- ### Conversation Summary
141
-
142
- #### Overview
143
- [Brief description of what this conversation was about]
144
-
145
- #### Background & Context
146
- [Complete background information]
147
-
148
- #### Topics Discussed
149
- - [Topic 1: detailed description]
150
- - [Topic 2: detailed description]
151
- - [All topics with full details]
152
-
153
- #### Key Decisions
154
- - [Decision 1: details and rationale]
155
- - [All decisions made during the conversation]
156
-
157
- #### File Operations
158
- - Created: [file paths]
159
- - Modified: [file paths]
160
- - Analyzed: [file paths]
161
- - Deleted: [file paths]
162
-
163
- #### Code Changes
164
- - [Specific code changes with details]
165
- - [All implementations]
166
-
167
- #### Problems & Solutions
168
- - Problem: [description]
169
- Solution: [how it was solved]
170
- - [All problems and solutions]
171
-
172
- #### Current State
173
- [What is the current status of the project/work]
174
-
175
- #### Pending Tasks
176
- - [Any ongoing or pending work]
177
-
178
- #### Important Details
179
- [Any other crucial information]
180
-
181
- Please provide the comprehensive summary possible. Do not omit any important information.`;
544
+ // Select prompt based on whether we have previous summary
545
+ let basePrompt = previousSummary ? UPDATE_SUMMARIZATION_PROMPT : SUMMARIZATION_PROMPT;
546
+ if (customInstructions) {
547
+ basePrompt = `${basePrompt}\n\nAdditional focus: ${customInstructions}`;
548
+ }
549
+ // Build prompt
550
+ let promptText = `<conversation>\n${conversationText}\n</conversation>\n\n`;
551
+ if (previousSummary) {
552
+ promptText += `<previous-summary>\n${previousSummary}\n</previous-summary>\n\n`;
553
+ }
554
+ promptText += basePrompt;
555
+ const maxTokens = Math.floor(reserveTokens * COMPRESSION_RATIO.MAX_TOKENS_RATIO);
556
+ const summaryMessage = {
557
+ role: 'user',
558
+ content: promptText
559
+ };
560
+ const aiPromise = this.aiClient.compress([summaryMessage], {
561
+ maxTokens,
562
+ temperature: 0.3
563
+ });
182
564
  try {
183
- const summaryMessage = {
184
- role: 'user',
185
- content: summaryPrompt
186
- };
187
- const response = await this.aiClient.chatCompletion([summaryMessage], {
188
- maxTokens: 8192,
189
- temperature: 0.3
190
- });
565
+ const response = await getCancellationManager().withCancellation(aiPromise, 'context-compression-summary');
191
566
  const summary = response.choices[0]?.message?.content || '';
192
567
  return typeof summary === 'string' ? summary : JSON.stringify(summary);
193
568
  }
194
569
  catch (error) {
570
+ if (error.message === 'Operation cancelled by user') {
571
+ throw error;
572
+ }
195
573
  console.error('Failed to generate summary:', error);
574
+ await logOutput('error', 'Failed to generate summary', { error: error.message });
196
575
  const userCount = messages.filter(m => m.role === 'user').length;
197
576
  const toolCount = messages.filter(m => m.role === 'tool').length;
198
577
  return `[Summary of ${messages.length} messages: ${userCount} user exchanges, ${toolCount} tool calls. Key topics discussed but details unavailable due to summarization error.]`;
199
578
  }
200
579
  }
201
580
  /**
202
- * Create compressed message copy(用于保存)
581
+ * Generate turn prefix summary when splitting a turn
582
+ */
583
+ async generateTurnPrefixSummary(messages, reserveTokens) {
584
+ if (!this.aiClient) {
585
+ throw new Error('AI client not initialized for summarization');
586
+ }
587
+ const conversationText = messages
588
+ .map((m, idx) => {
589
+ const role = m.role === 'user' ? 'User' :
590
+ m.role === 'assistant' ? 'Assistant' :
591
+ m.role === 'tool' ? 'Tool' : m.role;
592
+ return `[${idx + 1}] ${role}:\n${m.content}`;
593
+ })
594
+ .join('\n\n' + '='.repeat(50) + '\n\n');
595
+ const promptText = `<conversation>\n${conversationText}\n</conversation>\n\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`;
596
+ const maxTokens = Math.floor(reserveTokens * COMPRESSION_RATIO.SUMMARY_MAX_TOKENS_RATIO);
597
+ const summaryMessage = {
598
+ role: 'user',
599
+ content: promptText
600
+ };
601
+ const aiPromise = this.aiClient.compress([summaryMessage], {
602
+ maxTokens,
603
+ temperature: 0.3
604
+ });
605
+ try {
606
+ const response = await getCancellationManager().withCancellation(aiPromise, 'context-compression-turn-prefix');
607
+ const content = response.choices[0]?.message?.content || '';
608
+ return typeof content === 'string' ? content : JSON.stringify(content);
609
+ }
610
+ catch (error) {
611
+ if (error.message === 'Operation cancelled by user') {
612
+ throw error;
613
+ }
614
+ console.error('Failed to generate turn prefix summary:', error);
615
+ await logOutput('error', 'Failed to generate turn prefix summary', { error: error.message });
616
+ return '[Turn prefix summary unavailable]';
617
+ }
618
+ }
619
+ /**
620
+ * Main compression function with incremental compaction support
621
+ */
622
+ async compressContext(messages, systemPrompt, config, previousSummary, modelName) {
623
+ const _cfg = { ...this.defaultConfig, ...config };
624
+ const originalMessageCount = messages.length;
625
+ const originalSize = messages.reduce((total, msg) => total + msg.content.length, 0);
626
+ const _originalTokens = this.estimateContextTokens(messages);
627
+ const contextWindow = getModelContextWindow(modelName);
628
+ // Check if compression is needed
629
+ const { needsCompression } = this.needsCompression(messages, config, modelName);
630
+ if (!needsCompression) {
631
+ return {
632
+ compressedMessages: messages,
633
+ wasCompressed: false,
634
+ originalMessageCount,
635
+ compressedMessageCount: messages.length,
636
+ originalSize,
637
+ compressedSize: originalSize,
638
+ compressionMethod: 'none'
639
+ };
640
+ }
641
+ // Prepare compaction
642
+ // Reserve 50% of context window for new conversation, 15% for summary
643
+ const reserveTokens = Math.floor(contextWindow * COMPRESSION_RATIO.RESERVE_RATIO);
644
+ const summaryReserveTokens = Math.max(COMPRESSION_RATIO.MIN_SUMMARY_TOKENS, Math.floor((contextWindow - reserveTokens) * COMPRESSION_RATIO.SUMMARY_THRESHOLD_RATIO));
645
+ const keepRecentTokens = contextWindow - reserveTokens - summaryReserveTokens;
646
+ const preparation = this.prepareCompaction(messages, Math.max(0, keepRecentTokens));
647
+ if (!preparation) {
648
+ // Already compressed or no valid cut point
649
+ return {
650
+ compressedMessages: messages,
651
+ wasCompressed: false,
652
+ originalMessageCount,
653
+ compressedMessageCount: messages.length,
654
+ originalSize,
655
+ compressedSize: originalSize,
656
+ compressionMethod: 'none'
657
+ };
658
+ }
659
+ const { firstKeptEntryIndex, messagesToSummarize, turnPrefixMessages, isSplitTurn, tokensBefore, fileOps } = preparation;
660
+ // Generate summary
661
+ let summary;
662
+ if (isSplitTurn && turnPrefixMessages.length > 0) {
663
+ // Generate both summaries in parallel
664
+ const [historyResult, turnPrefixResult] = await Promise.all([
665
+ messagesToSummarize.length > 0
666
+ ? this.generateSummary(messagesToSummarize, systemPrompt, summaryReserveTokens, previousSummary)
667
+ : Promise.resolve('No prior history.'),
668
+ this.generateTurnPrefixSummary(turnPrefixMessages, summaryReserveTokens)
669
+ ]);
670
+ summary = `${historyResult}\n\n---\n\n**Turn Context (split turn):**\n\n${turnPrefixResult}`;
671
+ }
672
+ else {
673
+ summary = await this.generateSummary(messagesToSummarize, systemPrompt, summaryReserveTokens, previousSummary);
674
+ }
675
+ // Add file operations to summary
676
+ summary += this.formatFileOperations(fileOps);
677
+ // Build compressed messages: summary + kept messages
678
+ // Summary is inserted as prefix in first user message to maintain valid message order
679
+ const compressedMessages = [];
680
+ if (messagesToSummarize.length > 0) {
681
+ // Find first user message in kept messages
682
+ let firstKeptUserMsg = null;
683
+ let firstKeptUserIndex = -1;
684
+ for (let i = firstKeptEntryIndex; i < messages.length; i++) {
685
+ if (messages[i].role === 'user') {
686
+ firstKeptUserMsg = messages[i];
687
+ firstKeptUserIndex = i;
688
+ break;
689
+ }
690
+ }
691
+ if (firstKeptUserMsg) {
692
+ // Prepend summary to first user message content
693
+ const summaryPrefix = `[Previous conversation summarized (${messagesToSummarize.length} messages):]\n${summary}\n\n---\n\n`;
694
+ compressedMessages.push({
695
+ role: 'user',
696
+ content: summaryPrefix + firstKeptUserMsg.content,
697
+ timestamp: firstKeptUserMsg.timestamp,
698
+ images: firstKeptUserMsg.images
699
+ });
700
+ // Add remaining kept messages (skip the modified first user message)
701
+ for (let i = firstKeptUserIndex + 1; i < messages.length; i++) {
702
+ const msg = messages[i];
703
+ compressedMessages.push({
704
+ role: msg.role,
705
+ content: msg.content,
706
+ timestamp: msg.timestamp,
707
+ images: msg.images,
708
+ reasoning_content: msg.reasoning_content,
709
+ tool_calls: msg.tool_calls,
710
+ tool_call_id: msg.tool_call_id
711
+ });
712
+ }
713
+ }
714
+ else {
715
+ // No user message in kept messages (rare case)
716
+ // Insert summary as a user message, then add all kept messages
717
+ // This ensures valid message order: user �?assistant �?tool �?tool...
718
+ compressedMessages.push({
719
+ role: 'user',
720
+ content: `[Conversation Summary - ${messagesToSummarize.length} messages compressed]\n\n${summary}`,
721
+ timestamp: Date.now()
722
+ });
723
+ // Add all kept messages (they may start with assistant or tool)
724
+ for (let i = firstKeptEntryIndex; i < messages.length; i++) {
725
+ const msg = messages[i];
726
+ compressedMessages.push({
727
+ role: msg.role,
728
+ content: msg.content,
729
+ timestamp: msg.timestamp,
730
+ images: msg.images,
731
+ reasoning_content: msg.reasoning_content,
732
+ tool_calls: msg.tool_calls,
733
+ tool_call_id: msg.tool_call_id
734
+ });
735
+ }
736
+ }
737
+ }
738
+ else {
739
+ // No messages to summarize, just keep all messages
740
+ for (let i = firstKeptEntryIndex; i < messages.length; i++) {
741
+ const msg = messages[i];
742
+ compressedMessages.push({
743
+ role: msg.role,
744
+ content: msg.content,
745
+ timestamp: msg.timestamp,
746
+ images: msg.images,
747
+ reasoning_content: msg.reasoning_content,
748
+ tool_calls: msg.tool_calls,
749
+ tool_call_id: msg.tool_call_id
750
+ });
751
+ }
752
+ }
753
+ const compressedSize = compressedMessages.reduce((total, msg) => total + msg.content.length, 0);
754
+ const _compressedTokens = this.estimateContextTokens(compressedMessages);
755
+ const _reductionPercent = Math.round((1 - compressedSize / originalSize) * 100);
756
+ return {
757
+ compressedMessages,
758
+ wasCompressed: true,
759
+ originalMessageCount,
760
+ compressedMessageCount: compressedMessages.length,
761
+ originalSize,
762
+ compressedSize,
763
+ compressionMethod: 'summary',
764
+ tokensBefore,
765
+ details: {
766
+ readFiles: Array.from(fileOps.read),
767
+ modifiedFiles: Array.from(fileOps.modified)
768
+ }
769
+ };
770
+ }
771
+ /**
772
+ * Create compressed message copy for saving
203
773
  */
204
774
  createCompressedSnapshot(messages, compressionResult) {
205
775
  return {
@@ -209,17 +779,11 @@ Please provide the comprehensive summary possible. Do not omit any important inf
209
779
  originalSize: compressionResult.originalSize,
210
780
  compressedSize: compressionResult.compressedSize,
211
781
  compressionMethod: compressionResult.compressionMethod,
782
+ tokensBefore: compressionResult.tokensBefore,
783
+ details: compressionResult.details,
212
784
  messages: compressionResult.compressedMessages
213
785
  };
214
786
  }
215
- /**
216
- * Estimate token count (rough estimate)
217
- */
218
- estimateTokens(text) {
219
- const chineseChars = (text.match(/[\u4e00-\u9fa5]/g) || []).length;
220
- const otherChars = text.length - chineseChars;
221
- return Math.ceil(chineseChars / 2 + otherChars / 4);
222
- }
223
787
  }
224
788
  let compressorInstance = null;
225
789
  export function getContextCompressor(authConfig) {