@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
@@ -23,6 +23,7 @@ import { ChatSessionManager } from "../protocol/chat-session-manager.js";
23
23
  import { AgentServer } from "../protocol/server.js";
24
24
  import { listenTcp } from "../protocol/tcp-transport.js";
25
25
  import { SettingsManager } from "../settings/manager.js";
26
+ import { computeEffectiveDisabledLists } from "../capability-control/disabled-lists.js";
26
27
  import { personalizationFrom } from "../settings/personalization.js";
27
28
  import { MCPManager } from "../tool-system/mcp-manager.js";
28
29
  import { mergePluginMcpServers } from "../plugins/installer/loadPluginMcp.js";
@@ -31,18 +32,24 @@ import { HeadlessApprovalBackend } from "../tool-system/permission.js";
31
32
  import { createRunManager } from "../run/factory.js";
32
33
  import { startAutomation } from "../automation/index.js";
33
34
  import { CronStore, defaultCronStorePath } from "../automation/store.js";
35
+ import { resolveLLMConfigForTag } from "../engine/resolve-llm-config.js";
34
36
  const cwd = process.env.AGENT_CWD ?? process.cwd();
35
37
  const port = Number(process.env.AGENT_TCP_PORT ?? "4321");
36
38
  const host = process.env.AGENT_TCP_HOST ?? "127.0.0.1";
37
39
  const settingsManager = new SettingsManager(cwd, "full");
40
+ // Read once at startup and reuse for every session (see engineFactory below).
41
+ // This is intentional for the TCP host: it's a headless long-running server,
42
+ // so config changes — including `mcpServers` — take effect on restart, not
43
+ // mid-session. (The stdio host re-reads per session via freshSettings(); the
44
+ // difference is by design, not a bug. Assessment §4.8.)
38
45
  const settings = settingsManager.get();
39
- const llmConfig = {
40
- provider: settings.model.provider,
41
- model: settings.model.name,
42
- apiKey: settings.model.apiKey ?? "",
43
- baseUrl: settings.model.baseUrl,
44
- maxTokens: settings.model.maxTokens,
45
- };
46
+ const seedLlm = resolveLLMConfigForTag(settings, "text", settings.defaults?.text);
47
+ if (!seedLlm) {
48
+ console.error(`[agent-server] 没有可用的文本模型连接(defaults.text=${settings.defaults?.text ?? "未设置"})。` +
49
+ `请在「连接」页添加并填写凭证。`);
50
+ process.exit(1);
51
+ }
52
+ const llmConfig = seedLlm;
46
53
  // ── Shared runtime (same bootstrap as stdio) ─────────────────────
47
54
  const seedEngine = new Engine({ llm: llmConfig, cwd, settingsScope: "full" });
48
55
  const modelPool = seedEngine.getModelPool();
@@ -60,25 +67,32 @@ const runtime = new EngineRuntime({
60
67
  });
61
68
  const chatManager = new ChatSessionManager({
62
69
  runtime,
63
- engineFactory: (slice) => new Engine({
64
- llm: runtime.modelPool.resolveLLMConfig() ?? resolvedLlmConfig,
65
- clientDefaults: resolvedClientDefaults,
66
- cwd,
67
- runtime,
68
- settingsScope: "full",
69
- mcpServers: mergePluginMcpServers(settings.mcpServers ?? {}, settings.disabledPlugins ?? []),
70
- permissionMode: slice.permissionMode,
71
- preset: slice.preset,
72
- customSystemPrompt: slice.customSystemPrompt,
73
- appendSystemPrompt: slice.appendSystemPrompt,
74
- // Personalization + instruction compat come from disk settings only
75
- // (not per-request slice overrides) same disk-only contract as the
76
- // stdio host. Shared helper keeps the three fields wired identically.
77
- ...personalizationFrom(settings.agent),
78
- maxTurns: slice.maxTurns,
79
- maxContextTokens: slice.maxContextTokens,
80
- ...(slice.cwd ? { cwd: slice.cwd } : {}),
81
- }),
70
+ engineFactory: (slice) => {
71
+ // Fold project capabilityOverrides over the global disabledPlugins for
72
+ // the MCP merge (能力总览 project "on" must override global off) — same
73
+ // contract as the stdio host's factory.
74
+ const sessionCwd = slice.cwd ?? cwd;
75
+ const { disabledPlugins } = computeEffectiveDisabledLists(new SettingsManager(sessionCwd, "full"), sessionCwd);
76
+ return new Engine({
77
+ llm: runtime.modelPool.resolveLLMConfig() ?? resolvedLlmConfig,
78
+ clientDefaults: resolvedClientDefaults,
79
+ cwd,
80
+ runtime,
81
+ settingsScope: "full",
82
+ mcpServers: mergePluginMcpServers(settings.mcpServers ?? {}, disabledPlugins, settings.mcpServerOverrides ?? {}),
83
+ permissionMode: slice.permissionMode,
84
+ preset: slice.preset,
85
+ customSystemPrompt: slice.customSystemPrompt,
86
+ appendSystemPrompt: slice.appendSystemPrompt,
87
+ // Personalization + instruction compat come from disk settings only
88
+ // (not per-request slice overrides) — same disk-only contract as the
89
+ // stdio host. Shared helper keeps the three fields wired identically.
90
+ ...personalizationFrom(settings.agent),
91
+ maxTurns: slice.maxTurns,
92
+ maxContextTokens: slice.maxContextTokens,
93
+ ...(slice.cwd ? { cwd: slice.cwd } : {}),
94
+ });
95
+ },
82
96
  maxSessions: 16,
83
97
  idleTtlMs: 30 * 60 * 1000,
84
98
  });
