@cjhyy/code-shell-core 0.5.0-rc.2 → 0.6.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/README.md +13 -10
  2. package/dist/agent/agent-definition-registry.d.ts +3 -0
  3. package/dist/agent/agent-definition-registry.js +3 -1
  4. package/dist/agent/agent-definition.d.ts +15 -0
  5. package/dist/agent/agent-definition.js +27 -3
  6. package/dist/arena/context/context-tools.js +47 -4
  7. package/dist/arena/ledger.js +9 -1
  8. package/dist/arena/strategies/utils.d.ts +1 -4
  9. package/dist/arena/strategies/utils.js +7 -84
  10. package/dist/automation/cron-expr.d.ts +10 -0
  11. package/dist/automation/cron-expr.js +23 -5
  12. package/dist/automation/runner.d.ts +21 -4
  13. package/dist/automation/runner.js +48 -12
  14. package/dist/automation/scheduler.d.ts +38 -0
  15. package/dist/automation/scheduler.js +89 -12
  16. package/dist/automation/store.js +5 -2
  17. package/dist/capability-control/disabled-lists.d.ts +25 -0
  18. package/dist/capability-control/disabled-lists.js +57 -0
  19. package/dist/capability-control/overlay.d.ts +15 -0
  20. package/dist/capability-control/overlay.js +27 -0
  21. package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
  22. package/dist/cc-orchestrator/agent-adapter.js +133 -0
  23. package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
  24. package/dist/cc-orchestrator/cc-capability.js +53 -0
  25. package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
  26. package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
  27. package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
  28. package/dist/cc-orchestrator/codex-session-history.js +187 -0
  29. package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
  30. package/dist/cc-orchestrator/external-agent-changes.js +214 -0
  31. package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
  32. package/dist/cc-orchestrator/external-agent-driver.js +69 -0
  33. package/dist/cc-orchestrator/index.d.ts +8 -0
  34. package/dist/cc-orchestrator/index.js +8 -0
  35. package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
  36. package/dist/cc-orchestrator/relevance-judge.js +29 -0
  37. package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
  38. package/dist/cc-orchestrator/session-discovery.js +125 -0
  39. package/dist/cc-orchestrator/session-history.d.ts +19 -0
  40. package/dist/cc-orchestrator/session-history.js +67 -0
  41. package/dist/cli/agent-server-stdio.d.ts +15 -1
  42. package/dist/cli/agent-server-stdio.js +115 -17
  43. package/dist/cli/agent-server-tcp.js +40 -26
  44. package/dist/context/compaction.d.ts +56 -0
  45. package/dist/context/compaction.js +186 -0
  46. package/dist/context/manager.js +25 -4
  47. package/dist/cost-tracker.js +5 -61
  48. package/dist/credentials/cipher.d.ts +49 -0
  49. package/dist/credentials/cipher.js +45 -0
  50. package/dist/credentials/cookie-jar.d.ts +24 -0
  51. package/dist/credentials/cookie-jar.js +40 -0
  52. package/dist/credentials/index.d.ts +7 -0
  53. package/dist/credentials/index.js +5 -0
  54. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  55. package/dist/credentials/inject-credential-tool.js +130 -0
  56. package/dist/credentials/store.d.ts +72 -0
  57. package/dist/credentials/store.js +184 -0
  58. package/dist/credentials/types.d.ts +56 -0
  59. package/dist/credentials/use-credential-tool.d.ts +29 -0
  60. package/dist/credentials/use-credential-tool.js +205 -0
  61. package/dist/credentials/use-gate.d.ts +56 -0
  62. package/dist/credentials/use-gate.js +52 -0
  63. package/dist/data/model-metadata.d.ts +77 -0
  64. package/dist/data/model-metadata.js +56 -0
  65. package/dist/data/model-metadata.json +216 -0
  66. package/dist/data/openrouter-models.d.ts +18 -7
  67. package/dist/data/openrouter-models.js +35 -8
  68. package/dist/engine/aux-key.d.ts +10 -0
  69. package/dist/engine/aux-key.js +11 -0
  70. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  71. package/dist/engine/dynamic-tool-defs.js +36 -0
  72. package/dist/engine/engine.d.ts +267 -138
  73. package/dist/engine/engine.js +957 -191
  74. package/dist/engine/friendly-error.d.ts +18 -0
  75. package/dist/engine/friendly-error.js +63 -0
  76. package/dist/engine/goal.d.ts +145 -0
  77. package/dist/engine/goal.js +144 -0
  78. package/dist/engine/image-policy.d.ts +13 -0
  79. package/dist/engine/image-policy.js +24 -0
  80. package/dist/engine/model-connections-pool.d.ts +17 -0
  81. package/dist/engine/model-connections-pool.js +66 -0
  82. package/dist/engine/model-facade.d.ts +10 -0
  83. package/dist/engine/model-facade.js +25 -0
  84. package/dist/engine/patch-orphaned-tools.js +3 -0
  85. package/dist/engine/resolve-llm-config.d.ts +16 -0
  86. package/dist/engine/resolve-llm-config.js +44 -0
  87. package/dist/engine/runtime.js +2 -1
  88. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  89. package/dist/engine/sandbox-cache-key.js +9 -0
  90. package/dist/engine/sandbox-config.d.ts +31 -0
  91. package/dist/engine/sandbox-config.js +38 -0
  92. package/dist/engine/session-usage.d.ts +19 -0
  93. package/dist/engine/session-usage.js +25 -0
  94. package/dist/engine/steer-queue.d.ts +32 -0
  95. package/dist/engine/steer-queue.js +26 -0
  96. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  97. package/dist/engine/streaming-tool-queue.js +50 -10
  98. package/dist/engine/turn-loop.d.ts +67 -3
  99. package/dist/engine/turn-loop.js +292 -41
  100. package/dist/engine/types.d.ts +175 -0
  101. package/dist/engine/types.js +13 -0
  102. package/dist/external-agents/config.d.ts +2 -0
  103. package/dist/external-agents/config.js +15 -0
  104. package/dist/external-agents/types.d.ts +31 -0
  105. package/dist/external-agents/types.js +1 -0
  106. package/dist/git/utils.js +11 -6
  107. package/dist/git/worktree.d.ts +48 -0
  108. package/dist/git/worktree.js +86 -10
  109. package/dist/hooks/goal-stop-hook.d.ts +28 -0
  110. package/dist/hooks/goal-stop-hook.js +186 -9
  111. package/dist/hooks/registry.d.ts +8 -0
  112. package/dist/hooks/registry.js +19 -0
  113. package/dist/hooks/shell-runner.js +10 -21
  114. package/dist/index.d.ts +49 -6
  115. package/dist/index.js +60 -4
  116. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  117. package/dist/llm/capabilities/param-specs.js +62 -0
  118. package/dist/llm/capabilities/rules.js +4 -0
  119. package/dist/llm/capabilities/types.d.ts +10 -0
  120. package/dist/llm/client-base.d.ts +28 -1
  121. package/dist/llm/client-base.js +119 -13
  122. package/dist/llm/model-cache.js +4 -2
  123. package/dist/llm/model-pool.d.ts +14 -0
  124. package/dist/llm/model-pool.js +13 -0
  125. package/dist/llm/provider-auth.d.ts +41 -0
  126. package/dist/llm/provider-auth.js +76 -0
  127. package/dist/llm/provider-catalog.d.ts +4 -0
  128. package/dist/llm/providers/anthropic.js +64 -14
  129. package/dist/llm/providers/openai.d.ts +36 -0
  130. package/dist/llm/providers/openai.js +257 -51
  131. package/dist/llm/reasoning-setting.d.ts +3 -3
  132. package/dist/llm/reasoning-setting.js +9 -1
  133. package/dist/llm/stream-watchdog.js +5 -1
  134. package/dist/llm/token-counter.js +9 -2
  135. package/dist/llm/types.d.ts +4 -0
  136. package/dist/logging/sanitize-messages.js +22 -0
  137. package/dist/lsp/manager.d.ts +1 -1
  138. package/dist/lsp/manager.js +40 -10
  139. package/dist/model-catalog/builtin.d.ts +12 -0
  140. package/dist/model-catalog/builtin.js +407 -0
  141. package/dist/model-catalog/gen-connections.d.ts +20 -0
  142. package/dist/model-catalog/gen-connections.js +28 -0
  143. package/dist/model-catalog/index.d.ts +41 -0
  144. package/dist/model-catalog/index.js +90 -0
  145. package/dist/model-catalog/params.d.ts +20 -0
  146. package/dist/model-catalog/params.js +45 -0
  147. package/dist/model-catalog/resolve.d.ts +48 -0
  148. package/dist/model-catalog/resolve.js +33 -0
  149. package/dist/model-catalog/save-entry.d.ts +32 -0
  150. package/dist/model-catalog/save-entry.js +104 -0
  151. package/dist/model-catalog/types.d.ts +561 -0
  152. package/dist/model-catalog/types.js +93 -0
  153. package/dist/model-catalog/upsert.d.ts +9 -0
  154. package/dist/model-catalog/upsert.js +8 -0
  155. package/dist/onboarding.d.ts +12 -82
  156. package/dist/onboarding.js +61 -326
  157. package/dist/plugins/gitOps.d.ts +19 -0
  158. package/dist/plugins/gitOps.js +73 -4
  159. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  160. package/dist/plugins/installer/checkUpdate.js +32 -0
  161. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  162. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  163. package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
  164. package/dist/plugins/installer/codex/convertMcp.js +45 -5
  165. package/dist/plugins/installer/install.js +25 -1
  166. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  167. package/dist/plugins/installer/installFromArchive.js +134 -0
  168. package/dist/plugins/installer/installFromSource.js +8 -2
  169. package/dist/plugins/installer/loadPluginAgents.js +6 -2
  170. package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
  171. package/dist/plugins/installer/loadPluginMcp.js +35 -2
  172. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  173. package/dist/plugins/installer/pruneDisabled.js +73 -0
  174. package/dist/plugins/installer/types.d.ts +5 -2
  175. package/dist/plugins/installer/types.js +1 -0
  176. package/dist/plugins/installer/uninstall.js +4 -0
  177. package/dist/plugins/installer/unzip.d.ts +14 -0
  178. package/dist/plugins/installer/unzip.js +82 -0
  179. package/dist/plugins/installer/update.d.ts +14 -0
  180. package/dist/plugins/installer/update.js +53 -21
  181. package/dist/plugins/loadPluginHooks.d.ts +47 -1
  182. package/dist/plugins/loadPluginHooks.js +73 -1
  183. package/dist/plugins/marketplaceManager.d.ts +7 -0
  184. package/dist/plugins/marketplaceManager.js +20 -0
  185. package/dist/plugins/pluginCommandHook.js +4 -18
  186. package/dist/plugins/pluginContent.d.ts +30 -0
  187. package/dist/plugins/pluginContent.js +83 -0
  188. package/dist/plugins/pluginInstaller.d.ts +13 -0
  189. package/dist/plugins/pluginInstaller.js +42 -8
  190. package/dist/plugins/schemas.js +1 -0
  191. package/dist/plugins/types.d.ts +6 -0
  192. package/dist/preset/index.d.ts +7 -1
  193. package/dist/preset/index.js +96 -6
  194. package/dist/product/types.d.ts +1 -1
  195. package/dist/prompt/composer.d.ts +27 -0
  196. package/dist/prompt/composer.js +67 -21
  197. package/dist/prompt/instruction-scanner.js +5 -3
  198. package/dist/prompt/section-loader.js +1 -0
  199. package/dist/prompt/sections/base.md +1 -0
  200. package/dist/prompt/sections/browser.md +10 -0
  201. package/dist/prompt/sections/coding.md +4 -0
  202. package/dist/protocol/chat-session-manager.d.ts +8 -2
  203. package/dist/protocol/chat-session-manager.js +36 -0
  204. package/dist/protocol/chat-session.d.ts +65 -0
  205. package/dist/protocol/chat-session.js +94 -2
  206. package/dist/protocol/client.d.ts +27 -0
  207. package/dist/protocol/client.js +38 -0
  208. package/dist/protocol/server.d.ts +112 -0
  209. package/dist/protocol/server.js +586 -16
  210. package/dist/protocol/transport.js +3 -2
  211. package/dist/protocol/types.d.ts +46 -0
  212. package/dist/protocol/types.js +16 -0
  213. package/dist/quota/credentials.d.ts +3 -0
  214. package/dist/quota/credentials.js +80 -0
  215. package/dist/quota/index.d.ts +36 -0
  216. package/dist/quota/index.js +155 -0
  217. package/dist/quota/types.d.ts +48 -0
  218. package/dist/quota/types.js +13 -0
  219. package/dist/review/review-prompt.d.ts +28 -0
  220. package/dist/review/review-prompt.js +81 -0
  221. package/dist/run/FileRunStore.js +8 -3
  222. package/dist/run/RunApprovalBackend.js +25 -5
  223. package/dist/run/RunManager.d.ts +12 -0
  224. package/dist/run/RunManager.js +35 -0
  225. package/dist/run/factory.d.ts +1 -1
  226. package/dist/runtime/background-shell.d.ts +139 -0
  227. package/dist/runtime/background-shell.js +495 -0
  228. package/dist/runtime/output-clean.d.ts +24 -0
  229. package/dist/runtime/output-clean.js +41 -0
  230. package/dist/runtime/ring-file.d.ts +64 -0
  231. package/dist/runtime/ring-file.js +174 -0
  232. package/dist/runtime/safe-spawn.js +15 -34
  233. package/dist/runtime/spawn-common.d.ts +148 -0
  234. package/dist/runtime/spawn-common.js +303 -0
  235. package/dist/runtime/truncate-output.d.ts +22 -0
  236. package/dist/runtime/truncate-output.js +49 -0
  237. package/dist/runtime/utf8-cut.d.ts +11 -0
  238. package/dist/runtime/utf8-cut.js +23 -0
  239. package/dist/services/auto-dream.d.ts +4 -0
  240. package/dist/services/auto-dream.js +26 -26
  241. package/dist/services/diagnostics.d.ts +1 -2
  242. package/dist/services/diagnostics.js +12 -7
  243. package/dist/services/extract-memories.d.ts +14 -1
  244. package/dist/services/extract-memories.js +45 -6
  245. package/dist/services/memory-orchestrator.d.ts +21 -0
  246. package/dist/services/memory-orchestrator.js +125 -50
  247. package/dist/services/session-memory.js +24 -12
  248. package/dist/session/file-history.d.ts +124 -1
  249. package/dist/session/file-history.js +222 -6
  250. package/dist/session/memory.d.ts +116 -2
  251. package/dist/session/memory.js +250 -28
  252. package/dist/session/session-manager.d.ts +40 -0
  253. package/dist/session/session-manager.js +113 -3
  254. package/dist/session/simple-diff.d.ts +23 -0
  255. package/dist/session/simple-diff.js +84 -0
  256. package/dist/session/transcript.d.ts +25 -1
  257. package/dist/session/transcript.js +35 -2
  258. package/dist/session/undo-target.d.ts +67 -0
  259. package/dist/session/undo-target.js +144 -0
  260. package/dist/settings/disk-defaults.d.ts +9 -2
  261. package/dist/settings/disk-defaults.js +11 -2
  262. package/dist/settings/feature-flags.d.ts +64 -0
  263. package/dist/settings/feature-flags.js +61 -0
  264. package/dist/settings/manager.d.ts +68 -1
  265. package/dist/settings/manager.js +266 -29
  266. package/dist/settings/migrate-config.d.ts +45 -0
  267. package/dist/settings/migrate-config.js +125 -0
  268. package/dist/settings/schema-export.d.ts +25 -0
  269. package/dist/settings/schema-export.js +38 -0
  270. package/dist/settings/schema.d.ts +1186 -771
  271. package/dist/settings/schema.js +268 -97
  272. package/dist/skills/scanner.d.ts +9 -0
  273. package/dist/skills/scanner.js +30 -2
  274. package/dist/stt/resolve-transcribe.d.ts +31 -0
  275. package/dist/stt/resolve-transcribe.js +108 -0
  276. package/dist/stt/transcribe.d.ts +51 -0
  277. package/dist/stt/transcribe.js +65 -0
  278. package/dist/tool-system/browser-bridge.d.ts +226 -0
  279. package/dist/tool-system/browser-bridge.js +163 -0
  280. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  281. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  282. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  283. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  284. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  285. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  286. package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
  287. package/dist/tool-system/builtin/agent-registry.js +8 -0
  288. package/dist/tool-system/builtin/agent.d.ts +21 -1
  289. package/dist/tool-system/builtin/agent.js +489 -42
  290. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  291. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  292. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  293. package/dist/tool-system/builtin/apply-patch/index.js +0 -15
  294. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  295. package/dist/tool-system/builtin/background-jobs.js +124 -0
  296. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  297. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  298. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  299. package/dist/tool-system/builtin/background-work.js +86 -0
  300. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  301. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  302. package/dist/tool-system/builtin/bash.d.ts +5 -2
  303. package/dist/tool-system/builtin/bash.js +98 -62
  304. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  305. package/dist/tool-system/builtin/browser-tools.js +312 -0
  306. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  307. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  308. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  309. package/dist/tool-system/builtin/check-quota.js +34 -0
  310. package/dist/tool-system/builtin/config.js +7 -0
  311. package/dist/tool-system/builtin/cron.d.ts +7 -0
  312. package/dist/tool-system/builtin/cron.js +55 -3
  313. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  314. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  315. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  316. package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
  317. package/dist/tool-system/builtin/edit.js +20 -16
  318. package/dist/tool-system/builtin/eol.d.ts +29 -0
  319. package/dist/tool-system/builtin/eol.js +37 -0
  320. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  321. package/dist/tool-system/builtin/file-cache.js +8 -0
  322. package/dist/tool-system/builtin/generate-image.d.ts +35 -0
  323. package/dist/tool-system/builtin/generate-image.js +278 -50
  324. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  325. package/dist/tool-system/builtin/generate-video.js +361 -0
  326. package/dist/tool-system/builtin/glob.js +0 -7
  327. package/dist/tool-system/builtin/grep.js +6 -8
  328. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  329. package/dist/tool-system/builtin/image-providers.js +190 -0
  330. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  331. package/dist/tool-system/builtin/image-uploader.js +74 -0
  332. package/dist/tool-system/builtin/index.d.ts +7 -1
  333. package/dist/tool-system/builtin/index.js +249 -25
  334. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  335. package/dist/tool-system/builtin/memory.js +45 -7
  336. package/dist/tool-system/builtin/notebook-edit.js +0 -7
  337. package/dist/tool-system/builtin/powershell.js +4 -1
  338. package/dist/tool-system/builtin/read.js +10 -10
  339. package/dist/tool-system/builtin/repl.js +4 -1
  340. package/dist/tool-system/builtin/skill.js +9 -0
  341. package/dist/tool-system/builtin/sleep.js +3 -2
  342. package/dist/tool-system/builtin/tool-search.js +25 -7
  343. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  344. package/dist/tool-system/builtin/video-providers.js +235 -0
  345. package/dist/tool-system/builtin/web-fetch.js +12 -2
  346. package/dist/tool-system/builtin/web-search.js +21 -7
  347. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  348. package/dist/tool-system/builtin/worktree.js +31 -4
  349. package/dist/tool-system/builtin/write.js +0 -6
  350. package/dist/tool-system/context.d.ts +154 -6
  351. package/dist/tool-system/executor.d.ts +3 -1
  352. package/dist/tool-system/executor.js +172 -88
  353. package/dist/tool-system/investigation-guard.js +1 -1
  354. package/dist/tool-system/mcp-manager.d.ts +42 -4
  355. package/dist/tool-system/mcp-manager.js +186 -20
  356. package/dist/tool-system/path-policy.d.ts +5 -0
  357. package/dist/tool-system/path-policy.js +307 -8
  358. package/dist/tool-system/permission.d.ts +36 -1
  359. package/dist/tool-system/permission.js +281 -69
  360. package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
  361. package/dist/tool-system/plan-mode-allowlist.js +24 -2
  362. package/dist/tool-system/registry.d.ts +1 -0
  363. package/dist/tool-system/registry.js +16 -2
  364. package/dist/tool-system/sandbox/index.d.ts +8 -0
  365. package/dist/tool-system/sandbox/index.js +7 -2
  366. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  367. package/dist/tool-system/validate-tool-metadata.js +63 -0
  368. package/dist/types.d.ts +217 -6
  369. package/dist/updater.js +20 -9
  370. package/dist/utils/envUtils.d.ts +0 -9
  371. package/dist/utils/envUtils.js +3 -28
  372. package/dist/utils/exec.d.ts +40 -0
  373. package/dist/utils/exec.js +144 -0
  374. package/dist/utils/json.d.ts +12 -0
  375. package/dist/utils/json.js +92 -0
  376. package/dist/utils/theme.d.ts +1 -1
  377. package/dist/utils/theme.js +1 -1
  378. package/dist/utils/toolDisplay.js +0 -1
  379. package/package.json +13 -7
  380. package/dist/agent/coordinator.d.ts +0 -49
  381. package/dist/agent/coordinator.js +0 -77
  382. package/dist/settings/manager.test.js +0 -73
  383. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  384. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  385. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  386. package/dist/tool-system/builtin/send-message.js +0 -47
  387. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Map a raw error into a user-friendly message with a concrete next step