@@ -16,6 +16,25 @@ import type { Message } from "../types.js";
16
16
  * Uses per-block-type estimation with 33% overhead padding.
17
17
  */
18
18
  export declare function estimateTokens(messages: Message[]): number;
19
+ /**
20
+ * Reconcile user-supplied compaction ratios into a safe ordering.
21
+ *
22
+ * The three tiers must satisfy `floor < compact < summarize` or the manager
23
+ * fires them in the wrong order (e.g. an emergency window-compact before the
24
+ * cheaper summary). Users edit these freely in settings.json, so we clamp
25
+ * rather than trust: summarize is pulled up to at least compact, floor is
26
+ * pushed down to at most compact. Absent fields are left undefined so the
27
+ * ContextManager keeps its own default for them.
28
+ */
29
+ export declare function clampContextRatios(input: {
30
+ compactAtRatio?: number;
31
+ summarizeAtRatio?: number;
32
+ microcompactFloorRatio?: number;
33
+ }): {
34
+ compactAtRatio?: number;
35
+ summarizeAtRatio?: number;
36
+ microcompactFloorRatio?: number;
37
+ };
19
38
  /**
20
39
  * Expand a slice start-index backwards so that every tool_result in the
21
40
  * kept range has its corresponding tool_use in the kept range too.
@@ -74,6 +93,43 @@ export interface MicrocompactOptions {
74
93
  * forced into blind re-Reads (which then trip the Investigation guard).
75
94
  */
76
95
  export declare function microcompact(messages: Message[], options?: MicrocompactOptions): Message[];