3
+ * (TODO 3.4). The turn loop emits `{type:"error", error}` to the UI; routing
4
+ * the message through here turns opaque provider strings ("401", "ETIMEDOUT")
5
+ * into something a user can act on. Pure + testable — no I/O.
6
+ *
7
+ * Heuristic, message-pattern based: we don't have typed error codes from every
8
+ * provider, so we match on substrings. Unknown errors pass through unchanged
9
+ * (with no suggestion) rather than getting a misleading canned message.
10
+ */
11
+ export interface FriendlyError {
12
+ message: string;
13
+ /** A concrete next step, or undefined when we have nothing useful to add. */
14
+ suggestion?: string;
15
+ }
16
+ export declare function friendlyError(err: unknown): FriendlyError;
17
+ /** One-line form: "<message> (<suggestion>)" — what the UI shows. */
18
+ export declare function formatFriendlyError(err: unknown): string;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Map a raw error into a user-friendly message with a concrete next step
3
+ * (TODO 3.4). The turn loop emits `{type:"error", error}` to the UI; routing
4
+ * the message through here turns opaque provider strings ("401", "ETIMEDOUT")
5
+ * into something a user can act on. Pure + testable — no I/O.
6
+ *
7
+ * Heuristic, message-pattern based: we don't have typed error codes from every
8
+ * provider, so we match on substrings. Unknown errors pass through unchanged
9
+ * (with no suggestion) rather than getting a misleading canned message.
10
+ */
11
+ const RULES = [
12
+ {
13
+ test: /\b(401|403|invalid api key|unauthorized|authentication)\b/i,
14
+ message: () => "Authentication failed — the API key was rejected.",
15
+ suggestion: "Check the provider's apiKey/authCommand in settings (run /login to reconfigure), then retry.",
16
+ },
17
+ {
18
+ test: /\b(429|rate.?limit|too many requests)\b/i,
19
+ message: () => "Rate limited by the provider.",
20
+ suggestion: "Wait a moment and retry, lower request frequency, or switch to a model with more headroom.",
21
+ },
22
+ {
23
+ test: /\b(timed? ?out|etimedout|esockettimedout|deadline)\b/i,
24
+ suggestion: "The request timed out — check your network, then retry. Long tasks can run in the background (run_in_background).",
25
+ },
26
+ {
27
+ test: /\b(econnrefused|enotfound|econnreset|network|fetch failed|socket hang up)\b/i,
28
+ message: () => "Network error reaching the provider.",
29
+ suggestion: "Check your connection and the provider baseUrl, then retry. Transient errors are retried automatically.",
30
+ },
31
+ {
32
+ test: /\bcontext (limit|length|window)|too long|maximum context|prompt is too long\b/i,
33
+ message: () => "The conversation exceeded the model's context window.",
34
+ suggestion: "Start a new session, /compact the history, or switch to a model with a larger context window.",
35
+ },
36
+ {
37
+ test: /\b(insufficient_quota|quota|billing|payment|credit)\b/i,
38
+ message: () => "The provider rejected the request for billing/quota reasons.",
39
+ suggestion: "Check the provider account's quota/billing, then retry.",
40
+ },
41
+ {
42
+ test: /\b(500|502|503|504|overloaded|server error|service unavailable)\b/i,
43
+ message: () => "The provider had a server-side error.",
44
+ suggestion: "This is usually transient — retry shortly, or switch models if it persists.",
45
+ },
46
+ ];
47
+ export function friendlyError(err) {
48
+ const raw = err instanceof Error ? err.message : typeof err === "string" ? err : String(err);
49
+ for (const rule of RULES) {
50
+ if (rule.test.test(raw)) {
51
+ return {
52
+ message: rule.message ? rule.message(raw) : raw,
53
+ suggestion: rule.suggestion,
54
+ };
55
+ }
56
+ }
57
+ return { message: raw };
58
+ }
59
+ /** One-line form: "<message> (<suggestion>)" — what the UI shows. */
60
+ export function formatFriendlyError(err) {
61
+ const f = friendlyError(err);
62
+ return f.suggestion ? `${f.message}\n→ ${f.suggestion}` : f.message;
63
+ }
@@ -17,13 +17,158 @@ export interface GoalConfig {
17
17
  tokenBudget?: number;
18
18
  /** Hard cap on wall-clock duration of the whole goal run, in ms. */
19
19
  timeBudgetMs?: number;
20
+ /**
21
+ * Hard cap on total turns for this goal run. When set, it overrides the
22
+ * engine's interactive maxTurns default — a goal ("keep going until done")
23
+ * routinely needs more turns than a single interactive prompt, and the
24
+ * stop-hook keeps re-blocking completion, so the 100-turn interactive
25
+ * ceiling would silently truncate a long unattended goal. Drops
26
+ * non-positive values to "no override". See GOAL_DEFAULT_MAX_TURNS for the
27
+ * fallback applied when a goal is active but no explicit cap was given.
28
+ */
29
+ maxTurns?: number;
30
+ /**
31
+ * Max CONSECUTIVE times the on_stop judge may block termination before the
32
+ * loop forces a stop (the "stuck on an unsatisfiable goal" backstop). A goal
33
+ * that keeps legitimately making progress resets this every accepted turn, so
34
+ * this only bites when the judge re-blocks over and over with no completion.
35
+ * Overrides GOAL_DEFAULT_MAX_STOP_BLOCKS. Non-positive values are dropped.
36
+ */
37
+ maxStopBlocks?: number;
38
+ /**
39
+ * Epoch-ms timestamp of when the user last set/replaced this goal. The judge
40
+ * uses it to anchor RELATIVE deadlines written in the objective ("做到3点"、
41
+ * "until 15:00"): a bare "3点" is read as the first such time AFTER the goal
42
+ * was set, not after "now" — otherwise, once the clock passes the deadline,
43
+ * the judge could misread it as tomorrow's 3点 and never stop. Stamped at the
44
+ * override site (Engine), preserved through normalize so a resumed/inherited
45
+ * goal keeps its original anchor. Absent for goals created before this field
46
+ * existed → the judge falls back to reasoning from current time alone.
47
+ */
48
+ setAtMs?: number;
20
49
  }