96
+ export interface DedupeFileReadsResult {
97
+ messages: Message[];
98
+ /** How many stale Read results were cleared. */
99
+ clearedCount: number;
100
+ }
101
+ /**
102
+ * Content-aware dedup: when the SAME file is Read more than once, every Read
103
+ * result except the most recent is stale — the file's current state is in the
104
+ * latest read. Clear the older ones (replace with a fingerprint pointing at
105
+ * the newer read) regardless of the recency window or pressure floor, because
106
+ * this is pure waste removal, not lossy compaction: the model never needs two
107
+ * copies of the same file.
108
+ *
109
+ * Distinct from microcompact (which is recency-gated and pressure-gated): a
110
+ * file Read 3 times in the last 3 turns keeps 3 full copies under microcompact
111
+ * but only the newest under this pass. Zero-cost and always safe to run, so the
112
+ * ContextManager calls it as an early tier.
113
+ *
114
+ * Only `Read` is deduped (its result is exactly the file content). Edit/Write
115
+ * results are diffs/confirmations, not full snapshots, so they're left alone.
116
+ */
117
+ export declare function dedupeFileReads(messages: Message[]): DedupeFileReadsResult;
118
+ /**
119
+ * Observation masking for browser_observe(snapshot) results (the research's
120
+ * highest-leverage browser-token saving: a page snapshot is large and only the
121
+ * LATEST one matters for the next decision; older ones are stale element lists).
122
+ * Keep the most recent snapshot result verbatim; replace every earlier one with
123
+ * a one-line placeholder. Deterministic — no LLM summarization needed.
124
+ *
125
+ * Keyed on the snapshot OBSERVATION (browser_observe with mode snapshot) — read/
126
+ * extract observations and act results are left untouched. Renamed from
127
+ * maskOldBrowserSnapshots when the 9 browser_* tools collapsed into 3.
128
+ */
129
+ export declare function maskOldObservations(messages: Message[]): {
130
+ messages: Message[];
131
+ maskedCount: number;
132
+ };
77
133
  /**
78
134
  * Apply aggregate per-message tool result budget.
79
135
  * When total tool_result content in a single message exceeds maxTotalChars,
@@ -18,6 +18,30 @@ import { estimateMessagesTokens } from "./token-counter.js";
18
18
  export function estimateTokens(messages) {
19
19
  return Math.ceil(estimateMessagesTokens(messages) * (4 / 3));
20
20
  }
21
+ /**
22
+ * Reconcile user-supplied compaction ratios into a safe ordering.
23
+ *
24
+ * The three tiers must satisfy `floor < compact < summarize` or the manager
25
+ * fires them in the wrong order (e.g. an emergency window-compact before the
26
+ * cheaper summary). Users edit these freely in settings.json, so we clamp
27
+ * rather than trust: summarize is pulled up to at least compact, floor is
28
+ * pushed down to at most compact. Absent fields are left undefined so the
29
+ * ContextManager keeps its own default for them.
30
+ */
31
+ export function clampContextRatios(input) {
32
+ const compact = input.compactAtRatio;
33
+ const summarize = input.summarizeAtRatio !== undefined && compact !== undefined
34
+ ? Math.max(input.summarizeAtRatio, compact)
35
+ : input.summarizeAtRatio;
36
+ const floor = input.microcompactFloorRatio !== undefined && compact !== undefined
37
+ ? Math.min(input.microcompactFloorRatio, compact)
38
+ : input.microcompactFloorRatio;
39
+ return {
40
+ compactAtRatio: compact,
41
+ summarizeAtRatio: summarize,
42
+ microcompactFloorRatio: floor,
43
+ };
44
+ }
21
45
  // ─── Tool Use / Result Pair Protection ──────────────────────────────
22
46
  /**
23
47
  * Expand a slice start-index backwards so that every tool_result in the
@@ -275,6 +299,168 @@ export function microcompact(messages, options = {}) {
275
299
  }
276
300
  return result;
277
301
  }
302
+ /** Tools whose result is the content of a single file, keyed by path. */
303
+ const FILE_READ_TOOLS = new Set(["Read"]);
304
+ /**
305
+ * Content-aware dedup: when the SAME file is Read more than once, every Read
306
+ * result except the most recent is stale — the file's current state is in the
307
+ * latest read. Clear the older ones (replace with a fingerprint pointing at
308
+ * the newer read) regardless of the recency window or pressure floor, because
309
+ * this is pure waste removal, not lossy compaction: the model never needs two
310
+ * copies of the same file.
311
+ *
312
+ * Distinct from microcompact (which is recency-gated and pressure-gated): a
313
+ * file Read 3 times in the last 3 turns keeps 3 full copies under microcompact
314
+ * but only the newest under this pass. Zero-cost and always safe to run, so the
315
+ * ContextManager calls it as an early tier.
316
+ *
317
+ * Only `Read` is deduped (its result is exactly the file content). Edit/Write
318
+ * results are diffs/confirmations, not full snapshots, so they're left alone.
319
+ */
320
+ export function dedupeFileReads(messages) {
321
+ const idToName = buildToolUseIdToNameMap(messages);
322
+ const idToInput = new Map();
323
+ for (const msg of messages) {
324
+ if (!Array.isArray(msg.content))
325
+ continue;
326
+ for (const block of msg.content) {
327
+ if (block.type === "tool_use" && block.id)
328
+ idToInput.set(block.id, block.input);
329
+ }
330
+ }
331
+ // Resolve a Read tool_use_id to its file_path arg (the dedup key).
332
+ const pathOf = (toolUseId) => {
333
+ const input = idToInput.get(toolUseId);
334
+ const p = input?.file_path ?? input?.path;
335
+ return typeof p === "string" && p.length > 0 ? p : undefined;
336
+ };
337
+ // Collect, per file path, the message indices + block positions of every
338
+ // non-cleared Read result. Walk forward so "last" is the newest.
339
+ const byPath = new Map();
340
+ for (let i = 0; i < messages.length; i++) {
341
+ const msg = messages[i];
342
+ if (!Array.isArray(msg.content))
343
+ continue;
344
+ for (const block of msg.content) {
345
+ if (block.type !== "tool_result" || !block.tool_use_id)
346
+ continue;
347
+ if (!FILE_READ_TOOLS.has(idToName.get(block.tool_use_id) ?? ""))
348
+ continue;
349
+ if (typeof block.content !== "string")
350
+ continue;
351
+ if (block.content.startsWith("[Old tool result cleared"))
352
+ continue;
353
+ const path = pathOf(block.tool_use_id);
354
+ if (!path)
355
+ continue;
356
+ const list = byPath.get(path) ?? [];
357
+ list.push({ msgIdx: i, toolUseId: block.tool_use_id });
358
+ byPath.set(path, list);
359
+ }
360
+ }
361
+ // For each path read more than once, mark all-but-last for clearing.
362
+ const clearIds = new Set();
363
+ for (const [, reads] of byPath) {
364
+ if (reads.length < 2)
365
+ continue;
366
+ for (let k = 0; k < reads.length - 1; k++)
367
+ clearIds.add(reads[k].toolUseId);
368
+ }
369
+ if (clearIds.size === 0)
370
+ return { messages, clearedCount: 0 };
371
+ let clearedCount = 0;
372
+ const result = messages.map((msg) => {
373
+ if (!Array.isArray(msg.content))
374
+ return msg;
375
+ return {
376
+ ...msg,
377
+ content: msg.content.map((block) => {
378
+ if (block.type !== "tool_result" || !block.tool_use_id)
379
+ return block;
380
+ if (!clearIds.has(block.tool_use_id))
381
+ return block;
382
+ const argsSummary = summarizeToolCallArgs("Read", idToInput.get(block.tool_use_id));
383
+ clearedCount++;
384
+ return {
385
+ ...block,
386
+ content: `[Old tool result cleared — superseded by a newer Read${argsSummary ? ` of ${argsSummary}` : ""}]`,
387
+ };
388
+ }),
389
+ };
390
+ });
391
+ return { messages: result, clearedCount };
392
+ }
393
+ /** Build id → true for tool_use blocks that are a browser snapshot observation,
394
+ * i.e. `browser_observe` with mode "snapshot" (the default when mode omitted).
395
+ * Only snapshots produce large, supersede-able element lists worth masking. */
396
+ function buildSnapshotObserveIdSet(messages) {
397
+ const ids = new Set();
398
+ for (const msg of messages) {
399
+ if (!Array.isArray(msg.content))
400
+ continue;
401
+ for (const block of msg.content) {
402
+ if (block.type !== "tool_use" || !block.id || block.name !== "browser_observe")
403
+ continue;
404
+ const mode = block.input?.mode;
405
+ if (mode === undefined || mode === "snapshot")
406
+ ids.add(block.id);
407
+ }
408
+ }
409
+ return ids;
410
+ }
411
+ const OLD_SNAPSHOT_PLACEHOLDER = "[Old browser snapshot collapsed — superseded by a newer browser_observe(snapshot). " +
412
+ "Re-run browser_observe for the current page's elements.]";
413
+ /**
414
+ * Observation masking for browser_observe(snapshot) results (the research's
415
+ * highest-leverage browser-token saving: a page snapshot is large and only the
416
+ * LATEST one matters for the next decision; older ones are stale element lists).
417
+ * Keep the most recent snapshot result verbatim; replace every earlier one with
418
+ * a one-line placeholder. Deterministic — no LLM summarization needed.
419
+ *
420
+ * Keyed on the snapshot OBSERVATION (browser_observe with mode snapshot) — read/
421
+ * extract observations and act results are left untouched. Renamed from
422
+ * maskOldBrowserSnapshots when the 9 browser_* tools collapsed into 3.
423
+ */
424
+ export function maskOldObservations(messages) {
425
+ const snapshotIds = buildSnapshotObserveIdSet(messages);
426
+ const snapResults = [];
427
+ for (const msg of messages) {
428
+ if (!Array.isArray(msg.content))
429
+ continue;
430
+ for (const block of msg.content) {
431
+ if (block.type !== "tool_result" || !block.tool_use_id)
432
+ continue;
433
+ if (!snapshotIds.has(block.tool_use_id))
434
+ continue;
435
+ if (typeof block.content !== "string")
436
+ continue;
437
+ if (block.content.startsWith("[Old browser snapshot collapsed"))
438
+ continue;
439
+ snapResults.push(block.tool_use_id);
440
+ }
441
+ }
442
+ if (snapResults.length < 2)
443
+ return { messages, maskedCount: 0 };
444
+ // Mask all but the last (newest walked-forward).
445
+ const maskIds = new Set(snapResults.slice(0, -1));
446
+ let maskedCount = 0;
447
+ const result = messages.map((msg) => {
448
+ if (!Array.isArray(msg.content))
449
+ return msg;
450
+ return {
451
+ ...msg,
452
+ content: msg.content.map((block) => {
453
+ if (block.type !== "tool_result" || !block.tool_use_id)
454
+ return block;
455
+ if (!maskIds.has(block.tool_use_id))
456
+ return block;
457
+ maskedCount++;
458
+ return { ...block, content: OLD_SNAPSHOT_PLACEHOLDER };
459
+ }),
460
+ };
461
+ });
462
+ return { messages: result, maskedCount };
463
+ }
278
464
  /**
279
465
  * Apply aggregate per-message tool result budget.
280
466
  * When total tool_result content in a single message exceeds maxTotalChars,
@@ -5,7 +5,7 @@
5
5
  * Tier 2: LLM summary (async) — generate summary of older messages via model call
6
6
  * Tier 3: window compact (sync, emergency) — aggressive truncation fallback
7
7
  */