50
+ /**
51
+ * Default consecutive-stop-block cap for goal runs. The real safety net for an
52
+ * unattended goal is the token/time budget + maxTurns; this cap only stops a
53
+ * goal that the judge keeps re-blocking with NO progress between blocks. 8 was
54
+ * too tight — a complex goal can legitimately get "not yet" several times while
55
+ * advancing — so we allow a generous streak before declaring it stuck.
56
+ */
57
+ export declare const GOAL_DEFAULT_MAX_STOP_BLOCKS = 25;
58
+ /**
59
+ * Consecutive-stop-block cap for NON-goal (interactive) runs. The 25-block goal
60
+ * default is far too loose for a plain interactive session: a plugin `on_stop`
61
+ * hook that keeps returning continueSession would loop 25× before the backstop
62
+ * bites (~3× the model calls). Non-goal runs fall back to this tighter cap —
63
+ * the historical value before the goal feature raised the goal-mode default.
64
+ */
65
+ export declare const INTERACTIVE_DEFAULT_MAX_STOP_BLOCKS = 8;
66
+ /**
67
+ * Resolve the consecutive-stop-block cap for a run. Precedence:
68
+ * 1. explicit `configMaxStopBlocks` (engine/caller override)
69
+ * 2. `goal.maxStopBlocks`
70
+ * 3. GOAL_DEFAULT_MAX_STOP_BLOCKS when a goal is active,
71
+ * INTERACTIVE_DEFAULT_MAX_STOP_BLOCKS otherwise (don't leak the loose goal
72
+ * cap onto plain interactive runs — see B3 in the redesign doc).
73
+ * Pure + injectable so engine and tests agree.
74
+ */
75
+ export declare function resolveMaxStopBlocks(configMaxStopBlocks: number | undefined, goal: GoalConfig | undefined): number;
76
+ /**
77
+ * Turn ceiling applied when a goal is active and neither the GoalConfig nor
78
+ * the engine config set an explicit maxTurns. Higher than the interactive
79
+ * default (100) because goal runs are unattended and the stop-hook keeps the
80
+ * loop going until the objective is met — the real safety backstops are the
81
+ * token/time budgets and maxStopBlocks, not this ceiling. A round 300 gives
82
+ * long goals room while still bounding a pathological loop.
83
+ */
84
+ export declare const GOAL_DEFAULT_MAX_TURNS = 300;
21
85
  /**
22
86
  * Coerce a raw goal input into a normalized GoalConfig, or undefined when
23
87
  * there is effectively no goal (empty objective). Drops non-positive
24
88
  * budgets (0 / negative → "no limit", same as absent).
25
89
  */
26
90
  export declare function normalizeGoal(raw: string | GoalConfig | undefined): GoalConfig | undefined;
91
+ /**
92
+ * Decide the goal-set timestamp (setAtMs) to persist when a send supplies an
93
+ * explicit goal. Pure so the engine and tests agree on the anchor rule:
94
+ * - A NEW or CHANGED objective → stamp `nowMs` (the user just expressed a
95
+ * fresh goal; any relative deadline in it is anchored to now).
96
+ * - The SAME objective continuing (bare re-send inheriting the stored goal) →
97
+ * keep the stored anchor, so a re-send doesn't silently move the deadline.
98
+ * Falls back to `nowMs` if the stored goal predates this field.
99
+ * `stored` is the previously-persisted active goal (or undefined for the first
100
+ * goal on a session).
101
+ */
102
+ export declare function resolveGoalSetAt(explicitObjective: string, stored: GoalConfig | undefined, nowMs: number): number;
103
+ /** Interactive (no-goal) turn ceiling — a single prompt rarely needs more. */
104
+ export declare const INTERACTIVE_DEFAULT_MAX_TURNS = 100;
105
+ /**
106
+ * Resolve the turn ceiling for a run, honoring goal mode.
107
+ *
108
+ * Precedence (first defined wins):
109
+ * 1. `configMaxTurns` — an explicit engine/caller override (always wins).
110
+ * 2. `goal.maxTurns` — a per-goal cap from the GoalConfig.
111
+ * 3. `GOAL_DEFAULT_MAX_TURNS` when a goal is active (raise the unattended
112
+ * ceiling above the interactive default).
113
+ * 4. `INTERACTIVE_DEFAULT_MAX_TURNS` otherwise.
114
+ *
115
+ * Pure + injectable so the engine and tests agree on the rule.
116
+ */
117
+ export declare function resolveMaxTurns(configMaxTurns: number | undefined, goal: GoalConfig | undefined): number;
118
+ /**
119
+ * How close a run is to either hard ceiling. Both maxTurns and maxStopBlocks
120
+ * can force-stop a goal, so the "approaching limit" UX must watch BOTH — the
121
+ * old code only watched maxTurns (turnsRemaining===2), but a re-blocked goal
122
+ * almost always hits the much-tighter stop-block cap first. See redesign doc.
123
+ */
124
+ export interface LimitProximity {
125
+ /** Turns left before maxTurns (maxTurns - turnCount). */
126
+ turnsRemaining: number;
127
+ /** Consecutive blocks left before maxStopBlocks (cap - stopBlockCount). */
128
+ stopBlocksRemaining: number;
129
+ /** True when EITHER dimension is within its approach threshold. */
130
+ approaching: boolean;
131
+ /** Which ceiling is closest — drives UI copy and the extend default. */
132
+ nearest: "turns" | "stopBlocks";
133
+ }
134
+ /** Warn when this many turns (or fewer) remain before maxTurns. */
135
+ export declare const APPROACH_TURNS = 5;
136
+ /** Warn when this many consecutive blocks (or fewer) remain before the cap. */
137
+ export declare const APPROACH_STOP_BLOCKS = 3;
138
+ /**
139
+ * Compute proximity to the two stop ceilings. Pure so turn-loop and tests
140
+ * agree. `nearest` favors stopBlocks when both are near, because the stop-block
141
+ * cap (default 25) is reached far sooner than maxTurns (default 300) for a
142
+ * goal the judge keeps re-blocking — it's the limit that actually bites.
143
+ */
144
+ export declare function limitProximity(turnCount: number, maxTurns: number, stopBlockCount: number, maxStopBlocks: number): LimitProximity;
145
+ export interface GoalExtension {
146
+ addTurns?: number;
147
+ addTokenBudget?: number;
148
+ addTimeBudgetMs?: number;
149
+ /** Raise the consecutive-stop-block cap — the limit that usually bites. */
150
+ addStopBlocks?: number;
151
+ }
152
+ /**
153
+ * Compute the new turn ceiling + goal budgets after a mid-run extension
154
+ * (TODO 3.1). Pure so the TurnLoop and tests agree on the arithmetic:
155
+ * - addTurns bumps the maxTurns ceiling (floored, positive only).
156
+ * - addTokenBudget/addTimeBudgetMs raise the goal's caps. When a cap was
157
+ * previously unset ("unlimited"), we seed it from CURRENT USAGE before
158
+ * adding — `tokensUsed` for tokens, `elapsedMs` for time — so extending an
159
+ * unbounded run sets a fresh cap ABOVE current usage rather than below it.
160
+ * (Seeding time from 0 was bug B1: a long-running unbounded goal would get
161
+ * a cap below its elapsed time and force-stop immediately on extend.)
162
+ * - addStopBlocks is handled by the caller (TurnLoop.extend) against the live
163
+ * config, not here, since it isn't part of the goal budget shape.
164
+ * `tokensUsed`/`elapsedMs` are the tracker's running totals (used only to seed
165
+ * unset caps). Returns the resulting limits; never mutates its inputs.
166
+ */
167
+ export declare function applyGoalExtension(currentMaxTurns: number, goal: GoalConfig | undefined, tokensUsed: number, elapsedMs: number, ext: GoalExtension): {
168
+ maxTurns: number;
169
+ tokenBudget?: number;
170
+ timeBudgetMs?: number;
171
+ };
27
172
  export interface GoalBudgetTracker {
28
173
  goal: GoalConfig;
29
174
  /** Wall-clock start (ms epoch), captured at run start. */
@@ -10,6 +10,48 @@
10
10
  * it accumulates total tokens across turns and stamps a wall-clock start,
11
11
  * so an unattended goal run can't burn tokens or wall time without bound.
12
12
  */
13
+ /**
14
+ * Default consecutive-stop-block cap for goal runs. The real safety net for an
15
+ * unattended goal is the token/time budget + maxTurns; this cap only stops a
16
+ * goal that the judge keeps re-blocking with NO progress between blocks. 8 was
17
+ * too tight — a complex goal can legitimately get "not yet" several times while
18
+ * advancing — so we allow a generous streak before declaring it stuck.
19
+ */
20
+ export const GOAL_DEFAULT_MAX_STOP_BLOCKS = 25;
21
+ /**
22
+ * Consecutive-stop-block cap for NON-goal (interactive) runs. The 25-block goal
23
+ * default is far too loose for a plain interactive session: a plugin `on_stop`
24
+ * hook that keeps returning continueSession would loop 25× before the backstop
25
+ * bites (~3× the model calls). Non-goal runs fall back to this tighter cap —
26
+ * the historical value before the goal feature raised the goal-mode default.
27
+ */
28
+ export const INTERACTIVE_DEFAULT_MAX_STOP_BLOCKS = 8;
29
+ /**
30
+ * Resolve the consecutive-stop-block cap for a run. Precedence:
31
+ * 1. explicit `configMaxStopBlocks` (engine/caller override)
32
+ * 2. `goal.maxStopBlocks`
33
+ * 3. GOAL_DEFAULT_MAX_STOP_BLOCKS when a goal is active,
34
+ * INTERACTIVE_DEFAULT_MAX_STOP_BLOCKS otherwise (don't leak the loose goal
35
+ * cap onto plain interactive runs — see B3 in the redesign doc).
36
+ * Pure + injectable so engine and tests agree.
37
+ */
38
+ export function resolveMaxStopBlocks(configMaxStopBlocks, goal) {
39
+ if (typeof configMaxStopBlocks === "number" && configMaxStopBlocks > 0) {
40
+ return Math.floor(configMaxStopBlocks);
41
+ }
42
+ if (goal?.maxStopBlocks && goal.maxStopBlocks > 0)
43
+ return goal.maxStopBlocks;
44
+ return goal ? GOAL_DEFAULT_MAX_STOP_BLOCKS : INTERACTIVE_DEFAULT_MAX_STOP_BLOCKS;
45
+ }
46
+ /**
47
+ * Turn ceiling applied when a goal is active and neither the GoalConfig nor
48
+ * the engine config set an explicit maxTurns. Higher than the interactive
49
+ * default (100) because goal runs are unattended and the stop-hook keeps the
50
+ * loop going until the objective is met — the real safety backstops are the
51
+ * token/time budgets and maxStopBlocks, not this ceiling. A round 300 gives
52
+ * long goals room while still bounding a pathological loop.
53
+ */
54
+ export const GOAL_DEFAULT_MAX_TURNS = 300;
13
55
  /**
14
56
  * Coerce a raw goal input into a normalized GoalConfig, or undefined when
15
57
  * there is effectively no goal (empty objective). Drops non-positive
@@ -27,8 +69,110 @@ export function normalizeGoal(raw) {
27
69
  out.tokenBudget = obj.tokenBudget;
28
70
  if (typeof obj.timeBudgetMs === "number" && obj.timeBudgetMs > 0)
29
71
  out.timeBudgetMs = obj.timeBudgetMs;
72
+ if (typeof obj.maxTurns === "number" && obj.maxTurns > 0)
73
+ out.maxTurns = Math.floor(obj.maxTurns);
74
+ if (typeof obj.maxStopBlocks === "number" && obj.maxStopBlocks > 0) {
75
+ out.maxStopBlocks = Math.floor(obj.maxStopBlocks);
76
+ }
77
+ // Preserve a positive goal-set timestamp so a resumed/inherited goal keeps
78
+ // the anchor for relative deadlines. Non-positive/junk is dropped, matching
79
+ // the budget fields (a bogus anchor is worse than none).
80
+ if (typeof obj.setAtMs === "number" && obj.setAtMs > 0)
81
+ out.setAtMs = obj.setAtMs;
30
82
  return out;
31
83
  }
84
+ /**
85
+ * Decide the goal-set timestamp (setAtMs) to persist when a send supplies an
86
+ * explicit goal. Pure so the engine and tests agree on the anchor rule:
87
+ * - A NEW or CHANGED objective → stamp `nowMs` (the user just expressed a
88
+ * fresh goal; any relative deadline in it is anchored to now).
89
+ * - The SAME objective continuing (bare re-send inheriting the stored goal) →
90
+ * keep the stored anchor, so a re-send doesn't silently move the deadline.
91
+ * Falls back to `nowMs` if the stored goal predates this field.
92
+ * `stored` is the previously-persisted active goal (or undefined for the first
93
+ * goal on a session).
94
+ */
95
+ export function resolveGoalSetAt(explicitObjective, stored, nowMs) {
96
+ const sameGoalContinues = !!stored && stored.objective === explicitObjective;
97
+ return sameGoalContinues ? stored.setAtMs ?? nowMs : nowMs;
98
+ }
99
+ /** Interactive (no-goal) turn ceiling — a single prompt rarely needs more. */
100
+ export const INTERACTIVE_DEFAULT_MAX_TURNS = 100;
101
+ /**
102
+ * Resolve the turn ceiling for a run, honoring goal mode.
103
+ *
104
+ * Precedence (first defined wins):
105
+ * 1. `configMaxTurns` — an explicit engine/caller override (always wins).
106
+ * 2. `goal.maxTurns` — a per-goal cap from the GoalConfig.
107
+ * 3. `GOAL_DEFAULT_MAX_TURNS` when a goal is active (raise the unattended
108
+ * ceiling above the interactive default).
109
+ * 4. `INTERACTIVE_DEFAULT_MAX_TURNS` otherwise.
110
+ *
111
+ * Pure + injectable so the engine and tests agree on the rule.
112
+ */
113
+ export function resolveMaxTurns(configMaxTurns, goal) {
114
+ if (typeof configMaxTurns === "number" && configMaxTurns > 0)
115
+ return configMaxTurns;
116
+ if (goal)
117
+ return goal.maxTurns ?? GOAL_DEFAULT_MAX_TURNS;
118
+ return INTERACTIVE_DEFAULT_MAX_TURNS;
119
+ }
120
+ /** Warn when this many turns (or fewer) remain before maxTurns. */
121
+ export const APPROACH_TURNS = 5;
122
+ /** Warn when this many consecutive blocks (or fewer) remain before the cap. */
123
+ export const APPROACH_STOP_BLOCKS = 3;
124
+ /**
125
+ * Compute proximity to the two stop ceilings. Pure so turn-loop and tests
126
+ * agree. `nearest` favors stopBlocks when both are near, because the stop-block
127
+ * cap (default 25) is reached far sooner than maxTurns (default 300) for a
128
+ * goal the judge keeps re-blocking — it's the limit that actually bites.
129
+ */
130
+ export function limitProximity(turnCount, maxTurns, stopBlockCount, maxStopBlocks) {
131
+ const turnsRemaining = maxTurns - turnCount;
132
+ const stopBlocksRemaining = maxStopBlocks - stopBlockCount;
133
+ const turnsNear = turnsRemaining <= APPROACH_TURNS;
134
+ const blocksNear = stopBlocksRemaining <= APPROACH_STOP_BLOCKS;
135
+ return {
136
+ turnsRemaining,
137
+ stopBlocksRemaining,
138
+ approaching: turnsNear || blocksNear,
139
+ nearest: blocksNear ? "stopBlocks" : "turns",
140
+ };
141
+ }
142
+ /**
143
+ * Compute the new turn ceiling + goal budgets after a mid-run extension
144
+ * (TODO 3.1). Pure so the TurnLoop and tests agree on the arithmetic:
145
+ * - addTurns bumps the maxTurns ceiling (floored, positive only).
146
+ * - addTokenBudget/addTimeBudgetMs raise the goal's caps. When a cap was
147
+ * previously unset ("unlimited"), we seed it from CURRENT USAGE before
148
+ * adding — `tokensUsed` for tokens, `elapsedMs` for time — so extending an
149
+ * unbounded run sets a fresh cap ABOVE current usage rather than below it.
150
+ * (Seeding time from 0 was bug B1: a long-running unbounded goal would get
151
+ * a cap below its elapsed time and force-stop immediately on extend.)
152
+ * - addStopBlocks is handled by the caller (TurnLoop.extend) against the live
153
+ * config, not here, since it isn't part of the goal budget shape.
154
+ * `tokensUsed`/`elapsedMs` are the tracker's running totals (used only to seed
155
+ * unset caps). Returns the resulting limits; never mutates its inputs.
156
+ */
157
+ export function applyGoalExtension(currentMaxTurns, goal, tokensUsed, elapsedMs, ext) {
158
+ let maxTurns = currentMaxTurns;
159
+ if (typeof ext.addTurns === "number" && ext.addTurns > 0) {
160
+ maxTurns += Math.floor(ext.addTurns);
161
+ }
162
+ let tokenBudget = goal?.tokenBudget;
163
+ let timeBudgetMs = goal?.timeBudgetMs;
164
+ if (goal) {
165
+ if (typeof ext.addTokenBudget === "number" && ext.addTokenBudget > 0) {
166
+ tokenBudget = (tokenBudget ?? tokensUsed) + Math.floor(ext.addTokenBudget);
167
+ }
168
+ if (typeof ext.addTimeBudgetMs === "number" && ext.addTimeBudgetMs > 0) {
169
+ // Seed an unset cap from elapsed time (not 0), mirroring the token branch,
170
+ // so the new cap lands above current usage. Fixes B1.
171
+ timeBudgetMs = (timeBudgetMs ?? elapsedMs) + Math.floor(ext.addTimeBudgetMs);
172
+ }
173
+ }
174
+ return { maxTurns, tokenBudget, timeBudgetMs };
175
+ }
32
176
  /** Create a run-scoped tracker. `nowMs` is injected for testability. */
33
177
  export function createGoalBudgetTracker(goal, nowMs) {
34
178
  return { goal, startedAtMs: nowMs, tokensUsed: 0 };
@@ -150,3 +150,16 @@ export interface DropOversizedResult {
150
150
  }
151
151
  export declare function dropOversizedImages(images: readonly ParsedImage[]): DropOversizedResult;
152
152
  export declare function enforceImagePolicy(images: readonly ParsedImage[]): ImagePolicyVerdict;
153
+ /**
154
+ * Collect the workspace file paths of any attached images that came from a
155
+ * real file (the desktop composer's path-attach flow sets ParsedImage.name to
156
+ * the absolute path). Pasted screenshots whose name is a bare filename, or any
157
+ * name that doesn't resolve to an existing file, are excluded.
158
+ *
159
+ * Pure given an `exists` predicate + `resolve` joiner, so it's unit-testable
160
+ * without touching the real fs. The engine passes `existsSync` and a
161
+ * cwd-aware joiner; downstream this surfaces the paths to the model so tools
162
+ * like GenerateImage(referenceImages) can use them (the path the composer
163
+ * already knew was otherwise dropped on the way to the LLM).
164
+ */
165
+ export declare function collectAttachedImagePaths(images: ReadonlyArray<ParsedImage>, resolve: (name: string) => string, exists: (absPath: string) => boolean): string[];
@@ -163,3 +163,27 @@ export function enforceImagePolicy(images) {
163
163
  }
164
164
  return { ok: true };
165
165
  }
166
+ /**
167
+ * Collect the workspace file paths of any attached images that came from a
168
+ * real file (the desktop composer's path-attach flow sets ParsedImage.name to
169
+ * the absolute path). Pasted screenshots whose name is a bare filename, or any
170
+ * name that doesn't resolve to an existing file, are excluded.
171
+ *
172
+ * Pure given an `exists` predicate + `resolve` joiner, so it's unit-testable
173
+ * without touching the real fs. The engine passes `existsSync` and a
174
+ * cwd-aware joiner; downstream this surfaces the paths to the model so tools
175
+ * like GenerateImage(referenceImages) can use them (the path the composer
176
+ * already knew was otherwise dropped on the way to the LLM).
177
+ */
178
+ export function collectAttachedImagePaths(images, resolve, exists) {
179
+ const out = [];
180
+ for (const img of images) {
181
+ const name = img.name?.trim();
182
+ if (!name)
183
+ continue;
184
+ const abs = resolve(name);
185
+ if (exists(abs))
186
+ out.push(abs);
187
+ }
188
+ return out;
189
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Bridge settings.modelConnections[] (the unified instance store) into
3
+ * ModelPool entries, so the engine sends requests using the new catalog-driven
4
+ * model selection. Pure: instances + catalog → ModelEntry[]. apiKeyRef is
5
+ * dereferenced via resolveInstance; protocol/baseUrl/token limits come from the
6
+ * resolved catalog entry + preset.
7
+ * See docs/superpowers/specs/2026-06-15-unified-model-catalog-design.md §6.
8
+ */
9
+ import { type ModelInstance, type Credential } from "../model-catalog/resolve.js";
10
+ import type { CatalogEntry } from "../model-catalog/index.js";
11
+ import type { ModelEntry } from "../llm/model-pool.js";
12
+ export type { ModelInstance, Credential } from "../model-catalog/resolve.js";
13
+ /**
14
+ * Convert text model connections into ModelPool register entries. Non-text
15
+ * instances and ones whose catalogId doesn't resolve are skipped.
16
+ */
17
+ export declare function modelEntriesFromConnections(connections: ModelInstance[], credentials: Credential[], catalog: CatalogEntry[]): ModelEntry[];
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Bridge settings.modelConnections[] (the unified instance store) into
3
+ * ModelPool entries, so the engine sends requests using the new catalog-driven
4
+ * model selection. Pure: instances + catalog → ModelEntry[]. apiKeyRef is
5
+ * dereferenced via resolveInstance; protocol/baseUrl/token limits come from the
6
+ * resolved catalog entry + preset.
7
+ * See docs/superpowers/specs/2026-06-15-unified-model-catalog-design.md §6.
8
+ */
9
+ import { resolveInstance } from "../model-catalog/resolve.js";
10
+ import { applyParams } from "../model-catalog/params.js";
11
+ /** Map a catalog entry's protocol to the ModelPool `provider` (LLM client). */
12
+ function clientProvider(entry) {
13
+ return entry.protocol === "anthropic-style" ? "anthropic" : "openai";
14
+ }
15
+ /**
16
+ * Map a connection's `paramValues.reasoning` to the engine's ReasoningSetting,
17
+ * so the new param store flows through the existing reasoning request pipeline
18
+ * (no new request-layer plumbing). enum→effort, number→budget, boolean→on/off.
19
+ */
20
+ function reasoningFromParamValues(paramValues) {
21
+ const v = paramValues?.reasoning;
22
+ if (typeof v === "string") {
23
+ return { mode: "effort", effort: v };
24
+ }
25
+ if (typeof v === "number")
26
+ return { mode: "budget", budgetTokens: v };
27
+ if (typeof v === "boolean")
28
+ return v ? { mode: "on" } : { mode: "off" };
29
+ return undefined;
30
+ }
31
+ /**
32
+ * Convert text model connections into ModelPool register entries. Non-text
33
+ * instances and ones whose catalogId doesn't resolve are skipped.
34
+ */
35
+ export function modelEntriesFromConnections(connections, credentials, catalog) {
36
+ const out = [];
37
+ for (const inst of connections) {
38
+ if (inst.tag !== "text")
39
+ continue;
40
+ const resolved = resolveInstance(inst, credentials, catalog);
41
+ if (!resolved)
42
+ continue;
43
+ const { entry, preset } = resolved;
44
+ const reasoning = reasoningFromParamValues(inst.paramValues);
45
+ // Generic param passthrough: map the connection's paramValues to request-body
46
+ // fields via each ParamSpec's wire.field. Exclude `reasoning` — it rides the
47
+ // dedicated entry.reasoning path (per-model dynamic translation in the client);
48
+ // emitting it here too would double-send it.
49
+ const passthroughParams = (preset?.params ?? []).filter((p) => p.name !== "reasoning");
50
+ const extraBody = applyParams(inst.paramValues ?? {}, passthroughParams);
51
+ const e = {
52
+ key: inst.id,
53
+ provider: clientProvider(entry),
54
+ model: resolved.model,
55
+ baseUrl: resolved.baseUrl,
56
+ needsKey: resolved.needsKey,
57
+ ...(resolved.apiKey !== undefined ? { apiKey: resolved.apiKey } : {}),
58
+ ...(preset?.maxContextTokens !== undefined ? { maxContextTokens: preset.maxContextTokens } : {}),
59
+ ...(preset?.maxOutputTokens !== undefined ? { maxOutputTokens: preset.maxOutputTokens } : {}),
60
+ ...(reasoning !== undefined ? { reasoning } : {}),
61
+ ...(Object.keys(extraBody).length > 0 ? { extraBody } : {}),
62
+ };
63
+ out.push(e);
64
+ }
65
+ return out;
66
+ }
@@ -4,6 +4,16 @@
4
4
  import type { LLMClientBase } from "../llm/client-base.js";
5
5
  import type { Message, ToolDefinition, LLMResponse, StreamCallback } from "../types.js";
6
6
  import { Transcript } from "../session/transcript.js";
7
+ /**
8
+ * Prompt-cache hit rate for one request, as CC computes it:
9
+ * cacheRead / (cacheRead + cacheCreation + uncachedInput)
10
+ * where uncachedInput = promptTokens − cacheRead − cacheCreation (promptTokens
11
+ * already includes the cached portion). Returns undefined when the provider
12
+ * reported no cache info at all, so `llm.request` only carries the field when
13
+ * it's meaningful. Makes hit-rate observable in logs — the prerequisite for
14
+ * any caching tuning (docs/todo/prompt-cache-optimization.md §四 step 1).
15
+ */
16
+ export declare function cacheHitRate(usage: LLMResponse["usage"]): number | undefined;
7
17
  export declare class ModelFacade {
8
18
  private readonly client;
9
19
  private readonly transcript;
@@ -10,6 +10,29 @@ function nextReqId() {
10
10
  _reqSeq += 1;
11
11
  return `r${_reqSeq.toString(36)}`;
12
12
  }
13
+ /**
14
+ * Prompt-cache hit rate for one request, as CC computes it:
15
+ * cacheRead / (cacheRead + cacheCreation + uncachedInput)
16
+ * where uncachedInput = promptTokens − cacheRead − cacheCreation (promptTokens
17
+ * already includes the cached portion). Returns undefined when the provider
18
+ * reported no cache info at all, so `llm.request` only carries the field when
19
+ * it's meaningful. Makes hit-rate observable in logs — the prerequisite for
20
+ * any caching tuning (docs/todo/prompt-cache-optimization.md §四 step 1).
21
+ */
22
+ export function cacheHitRate(usage) {
23
+ if (!usage)
24
+ return undefined;
25
+ const read = usage.cacheReadTokens ?? 0;
26
+ const creation = usage.cacheCreationTokens ?? 0;
27
+ if (read === 0 && creation === 0)
28
+ return undefined;
29
+ const prompt = usage.promptTokens ?? 0;
30
+ const uncached = Math.max(0, prompt - read - creation);
31
+ const denom = read + creation + uncached;
32
+ if (denom === 0)
33
+ return undefined;
34
+ return read / denom;
35
+ }
13
36
  export class ModelFacade {
14
37
  client;
15
38
  transcript;
@@ -82,6 +105,7 @@ export class ModelFacade {
82
105
  toolCalls: response.toolCalls.length,
83
106
  textLen: response.text?.length ?? 0,
84
107
  usage: response.usage,
108
+ cacheHitRate: cacheHitRate(response.usage),
85
109
  });
86
110
  recordLLMResponse(sid, {
87
111
  text: response.text,
@@ -135,6 +159,7 @@ export class ModelFacade {
135
159
  toolCalls: response.toolCalls.length,
136
160
  textLen: response.text?.length ?? 0,
137
161
  usage: response.usage,
162
+ cacheHitRate: cacheHitRate(response.usage),
138
163
  });
139
164
  recordLLMResponse(sid, {
140
165
  text: response.text,
@@ -79,6 +79,9 @@ export function patchOrphanedToolUses(messages) {
79
79
  type: "tool_result",
80
80
  tool_use_id: id,
81
81
  content: SYNTHETIC_ERROR_TEXT,
82
+ // Flag as an error so the Anthropic provider marks it is_error; otherwise
83
+ // the model reads the synthetic result as a successful tool output.
84
+ is_error: true,
82
85
  }));
83
86
  messages.splice(i + 1, 0, { role: "user", content: errorBlocks });
84
87
  // Mark these ids answered so a later assistant message referencing
@@ -0,0 +1,16 @@
1
+ /**
2
+ * resolveLLMConfigForTag — 单一入口:settings + tag + 可选偏好实例 id → LLMConfig。
3
+ * 所有非-engine 的 seed 场景(agent-server bootstrap / automation / dream / TUI
4
+ * 命令)都调它,避免各自手搓 { provider: settings.model.provider, ... }。
5
+ *
6
+ * 复用 modelEntriesFromConnections + 临时 ModelPool.toLLMConfig,与 engine 内部
7
+ * 长生命周期 pool 共享同一批零件,不逻辑分叉。
8
+ *
9
+ * 选择优先级:preferredId(命中才用)→ defaults[tag] → 首个可用连接。
10
+ * 返回 null = 该 tag 下没有任何可用连接,调用方据此抛明确错误。
11
+ *
12
+ * 本次只处理 text;image/video 已有独立 resolver(resolveImageProvider 等)。
13
+ */
14
+ import type { LLMConfig } from "../types.js";
15
+ import type { ValidatedSettings } from "../settings/schema.js";
16
+ export declare function resolveLLMConfigForTag(settings: ValidatedSettings, tag: "text", preferredInstanceId?: string): LLMConfig | null;