8
- import { estimateTokens, microcompact, snipCompact, windowCompact, truncateToolResult, buildSummarizationPrompt, applySummaryCompaction, applyToolResultBudget, extractAnchoredSummary, } from "./compaction.js";
8
+ import { estimateTokens, microcompact, dedupeFileReads, maskOldObservations, snipCompact, windowCompact, truncateToolResult, buildSummarizationPrompt, applySummaryCompaction, applyToolResultBudget, extractAnchoredSummary, } from "./compaction.js";
9
9
  import { applyToolResultPersistence, createContentReplacementState, reconstructContentReplacementState, resolveToolResultsDir, } from "./tool-result-storage.js";
10
10
  import { logger } from "../logging/logger.js";
11
11
  const DEFAULT_CONFIG = {
@@ -127,6 +127,25 @@ export class ContextManager {
127
127
  // Tier 0c: Aggregate tool result budget (per-message) — char-level
128
128
  // backstop for messages still over the limit after persistence.
129
129
  result = applyToolResultBudget(result);
130
+ // Tier 0d: dedup repeated Reads of the same file — keep only the latest
131
+ // copy (older ones are stale). Always-on + zero-cost: it's pure waste
132
+ // removal (the model never needs two snapshots of one file), unlike the
133
+ // pressure-/recency-gated tiers below. Runs before microcompact so an
134
+ // already-deduped result isn't double-counted toward the keep-recent window.
135
+ const dedup = dedupeFileReads(result);
136
+ if (dedup.clearedCount > 0) {
137
+ result = dedup.messages;
138
+ logger.info("context.dedupe_file_reads", { cleared: dedup.clearedCount });
139
+ }
140
+ // Tier 0d': browser observation masking — keep only the latest
141
+ // browser_snapshot, collapse older ones (stale element lists, often large).
142
+ // Same always-on waste-removal class as dedupeFileReads. The research's
143
+ // top browser-token lever (folding old observations beats LLM summarizing).
144
+ const masked = maskOldObservations(result);
145
+ if (masked.maskedCount > 0) {
146
+ result = masked.messages;
147
+ logger.info("context.mask_browser_snapshots", { masked: masked.maskedCount });
148
+ }
130
149
  // Tier 1: microcompact — fingerprint old whitelisted tool_results.
131
150
  // Only runs above the floor ratio: under-pressure context keeps full
132
151
  // detail so the model isn't forced to re-Read files it just looked at.
@@ -341,20 +360,22 @@ export class ContextManager {
341
360
  */
342
361
  truncateToolResults(messages) {
343
362
  const maxChars = this.config.maxToolResultChars;
344
- let modified = false;
345
363
  const result = messages.map((msg) => {
346
364
  if (!Array.isArray(msg.content))
347
365
  return msg;
366
+ // Per-message flag: a truncation in an earlier message must not force
367
+ // later, unchanged messages to be spread-copied.
368
+ let messageModified = false;
348
369
  const newContent = msg.content.map((block) => {
349
370
  if (block.type === "tool_result" && typeof block.content === "string") {
350
371
  if (block.content.length > maxChars) {
351
- modified = true;
372
+ messageModified = true;
352
373
  return { ...block, content: truncateToolResult(block.content, maxChars) };
353
374
  }
354
375
  }
355
376
  return block;
356
377
  });
357
- return modified ? { ...msg, content: newContent } : msg;
378
+ return messageModified ? { ...msg, content: newContent } : msg;
358
379
  });
359
380
  return result;
360
381
  }
@@ -3,67 +3,11 @@
3
3
  */
4
4
  import { NOOP_COLORIZER } from "./colorizer.js";
5
5
  import { findOpenRouterModel } from "./data/openrouter-models.js";
6
- function pricing(input, output) {
7
- // Default cache pricing: read = 10% of input, write = 125% of input
8
- return { input, output, cacheRead: input * 0.1, cacheWrite: input * 1.25 };
9
- }
10
- const MODEL_PRICING = {
11
- // Anthropic (per 1M tokens, USD)
12
- "claude-opus-4.6": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
13
- "claude-opus-4-6": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }, // alias
14
- "claude-opus-4.5": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
15
- "claude-opus-4.1": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
16
- "claude-opus-4": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
17
- "claude-sonnet-4.6": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
18
- "claude-sonnet-4-6": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, // alias
19
- "claude-sonnet-4.5": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
20
- "claude-sonnet-4": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
21
- "claude-3.7-sonnet": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
22
- "claude-3-7-sonnet": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
23
- "claude-3.5-haiku": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
24
- "claude-haiku-4.5": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
25
- "claude-haiku-4-5": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, // alias
26
- // OpenAI
27
- "gpt-5.4": pricing(5, 20),
28
- "gpt-5.4-mini": pricing(1.5, 6),
29
- "gpt-5.4-pro": pricing(10, 40),
30
- "gpt-5": pricing(5, 20),
31
- "gpt-4o": pricing(2.5, 10),
32
- "gpt-4o-mini": pricing(0.15, 0.6),
33
- "gpt-4.1": pricing(2, 8),
34
- "gpt-4.1-mini": pricing(0.4, 1.6),
35
- "o4-mini": pricing(1.1, 4.4),
36
- "o3": pricing(10, 40),
37
- "o3-mini": pricing(1.1, 4.4),
38
- // Google
39
- "gemini-2.5-pro": pricing(1.25, 10),
40
- "gemini-2.5-pro-preview": pricing(1.25, 10),
41
- "gemini-2.5-flash": pricing(0.15, 0.6),
42
- "gemini-3.1-pro-preview": pricing(2, 10),
43
- "gemini-3-flash-preview": pricing(0.15, 0.6),
44
- "gemini-2.0-flash": pricing(0.1, 0.4),
45
- // DeepSeek
46
- "deepseek-v4-flash": pricing(0.126, 0.252),
47
- "deepseek-v4-pro": pricing(0.5, 2),
48
- "deepseek-v3.2": pricing(0.14, 0.28),
49
- "deepseek-chat": pricing(0.14, 0.28),
50
- "deepseek-r1": pricing(0.55, 2.19),
51
- "deepseek-reasoner": pricing(0.55, 2.19),
52
- // Qwen
53
- "qwen3-coder": pricing(0.3, 0.6),
54
- "qwen3-235b-a22b": pricing(0.3, 1.2),
55
- "qwen3-30b-a3b": pricing(0.1, 0.3),
56
- "qwen3-max": pricing(0.5, 2),
57
- // Meta
58
- "llama-4-maverick": pricing(0.2, 0.8),
59
- "llama-4-scout": pricing(0.15, 0.4),
60
- // Mistral
61
- "devstral-medium": pricing(0.5, 1.5),
62
- "mistral-large": pricing(2, 6),
63
- "devstral-small": pricing(0.1, 0.3),
64
- };
65
- // Default fallback pricing
66
- const DEFAULT_PRICING = pricing(3, 15);
6
+ import { MODEL_PRICING, DEFAULT_PRICING, } from "./data/model-metadata.js";
7
+ // Pricing per 1M tokens (USD). The MODEL_PRICING table + DEFAULT_PRICING now
8
+ // live in data/model-metadata.json (loaded by data/model-metadata.ts) so a
9
+ // price change is a data edit, not a code change. cacheRead/cacheWrite are
10
+ // derived there: read = 10% of input, write = 125% of input.
67
11
  /** Build a ModelPricing from an OpenRouter snapshot entry. */
68
12
  function openRouterPricing(hit) {
69
13
  const input = hit.inputPricePerMillion;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Credential encryption boundary.
3
+ *
4
+ * The core has no business owning a platform encryption key — on the desktop
5
+ * the only safe key lives behind Electron `safeStorage`, which is in the main
6
+ * process, not in this worker. So core defines an INTERFACE and the host feeds
7
+ * an implementation: desktop main injects a safeStorage-backed cipher; the
8
+ * headless CLI / SDK inject {@link PlaintextCipher}. This keeps `safeStorage`
9
+ * out of `packages/core` entirely (`grep -R safeStorage packages/core/src`
10
+ * must stay empty) and puts secret crypto where the key actually is.
11
+ *
12
+ * The stored field is a tagged string so a store written by one cipher can be
13
+ * read (or rejected) by another:
14
+ * - `plain:<secret>` — PlaintextCipher, or any pre-cipher legacy value
15
+ * that has no recognized prefix (treated as plain).
16
+ * - `enc:<scheme>:<base64>` — an encrypting cipher; `<scheme>` lets a cipher
17
+ * recognize its own ciphertext via canDecrypt().
18
+ */
19
+ export interface EncryptionCipher {
20
+ /** Encrypt a plaintext secret into its stored (tagged) form. */
21
+ encrypt(plaintext: string): string;
22
+ /** Decrypt a stored value back to plaintext. Must accept this cipher's own
23
+ * output and legacy un-prefixed plaintext; may throw if a value is
24
+ * recognizably foreign and undecryptable. */
25
+ decrypt(stored: string): string;
26
+ /** True when this cipher can decrypt `stored`. Used by the store to decide
27
+ * whether to migrate (re-encrypt on next save) a value written by a
28
+ * different cipher / left as legacy plaintext. */
29
+ canDecrypt?(stored: string): boolean;
30
+ }
31
+ /**
32
+ * The no-encryption strategy — chosen explicitly, not a no-op. Headless and
33
+ * SDK hosts have no safe key store, so they keep credentials as owner-only
34
+ * (0o600) plaintext, exactly as before this boundary existed. Named so the
35
+ * choice reads honestly in host wiring: `new CredentialStore(cwd, new
36
+ * PlaintextCipher())` says "plaintext on purpose", not "forgot to encrypt".
37
+ */
38
+ export declare class PlaintextCipher implements EncryptionCipher {
39
+ encrypt(plaintext: string): string;
40
+ decrypt(stored: string): string;
41
+ canDecrypt(stored: string): boolean;
42
+ }
43
+ /** Reads a value that may be tagged (`plain:`) or legacy bare plaintext. */
44
+ export declare function readPlaintext(stored: string): string;
45
+ /** Host startup hook: install the process-wide credential cipher (desktop main
46
+ * passes a safeStorage-backed implementation). Idempotent; last call wins. */
47
+ export declare function setDefaultCredentialCipher(cipher: EncryptionCipher): void;
48
+ /** The current process-default cipher (PlaintextCipher unless a host set one). */
49
+ export declare function getDefaultCredentialCipher(): EncryptionCipher;
@@ -0,0 +1,45 @@
1
+ const PLAIN_PREFIX = "plain:";
2
+ /**
3
+ * The no-encryption strategy — chosen explicitly, not a no-op. Headless and
4
+ * SDK hosts have no safe key store, so they keep credentials as owner-only
5
+ * (0o600) plaintext, exactly as before this boundary existed. Named so the
6
+ * choice reads honestly in host wiring: `new CredentialStore(cwd, new
7
+ * PlaintextCipher())` says "plaintext on purpose", not "forgot to encrypt".
8
+ */
9
+ export class PlaintextCipher {
10
+ encrypt(plaintext) {
11
+ return `${PLAIN_PREFIX}${plaintext}`;
12
+ }
13
+ decrypt(stored) {
14
+ // Accept our own tag, and treat any un-tagged legacy value as plaintext.
15
+ if (stored.startsWith(PLAIN_PREFIX))
16
+ return stored.slice(PLAIN_PREFIX.length);
17
+ if (stored.startsWith("enc:")) {
18
+ throw new Error("PlaintextCipher cannot decrypt an encrypted credential");
19
+ }
20
+ return stored;
21
+ }
22
+ canDecrypt(stored) {
23
+ return !stored.startsWith("enc:");
24
+ }
25
+ }
26
+ /** Reads a value that may be tagged (`plain:`) or legacy bare plaintext. */
27
+ export function readPlaintext(stored) {
28
+ return stored.startsWith(PLAIN_PREFIX) ? stored.slice(PLAIN_PREFIX.length) : stored;
29
+ }
30
+ // ─── Process-default cipher ──────────────────────────────────────
31
+ // CredentialStore is constructed at ~12 call sites (core + desktop) as
32
+ // `new CredentialStore(cwd)`. Rather than thread a cipher through every one,
33
+ // the host sets the process default ONCE at startup; stores pick it up unless
34
+ // a cipher is passed explicitly. Defaults to PlaintextCipher so any host that
35
+ // never calls the setter behaves exactly as before.
36
+ let defaultCipher = new PlaintextCipher();
37
+ /** Host startup hook: install the process-wide credential cipher (desktop main
38
+ * passes a safeStorage-backed implementation). Idempotent; last call wins. */
39
+ export function setDefaultCredentialCipher(cipher) {
40
+ defaultCipher = cipher;
41
+ }
42
+ /** The current process-default cipher (PlaintextCipher unless a host set one). */
43
+ export function getDefaultCredentialCipher() {
44
+ return defaultCipher;
45
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Cookie jar 工具(凭证模块第二期):core 侧的纯函数,把存进 CredentialStore 的
3
+ * cookie 凭证(序列化的 jar)转成 yt-dlp/curl/wget/aria2 都吃的 Netscape cookies.txt。
4
+ *
5
+ * 形态与 desktop/src/main/credentials-service.ts 的 `formatNetscapeCookies` 一致
6
+ * (desktop 在拓取那一刻用,core 在取用那一刻用)。core 不能 import desktop,故各持一份
7
+ * 同语义的纯实现 —— 都无 Electron 依赖、可单测。
8
+ */
9
+ /** 与 Electron Cookie 对齐的最小子集(jar 里存的就是这个)。 */
10
+ export interface CookieLike {
11
+ domain?: string;
12
+ hostOnly?: boolean;
13
+ path?: string;
14
+ secure?: boolean;
15
+ expirationDate?: number;
16
+ name: string;
17
+ value: string;
18
+ }
19
+ /** Cookie[] → Netscape cookies.txt 字符串。跳过含 TAB/换行的脏 cookie。 */
20
+ export declare function formatNetscapeCookies(cookies: CookieLike[]): string;
21
+ /**
22
+ * 解析 cookie 凭证的 `secret`(序列化 jar)。容错:非数组/坏 JSON → 空数组。
23
+ */
24
+ export declare function parseCookieJar(secret: string | undefined): CookieLike[];
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Cookie jar 工具(凭证模块第二期):core 侧的纯函数,把存进 CredentialStore 的
3
+ * cookie 凭证(序列化的 jar)转成 yt-dlp/curl/wget/aria2 都吃的 Netscape cookies.txt。
4
+ *
5
+ * 形态与 desktop/src/main/credentials-service.ts 的 `formatNetscapeCookies` 一致
6
+ * (desktop 在拓取那一刻用,core 在取用那一刻用)。core 不能 import desktop,故各持一份
7
+ * 同语义的纯实现 —— 都无 Electron 依赖、可单测。
8
+ */
9
+ function bad(s) {
10
+ return s.includes("\t") || s.includes("\n") || s.includes("\r");
11
+ }
12
+ /** Cookie[] → Netscape cookies.txt 字符串。跳过含 TAB/换行的脏 cookie。 */
13
+ export function formatNetscapeCookies(cookies) {
14
+ const lines = ["# Netscape HTTP Cookie File"];
15
+ for (const c of cookies) {
16
+ if (bad(c.name) || bad(c.value) || (c.domain && bad(c.domain)))
17
+ continue;
18
+ const domain = c.domain ?? "";
19
+ const includeSub = c.hostOnly === true ? "FALSE" : "TRUE";
20
+ const path = c.path ?? "/";
21
+ const secure = c.secure ? "TRUE" : "FALSE";
22
+ const expiry = typeof c.expirationDate === "number" ? String(Math.floor(c.expirationDate)) : "0";
23
+ lines.push([domain, includeSub, path, secure, expiry, c.name, c.value].join("\t"));
24
+ }
25
+ return lines.join("\n") + "\n";
26
+ }
27
+ /**
28
+ * 解析 cookie 凭证的 `secret`(序列化 jar)。容错:非数组/坏 JSON → 空数组。
29
+ */
30
+ export function parseCookieJar(secret) {
31
+ if (!secret)
32
+ return [];
33
+ try {
34
+ const parsed = JSON.parse(secret);
35
+ return Array.isArray(parsed) ? parsed : [];
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ }