@cjhyy/code-shell-core 0.5.0-rc.0

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 (484) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/dist/agent/coordinator.d.ts +49 -0
  4. package/dist/agent/coordinator.js +77 -0
  5. package/dist/arena/arena.d.ts +43 -0
  6. package/dist/arena/arena.js +334 -0
  7. package/dist/arena/context/context-tools.d.ts +16 -0
  8. package/dist/arena/context/context-tools.js +231 -0
  9. package/dist/arena/detect-mode.d.ts +20 -0
  10. package/dist/arena/detect-mode.js +78 -0
  11. package/dist/arena/digest-builder.d.ts +25 -0
  12. package/dist/arena/digest-builder.js +120 -0
  13. package/dist/arena/index.d.ts +29 -0
  14. package/dist/arena/index.js +29 -0
  15. package/dist/arena/iterate/convergence.d.ts +25 -0
  16. package/dist/arena/iterate/convergence.js +103 -0
  17. package/dist/arena/iterate/formats/index.d.ts +22 -0
  18. package/dist/arena/iterate/formats/index.js +283 -0
  19. package/dist/arena/iterate/index.d.ts +11 -0
  20. package/dist/arena/iterate/index.js +9 -0
  21. package/dist/arena/iterate/iterative-arena.d.ts +23 -0
  22. package/dist/arena/iterate/iterative-arena.js +237 -0
  23. package/dist/arena/iterate/parse.d.ts +42 -0
  24. package/dist/arena/iterate/parse.js +123 -0
  25. package/dist/arena/iterate/phases/argue.d.ts +22 -0
  26. package/dist/arena/iterate/phases/argue.js +159 -0
  27. package/dist/arena/iterate/phases/revise.d.ts +16 -0
  28. package/dist/arena/iterate/phases/revise.js +62 -0
  29. package/dist/arena/iterate/phases/tournament.d.ts +34 -0
  30. package/dist/arena/iterate/phases/tournament.js +113 -0
  31. package/dist/arena/iterate/tools/web-tools.d.ts +13 -0
  32. package/dist/arena/iterate/tools/web-tools.js +54 -0
  33. package/dist/arena/iterate/types.d.ts +152 -0
  34. package/dist/arena/iterate/types.js +8 -0
  35. package/dist/arena/ledger.d.ts +47 -0
  36. package/dist/arena/ledger.js +151 -0
  37. package/dist/arena/lenses/architecture.d.ts +5 -0
  38. package/dist/arena/lenses/architecture.js +22 -0
  39. package/dist/arena/lenses/engineering.d.ts +5 -0
  40. package/dist/arena/lenses/engineering.js +22 -0
  41. package/dist/arena/lenses/general.d.ts +5 -0
  42. package/dist/arena/lenses/general.js +20 -0
  43. package/dist/arena/lenses/index.d.ts +16 -0
  44. package/dist/arena/lenses/index.js +47 -0
  45. package/dist/arena/lenses/product.d.ts +5 -0
  46. package/dist/arena/lenses/product.js +22 -0
  47. package/dist/arena/model-presets.d.ts +23 -0
  48. package/dist/arena/model-presets.js +44 -0
  49. package/dist/arena/phases/adjudication.d.ts +24 -0
  50. package/dist/arena/phases/adjudication.js +144 -0
  51. package/dist/arena/phases/build-consensus.d.ts +29 -0
  52. package/dist/arena/phases/build-consensus.js +86 -0
  53. package/dist/arena/phases/claim-registry.d.ts +26 -0
  54. package/dist/arena/phases/claim-registry.js +60 -0
  55. package/dist/arena/phases/cross-review.d.ts +45 -0
  56. package/dist/arena/phases/cross-review.js +224 -0
  57. package/dist/arena/phases/debate-rounds.d.ts +27 -0
  58. package/dist/arena/phases/debate-rounds.js +162 -0
  59. package/dist/arena/phases/participant-research.d.ts +38 -0
  60. package/dist/arena/phases/participant-research.js +317 -0
  61. package/dist/arena/phases/planning-detail-expansion.d.ts +38 -0
  62. package/dist/arena/phases/planning-detail-expansion.js +121 -0
  63. package/dist/arena/planner.d.ts +27 -0
  64. package/dist/arena/planner.js +312 -0
  65. package/dist/arena/providers/docs.d.ts +6 -0
  66. package/dist/arena/providers/docs.js +108 -0
  67. package/dist/arena/providers/git.d.ts +8 -0
  68. package/dist/arena/providers/git.js +174 -0
  69. package/dist/arena/providers/index.d.ts +32 -0
  70. package/dist/arena/providers/index.js +132 -0
  71. package/dist/arena/providers/none.d.ts +7 -0
  72. package/dist/arena/providers/none.js +11 -0
  73. package/dist/arena/providers/repo.d.ts +6 -0
  74. package/dist/arena/providers/repo.js +255 -0
  75. package/dist/arena/render/session.d.ts +17 -0
  76. package/dist/arena/render/session.js +190 -0
  77. package/dist/arena/render/terminal.d.ts +34 -0
  78. package/dist/arena/render/terminal.js +286 -0
  79. package/dist/arena/strategies/discussion.d.ts +25 -0
  80. package/dist/arena/strategies/discussion.js +143 -0
  81. package/dist/arena/strategies/index.d.ts +15 -0
  82. package/dist/arena/strategies/index.js +28 -0
  83. package/dist/arena/strategies/language-wrapper.d.ts +17 -0
  84. package/dist/arena/strategies/language-wrapper.js +102 -0
  85. package/dist/arena/strategies/lens-wrapper.d.ts +16 -0
  86. package/dist/arena/strategies/lens-wrapper.js +236 -0
  87. package/dist/arena/strategies/planning.d.ts +30 -0
  88. package/dist/arena/strategies/planning.js +225 -0
  89. package/dist/arena/strategies/review.d.ts +26 -0
  90. package/dist/arena/strategies/review.js +168 -0
  91. package/dist/arena/strategies/utils.d.ts +39 -0
  92. package/dist/arena/strategies/utils.js +647 -0
  93. package/dist/arena/tools/selector.d.ts +17 -0
  94. package/dist/arena/tools/selector.js +61 -0
  95. package/dist/arena/transitions.d.ts +48 -0
  96. package/dist/arena/transitions.js +92 -0
  97. package/dist/arena/types.d.ts +508 -0
  98. package/dist/arena/types.js +27 -0
  99. package/dist/cli/agent-server-stdio.d.ts +32 -0
  100. package/dist/cli/agent-server-stdio.js +116 -0
  101. package/dist/colorizer.d.ts +23 -0
  102. package/dist/colorizer.js +12 -0
  103. package/dist/context/compaction.d.ts +116 -0
  104. package/dist/context/compaction.js +534 -0
  105. package/dist/context/manager.d.ts +145 -0
  106. package/dist/context/manager.js +423 -0
  107. package/dist/context/token-counter.d.ts +27 -0
  108. package/dist/context/token-counter.js +91 -0
  109. package/dist/context/tool-result-storage.d.ts +96 -0
  110. package/dist/context/tool-result-storage.js +296 -0
  111. package/dist/cost-tracker.d.ts +64 -0
  112. package/dist/cost-tracker.js +314 -0
  113. package/dist/cron/scheduler.d.ts +34 -0
  114. package/dist/cron/scheduler.js +115 -0
  115. package/dist/data/deepseek-models.json +46 -0
  116. package/dist/data/gemini-models.json +67 -0
  117. package/dist/data/openai-models.json +175 -0
  118. package/dist/data/openrouter-models.d.ts +35 -0
  119. package/dist/data/openrouter-models.js +36 -0
  120. package/dist/data/openrouter-models.json +4626 -0
  121. package/dist/data/openrouter-sync.d.ts +16 -0
  122. package/dist/data/openrouter-sync.js +53 -0
  123. package/dist/data/static-catalogs.d.ts +25 -0
  124. package/dist/data/static-catalogs.js +26 -0
  125. package/dist/data/zai-models.json +56 -0
  126. package/dist/engine/cost-store.d.ts +22 -0
  127. package/dist/engine/cost-store.js +15 -0
  128. package/dist/engine/engine.d.ts +295 -0
  129. package/dist/engine/engine.js +1467 -0
  130. package/dist/engine/model-facade.d.ts +24 -0
  131. package/dist/engine/model-facade.js +194 -0
  132. package/dist/engine/parse-task.d.ts +59 -0
  133. package/dist/engine/parse-task.js +135 -0
  134. package/dist/engine/patch-orphaned-tools.d.ts +52 -0
  135. package/dist/engine/patch-orphaned-tools.js +95 -0
  136. package/dist/engine/query.d.ts +50 -0
  137. package/dist/engine/query.js +107 -0
  138. package/dist/engine/runtime.d.ts +50 -0
  139. package/dist/engine/runtime.js +59 -0
  140. package/dist/engine/streaming-tool-queue.d.ts +34 -0
  141. package/dist/engine/streaming-tool-queue.js +61 -0
  142. package/dist/engine/token-budget.d.ts +22 -0
  143. package/dist/engine/token-budget.js +40 -0
  144. package/dist/engine/tool-summary.d.ts +13 -0
  145. package/dist/engine/tool-summary.js +35 -0
  146. package/dist/engine/turn-loop.d.ts +122 -0
  147. package/dist/engine/turn-loop.js +602 -0
  148. package/dist/engine/turn-state.d.ts +20 -0
  149. package/dist/engine/turn-state.js +17 -0
  150. package/dist/exceptions.d.ts +61 -0
  151. package/dist/exceptions.js +116 -0
  152. package/dist/git/utils.d.ts +35 -0
  153. package/dist/git/utils.js +98 -0
  154. package/dist/git/worktree.d.ts +36 -0
  155. package/dist/git/worktree.js +139 -0
  156. package/dist/hooks/events.d.ts +114 -0
  157. package/dist/hooks/events.js +4 -0
  158. package/dist/hooks/inject.d.ts +19 -0
  159. package/dist/hooks/inject.js +29 -0
  160. package/dist/hooks/registry.d.ts +15 -0
  161. package/dist/hooks/registry.js +84 -0
  162. package/dist/hooks/shell-runner.d.ts +45 -0
  163. package/dist/hooks/shell-runner.js +173 -0
  164. package/dist/index.d.ts +117 -0
  165. package/dist/index.js +145 -0
  166. package/dist/llm/api-key-sanitize.d.ts +22 -0
  167. package/dist/llm/api-key-sanitize.js +81 -0
  168. package/dist/llm/capabilities/index.d.ts +20 -0
  169. package/dist/llm/capabilities/index.js +39 -0
  170. package/dist/llm/capabilities/rules.d.ts +26 -0
  171. package/dist/llm/capabilities/rules.js +215 -0
  172. package/dist/llm/capabilities/types.d.ts +114 -0
  173. package/dist/llm/capabilities/types.js +24 -0
  174. package/dist/llm/client-base.d.ts +29 -0
  175. package/dist/llm/client-base.js +137 -0
  176. package/dist/llm/client-factory.d.ts +10 -0
  177. package/dist/llm/client-factory.js +29 -0
  178. package/dist/llm/model-cache.d.ts +21 -0
  179. package/dist/llm/model-cache.js +46 -0
  180. package/dist/llm/model-fetcher.d.ts +29 -0
  181. package/dist/llm/model-fetcher.js +282 -0
  182. package/dist/llm/model-pool.d.ts +95 -0
  183. package/dist/llm/model-pool.js +246 -0
  184. package/dist/llm/provider-catalog.d.ts +32 -0
  185. package/dist/llm/provider-catalog.js +50 -0
  186. package/dist/llm/provider-kinds.d.ts +21 -0
  187. package/dist/llm/provider-kinds.js +132 -0
  188. package/dist/llm/providers/anthropic.d.ts +19 -0
  189. package/dist/llm/providers/anthropic.js +267 -0
  190. package/dist/llm/providers/openai.d.ts +64 -0
  191. package/dist/llm/providers/openai.js +606 -0
  192. package/dist/llm/retry.d.ts +12 -0
  193. package/dist/llm/retry.js +17 -0
  194. package/dist/llm/stream-watchdog.d.ts +42 -0
  195. package/dist/llm/stream-watchdog.js +70 -0
  196. package/dist/llm/token-counter.d.ts +17 -0
  197. package/dist/llm/token-counter.js +36 -0
  198. package/dist/llm/types.d.ts +37 -0
  199. package/dist/llm/types.js +4 -0
  200. package/dist/logging/logger.d.ts +109 -0
  201. package/dist/logging/logger.js +390 -0
  202. package/dist/logging/sanitize-messages.d.ts +42 -0
  203. package/dist/logging/sanitize-messages.js +150 -0
  204. package/dist/logging/session-recorder.d.ts +90 -0
  205. package/dist/logging/session-recorder.js +304 -0
  206. package/dist/lsp/client.d.ts +41 -0
  207. package/dist/lsp/client.js +166 -0
  208. package/dist/lsp/manager.d.ts +40 -0
  209. package/dist/lsp/manager.js +124 -0
  210. package/dist/lsp/servers.d.ts +16 -0
  211. package/dist/lsp/servers.js +60 -0
  212. package/dist/migrate-models.d.ts +45 -0
  213. package/dist/migrate-models.js +179 -0
  214. package/dist/onboarding.d.ts +189 -0
  215. package/dist/onboarding.js +625 -0
  216. package/dist/plugins/gitOps.d.ts +32 -0
  217. package/dist/plugins/gitOps.js +62 -0
  218. package/dist/plugins/installedPlugins.d.ts +15 -0
  219. package/dist/plugins/installedPlugins.js +56 -0
  220. package/dist/plugins/knownMarketplaces.d.ts +10 -0
  221. package/dist/plugins/knownMarketplaces.js +46 -0
  222. package/dist/plugins/loadPluginHooks.d.ts +52 -0
  223. package/dist/plugins/loadPluginHooks.js +162 -0
  224. package/dist/plugins/marketplaceManager.d.ts +49 -0
  225. package/dist/plugins/marketplaceManager.js +142 -0
  226. package/dist/plugins/parseMarketplaceInput.d.ts +16 -0
  227. package/dist/plugins/parseMarketplaceInput.js +73 -0
  228. package/dist/plugins/pluginCommandHook.d.ts +54 -0
  229. package/dist/plugins/pluginCommandHook.js +180 -0
  230. package/dist/plugins/pluginCommandsLoader.d.ts +25 -0
  231. package/dist/plugins/pluginCommandsLoader.js +114 -0
  232. package/dist/plugins/pluginInstaller.d.ts +36 -0
  233. package/dist/plugins/pluginInstaller.js +228 -0
  234. package/dist/plugins/schemas.d.ts +9 -0
  235. package/dist/plugins/schemas.js +136 -0
  236. package/dist/plugins/types.d.ts +75 -0
  237. package/dist/plugins/types.js +7 -0
  238. package/dist/plugins/varRewrite.d.ts +42 -0
  239. package/dist/plugins/varRewrite.js +129 -0
  240. package/dist/preset/index.d.ts +60 -0
  241. package/dist/preset/index.js +159 -0
  242. package/dist/product/define.d.ts +60 -0
  243. package/dist/product/define.js +123 -0
  244. package/dist/product/index.d.ts +5 -0
  245. package/dist/product/index.js +4 -0
  246. package/dist/product/types.d.ts +111 -0
  247. package/dist/product/types.js +21 -0
  248. package/dist/prompt/composer.d.ts +49 -0
  249. package/dist/prompt/composer.js +168 -0
  250. package/dist/prompt/instruction-scanner.d.ts +54 -0
  251. package/dist/prompt/instruction-scanner.js +187 -0
  252. package/dist/prompt/section-cache.d.ts +15 -0
  253. package/dist/prompt/section-cache.js +31 -0
  254. package/dist/prompt/section-loader.d.ts +26 -0
  255. package/dist/prompt/section-loader.js +53 -0
  256. package/dist/prompt/sections/base.md +35 -0
  257. package/dist/prompt/sections/coding.md +31 -0
  258. package/dist/prompt/sections/orchestration.md +16 -0
  259. package/dist/prompt/sections/tone.md +9 -0
  260. package/dist/protocol/chat-session-manager.d.ts +33 -0
  261. package/dist/protocol/chat-session-manager.js +65 -0
  262. package/dist/protocol/chat-session.d.ts +49 -0
  263. package/dist/protocol/chat-session.js +86 -0
  264. package/dist/protocol/client.d.ts +104 -0
  265. package/dist/protocol/client.js +260 -0
  266. package/dist/protocol/factories.d.ts +93 -0
  267. package/dist/protocol/factories.js +64 -0
  268. package/dist/protocol/helpers.d.ts +42 -0
  269. package/dist/protocol/helpers.js +55 -0
  270. package/dist/protocol/index.d.ts +4 -0
  271. package/dist/protocol/index.js +4 -0
  272. package/dist/protocol/server.d.ts +80 -0
  273. package/dist/protocol/server.js +855 -0
  274. package/dist/protocol/transport.d.ts +37 -0
  275. package/dist/protocol/transport.js +85 -0
  276. package/dist/protocol/types.d.ts +221 -0
  277. package/dist/protocol/types.js +61 -0
  278. package/dist/remote/bridge.d.ts +37 -0
  279. package/dist/remote/bridge.js +103 -0
  280. package/dist/run/ArtifactTracker.d.ts +38 -0
  281. package/dist/run/ArtifactTracker.js +132 -0
  282. package/dist/run/CheckpointWriter.d.ts +53 -0
  283. package/dist/run/CheckpointWriter.js +135 -0
  284. package/dist/run/EngineRunner.d.ts +72 -0
  285. package/dist/run/EngineRunner.js +119 -0
  286. package/dist/run/Evaluator.d.ts +56 -0
  287. package/dist/run/Evaluator.js +62 -0
  288. package/dist/run/FileRunStore.d.ts +39 -0
  289. package/dist/run/FileRunStore.js +176 -0
  290. package/dist/run/Heartbeat.d.ts +54 -0
  291. package/dist/run/Heartbeat.js +123 -0
  292. package/dist/run/RunApprovalBackend.d.ts +53 -0
  293. package/dist/run/RunApprovalBackend.js +85 -0
  294. package/dist/run/RunLock.d.ts +40 -0
  295. package/dist/run/RunLock.js +98 -0
  296. package/dist/run/RunManager.d.ts +82 -0
  297. package/dist/run/RunManager.js +587 -0
  298. package/dist/run/RunQueue.d.ts +27 -0
  299. package/dist/run/RunQueue.js +73 -0
  300. package/dist/run/RunStore.d.ts +25 -0
  301. package/dist/run/RunStore.js +9 -0
  302. package/dist/run/factory.d.ts +63 -0
  303. package/dist/run/factory.js +51 -0
  304. package/dist/run/index.d.ts +17 -0
  305. package/dist/run/index.js +23 -0
  306. package/dist/run/types.d.ts +136 -0
  307. package/dist/run/types.js +28 -0
  308. package/dist/runtime/safe-spawn.d.ts +118 -0
  309. package/dist/runtime/safe-spawn.js +268 -0
  310. package/dist/services/analytics.d.ts +29 -0
  311. package/dist/services/analytics.js +84 -0
  312. package/dist/services/auto-dream.d.ts +49 -0
  313. package/dist/services/auto-dream.js +124 -0
  314. package/dist/services/diagnostics.d.ts +41 -0
  315. package/dist/services/diagnostics.js +99 -0
  316. package/dist/services/extract-memories.d.ts +31 -0
  317. package/dist/services/extract-memories.js +71 -0
  318. package/dist/services/index.d.ts +11 -0
  319. package/dist/services/index.js +17 -0
  320. package/dist/services/memory-orchestrator.d.ts +60 -0
  321. package/dist/services/memory-orchestrator.js +133 -0
  322. package/dist/services/notifier.d.ts +25 -0
  323. package/dist/services/notifier.js +69 -0
  324. package/dist/services/oauth.d.ts +27 -0
  325. package/dist/services/oauth.js +153 -0
  326. package/dist/services/session-memory.d.ts +37 -0
  327. package/dist/services/session-memory.js +81 -0
  328. package/dist/session/file-history.d.ts +41 -0
  329. package/dist/session/file-history.js +115 -0
  330. package/dist/session/memory.d.ts +104 -0
  331. package/dist/session/memory.js +310 -0
  332. package/dist/session/session-manager.d.ts +41 -0
  333. package/dist/session/session-manager.js +261 -0
  334. package/dist/session/transcript.d.ts +39 -0
  335. package/dist/session/transcript.js +186 -0
  336. package/dist/settings/manager.d.ts +36 -0
  337. package/dist/settings/manager.js +187 -0
  338. package/dist/settings/schema.d.ts +1219 -0
  339. package/dist/settings/schema.js +246 -0
  340. package/dist/skills/frontmatter.d.ts +13 -0
  341. package/dist/skills/frontmatter.js +70 -0
  342. package/dist/skills/index.d.ts +7 -0
  343. package/dist/skills/index.js +6 -0
  344. package/dist/skills/scanner.d.ts +31 -0
  345. package/dist/skills/scanner.js +171 -0
  346. package/dist/state.d.ts +160 -0
  347. package/dist/state.js +267 -0
  348. package/dist/tool-system/builtin/agent-notifications.d.ts +84 -0
  349. package/dist/tool-system/builtin/agent-notifications.js +197 -0
  350. package/dist/tool-system/builtin/agent-registry.d.ts +67 -0
  351. package/dist/tool-system/builtin/agent-registry.js +126 -0
  352. package/dist/tool-system/builtin/agent-transcript-translator.d.ts +22 -0
  353. package/dist/tool-system/builtin/agent-transcript-translator.js +160 -0
  354. package/dist/tool-system/builtin/agent.d.ts +16 -0
  355. package/dist/tool-system/builtin/agent.js +364 -0
  356. package/dist/tool-system/builtin/apply-patch/applier.d.ts +26 -0
  357. package/dist/tool-system/builtin/apply-patch/applier.js +250 -0
  358. package/dist/tool-system/builtin/apply-patch/index.d.ts +20 -0
  359. package/dist/tool-system/builtin/apply-patch/index.js +101 -0
  360. package/dist/tool-system/builtin/apply-patch/parser.d.ts +17 -0
  361. package/dist/tool-system/builtin/apply-patch/parser.js +212 -0
  362. package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +18 -0
  363. package/dist/tool-system/builtin/apply-patch/seek-sequence.js +123 -0
  364. package/dist/tool-system/builtin/apply-patch/types.d.ts +49 -0
  365. package/dist/tool-system/builtin/apply-patch/types.js +13 -0
  366. package/dist/tool-system/builtin/arena.d.ts +31 -0
  367. package/dist/tool-system/builtin/arena.js +416 -0
  368. package/dist/tool-system/builtin/ask-user.d.ts +20 -0
  369. package/dist/tool-system/builtin/ask-user.js +99 -0
  370. package/dist/tool-system/builtin/bash.d.ts +21 -0
  371. package/dist/tool-system/builtin/bash.js +149 -0
  372. package/dist/tool-system/builtin/brief.d.ts +6 -0
  373. package/dist/tool-system/builtin/brief.js +41 -0
  374. package/dist/tool-system/builtin/config.d.ts +6 -0
  375. package/dist/tool-system/builtin/config.js +67 -0
  376. package/dist/tool-system/builtin/cron.d.ts +10 -0
  377. package/dist/tool-system/builtin/cron.js +61 -0
  378. package/dist/tool-system/builtin/edit.d.ts +6 -0
  379. package/dist/tool-system/builtin/edit.js +100 -0
  380. package/dist/tool-system/builtin/file-cache.d.ts +11 -0
  381. package/dist/tool-system/builtin/file-cache.js +39 -0
  382. package/dist/tool-system/builtin/glob.d.ts +7 -0
  383. package/dist/tool-system/builtin/glob.js +76 -0
  384. package/dist/tool-system/builtin/grep.d.ts +7 -0
  385. package/dist/tool-system/builtin/grep.js +150 -0
  386. package/dist/tool-system/builtin/index.d.ts +20 -0
  387. package/dist/tool-system/builtin/index.js +449 -0
  388. package/dist/tool-system/builtin/lsp.d.ts +6 -0
  389. package/dist/tool-system/builtin/lsp.js +141 -0
  390. package/dist/tool-system/builtin/mcp-tools.d.ts +10 -0
  391. package/dist/tool-system/builtin/mcp-tools.js +102 -0
  392. package/dist/tool-system/builtin/memory.d.ts +26 -0
  393. package/dist/tool-system/builtin/memory.js +226 -0
  394. package/dist/tool-system/builtin/notebook-edit.d.ts +6 -0
  395. package/dist/tool-system/builtin/notebook-edit.js +124 -0
  396. package/dist/tool-system/builtin/plan.d.ts +15 -0
  397. package/dist/tool-system/builtin/plan.js +55 -0
  398. package/dist/tool-system/builtin/powershell.d.ts +11 -0
  399. package/dist/tool-system/builtin/powershell.js +64 -0
  400. package/dist/tool-system/builtin/read.d.ts +6 -0
  401. package/dist/tool-system/builtin/read.js +70 -0
  402. package/dist/tool-system/builtin/remote-trigger.d.ts +6 -0
  403. package/dist/tool-system/builtin/remote-trigger.js +54 -0
  404. package/dist/tool-system/builtin/repl.d.ts +11 -0
  405. package/dist/tool-system/builtin/repl.js +82 -0
  406. package/dist/tool-system/builtin/send-message.d.ts +6 -0
  407. package/dist/tool-system/builtin/send-message.js +47 -0
  408. package/dist/tool-system/builtin/skill-prompt.d.ts +20 -0
  409. package/dist/tool-system/builtin/skill-prompt.js +52 -0
  410. package/dist/tool-system/builtin/skill.d.ts +9 -0
  411. package/dist/tool-system/builtin/skill.js +55 -0
  412. package/dist/tool-system/builtin/sleep.d.ts +6 -0
  413. package/dist/tool-system/builtin/sleep.js +33 -0
  414. package/dist/tool-system/builtin/task.d.ts +48 -0
  415. package/dist/tool-system/builtin/task.js +139 -0
  416. package/dist/tool-system/builtin/tool-search.d.ts +11 -0
  417. package/dist/tool-system/builtin/tool-search.js +90 -0
  418. package/dist/tool-system/builtin/web-fetch.d.ts +10 -0
  419. package/dist/tool-system/builtin/web-fetch.js +328 -0
  420. package/dist/tool-system/builtin/web-search.d.ts +25 -0
  421. package/dist/tool-system/builtin/web-search.js +174 -0
  422. package/dist/tool-system/builtin/worktree.d.ts +10 -0
  423. package/dist/tool-system/builtin/worktree.js +95 -0
  424. package/dist/tool-system/builtin/write.d.ts +6 -0
  425. package/dist/tool-system/builtin/write.js +36 -0
  426. package/dist/tool-system/context.d.ts +165 -0
  427. package/dist/tool-system/context.js +18 -0
  428. package/dist/tool-system/executor.d.ts +49 -0
  429. package/dist/tool-system/executor.js +495 -0
  430. package/dist/tool-system/investigation-guard.d.ts +46 -0
  431. package/dist/tool-system/investigation-guard.js +155 -0
  432. package/dist/tool-system/mcp-manager.d.ts +67 -0
  433. package/dist/tool-system/mcp-manager.js +249 -0
  434. package/dist/tool-system/permission.d.ts +111 -0
  435. package/dist/tool-system/permission.js +774 -0
  436. package/dist/tool-system/registry.d.ts +32 -0
  437. package/dist/tool-system/registry.js +131 -0
  438. package/dist/tool-system/sandbox/bwrap.d.ts +13 -0
  439. package/dist/tool-system/sandbox/bwrap.js +63 -0
  440. package/dist/tool-system/sandbox/index.d.ts +78 -0
  441. package/dist/tool-system/sandbox/index.js +222 -0
  442. package/dist/tool-system/sandbox/off.d.ts +2 -0
  443. package/dist/tool-system/sandbox/off.js +8 -0
  444. package/dist/tool-system/sandbox/seatbelt.d.ts +18 -0
  445. package/dist/tool-system/sandbox/seatbelt.js +109 -0
  446. package/dist/tool-system/task-guard.d.ts +29 -0
  447. package/dist/tool-system/task-guard.js +70 -0
  448. package/dist/tool-system/validation.d.ts +5 -0
  449. package/dist/tool-system/validation.js +39 -0
  450. package/dist/types.d.ts +376 -0
  451. package/dist/types.js +4 -0
  452. package/dist/updater.d.ts +65 -0
  453. package/dist/updater.js +405 -0
  454. package/dist/utils/debug.d.ts +41 -0
  455. package/dist/utils/debug.js +110 -0
  456. package/dist/utils/earlyInput.d.ts +43 -0
  457. package/dist/utils/earlyInput.js +166 -0
  458. package/dist/utils/env.d.ts +24 -0
  459. package/dist/utils/env.js +104 -0
  460. package/dist/utils/envUtils.d.ts +51 -0
  461. package/dist/utils/envUtils.js +135 -0
  462. package/dist/utils/execFileNoThrow.d.ts +39 -0
  463. package/dist/utils/execFileNoThrow.js +74 -0
  464. package/dist/utils/format.d.ts +44 -0
  465. package/dist/utils/format.js +236 -0
  466. package/dist/utils/intl.d.ts +22 -0
  467. package/dist/utils/intl.js +83 -0
  468. package/dist/utils/lockfile.d.ts +15 -0
  469. package/dist/utils/lockfile.js +30 -0
  470. package/dist/utils/memoize.d.ts +19 -0
  471. package/dist/utils/memoize.js +14 -0
  472. package/dist/utils/semver.d.ts +6 -0
  473. package/dist/utils/semver.js +13 -0
  474. package/dist/utils/sliceAnsi.d.ts +12 -0
  475. package/dist/utils/sliceAnsi.js +62 -0
  476. package/dist/utils/systemTheme.d.ts +40 -0
  477. package/dist/utils/systemTheme.js +108 -0
  478. package/dist/utils/task-sanitizer.d.ts +6 -0
  479. package/dist/utils/task-sanitizer.js +24 -0
  480. package/dist/utils/theme.d.ts +93 -0
  481. package/dist/utils/theme.js +544 -0
  482. package/dist/utils/toolDisplay.d.ts +31 -0
  483. package/dist/utils/toolDisplay.js +188 -0
  484. package/package.json +72 -0
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Abstract base class for all LLM provider clients.
3
+ */
4
+ import { LLMError, ContextLimitError, LLMRateLimitError } from "../exceptions.js";
5
+ import { logger } from "../logging/logger.js";
6
+ export class LLMClientBase {
7
+ config;
8
+ provider;
9
+ model;
10
+ temperature;
11
+ maxTokens;
12
+ timeout;
13
+ retryMaxAttempts;
14
+ enableStreaming;
15
+ /**
16
+ * Process-wide hook fired on every LLM response. The CLI installs this in
17
+ * main.ts to feed the cost tracker; lives on the base class so every code
18
+ * path (REPL, run, arena, sub-agents) reports through one funnel without
19
+ * each call site needing to remember.
20
+ */
21
+ static onUsage;
22
+ usage = {
23
+ records: [],
24
+ totalPromptTokens: 0,
25
+ totalCompletionTokens: 0,
26
+ totalTokens: 0,
27
+ requestCount: 0,
28
+ };
29
+ constructor(config) {
30
+ this.config = config;
31
+ this.provider = config.provider;
32
+ this.model = config.model;
33
+ this.temperature = config.temperature ?? 0.3;
34
+ this.maxTokens = config.maxTokens ?? 8192;
35
+ this.timeout = config.timeout ?? 120_000;
36
+ this.retryMaxAttempts = config.retryMaxAttempts ?? 3;
37
+ this.enableStreaming = config.enableStreaming ?? true;
38
+ this.initClient();
39
+ }
40
+ recordUsage(usage, options) {
41
+ if (options?.recordUsage === false)
42
+ return;
43
+ this.usage.records.push(usage);
44
+ this.usage.totalPromptTokens += usage.promptTokens;
45
+ this.usage.totalCompletionTokens += usage.completionTokens;
46
+ this.usage.totalTokens += usage.totalTokens;
47
+ this.usage.requestCount++;
48
+ LLMClientBase.onUsage?.(this.model, usage);
49
+ }
50
+ getUsage() {
51
+ return { ...this.usage };
52
+ }
53
+ async withRetry(fn, maxAttempts) {
54
+ const attempts = maxAttempts ?? this.retryMaxAttempts;
55
+ let lastError;
56
+ for (let attempt = 1; attempt <= attempts; attempt++) {
57
+ try {
58
+ return await fn();
59
+ }
60
+ catch (err) {
61
+ lastError = err;
62
+ if (err instanceof ContextLimitError)
63
+ throw err;
64
+ if (err instanceof LLMRateLimitError) {
65
+ const waitMs = (err.retryAfter ?? attempt * 2) * 1000;
66
+ logger.warn("llm.retry", {
67
+ cat: "llm",
68
+ provider: this.provider,
69
+ model: this.model,
70
+ attempt,
71
+ of: attempts,
72
+ reason: "rate_limit",
73
+ waitMs,
74
+ });
75
+ await new Promise((r) => setTimeout(r, waitMs));
76
+ continue;
77
+ }
78
+ // 4xx (except 429, handled above as LLMRateLimitError) is a
79
+ // deterministic client-side mistake — bad message sequence,
80
+ // unauthorized, model not found, prompt too long. Retrying
81
+ // gives the same answer 3 times with growing backoff and
82
+ // burns ~9 s of user time. Surface immediately.
83
+ if (isClientError(err)) {
84
+ logger.warn("llm.client_error_no_retry", {
85
+ cat: "llm",
86
+ provider: this.provider,
87
+ model: this.model,
88
+ status: err.status,
89
+ error: err.message,
90
+ });
91
+ throw err;
92
+ }
93
+ if (attempt === attempts) {
94
+ logger.error("llm.exhausted", {
95
+ cat: "llm",
96
+ provider: this.provider,
97
+ model: this.model,
98
+ attempts,
99
+ error: err.message,
100
+ });
101
+ break;
102
+ }
103
+ const backoff = Math.min(1000 * Math.pow(2, attempt - 1), 30_000);
104
+ logger.warn("llm.retry", {
105
+ cat: "llm",
106
+ provider: this.provider,
107
+ model: this.model,
108
+ attempt,
109
+ of: attempts,
110
+ reason: "error",
111
+ error: err.message,
112
+ backoffMs: backoff,
113
+ });
114
+ await new Promise((r) => setTimeout(r, backoff));
115
+ }
116
+ }
117
+ throw lastError ?? new LLMError("Unknown LLM error");
118
+ }
119
+ }
120
+ /**
121
+ * Detect HTTP 4xx errors from provider SDKs so withRetry can bail
122
+ * without burning backoff time. OpenAI/Anthropic SDKs both attach a
123
+ * numeric `status` to their error objects; we treat 400-499 as
124
+ * non-retryable (429 is handled separately above as a rate-limit).
125
+ *
126
+ * Network errors and 5xx fall through and remain retryable.
127
+ */
128
+ function isClientError(err) {
129
+ if (typeof err !== "object" || err === null)
130
+ return false;
131
+ const status = err.status;
132
+ if (typeof status !== "number")
133
+ return false;
134
+ if (status === 429)
135
+ return false;
136
+ return status >= 400 && status < 500;
137
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * LLM provider factory with registry pattern.
3
+ */
4
+ import type { LLMConfig } from "../types.js";
5
+ import type { LLMClientBase } from "./client-base.js";
6
+ type ProviderConstructor = new (config: LLMConfig) => LLMClientBase;
7
+ declare const PROVIDER_REGISTRY: Map<string, ProviderConstructor>;
8
+ export declare function registerProvider(name: string, cls: ProviderConstructor): void;
9
+ export declare function createLLMClient(config: LLMConfig): Promise<LLMClientBase>;
10
+ export { PROVIDER_REGISTRY };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * LLM provider factory with registry pattern.
3
+ */
4
+ import { LLMError } from "../exceptions.js";
5
+ const PROVIDER_REGISTRY = new Map();
6
+ export function registerProvider(name, cls) {
7
+ PROVIDER_REGISTRY.set(name, cls);
8
+ }
9
+ export async function createLLMClient(config) {
10
+ let Cls = PROVIDER_REGISTRY.get(config.provider);
11
+ if (!Cls) {
12
+ // Auto-register built-in providers on first use
13
+ if (config.provider === "anthropic") {
14
+ const { AnthropicClient } = await import("./providers/anthropic.js");
15
+ registerProvider("anthropic", AnthropicClient);
16
+ Cls = AnthropicClient;
17
+ }
18
+ else if (config.provider === "openai") {
19
+ const { OpenAIClient } = await import("./providers/openai.js");
20
+ registerProvider("openai", OpenAIClient);
21
+ Cls = OpenAIClient;
22
+ }
23
+ }
24
+ if (!Cls) {
25
+ throw new LLMError(`Unknown LLM provider: ${config.provider}. Available: ${[...PROVIDER_REGISTRY.keys()].join(", ")}`);
26
+ }
27
+ return new Cls(config);
28
+ }
29
+ export { PROVIDER_REGISTRY };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Cache file IO for per-provider model lists.
3
+ *
4
+ * One file per provider key under <cacheDir>/<providerKey>.json. TTL is
5
+ * 7 days. Callers decide whether to honor staleness — readCache just
6
+ * reads, isStale just checks. Malformed/missing files yield undefined.
7
+ */
8
+ export interface CachedModel {
9
+ id: string;
10
+ contextLength: number;
11
+ maxOutputTokens: number;
12
+ }
13
+ export interface ModelCacheFile {
14
+ fetchedAt: string;
15
+ providerKey: string;
16
+ models: CachedModel[];
17
+ }
18
+ export declare function readCache(cacheDir: string, providerKey: string): ModelCacheFile | undefined;
19
+ export declare function writeCache(cacheDir: string, providerKey: string, models: CachedModel[]): ModelCacheFile;
20
+ export declare function isStale(file: ModelCacheFile, now?: number): boolean;
21
+ export declare function defaultCacheDir(): string;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Cache file IO for per-provider model lists.
3
+ *
4
+ * One file per provider key under <cacheDir>/<providerKey>.json. TTL is
5
+ * 7 days. Callers decide whether to honor staleness — readCache just
6
+ * reads, isStale just checks. Malformed/missing files yield undefined.
7
+ */
8
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
9
+ import { homedir } from "node:os";
10
+ import { join } from "node:path";
11
+ const TTL_MS = 7 * 24 * 3600 * 1000;
12
+ export function readCache(cacheDir, providerKey) {
13
+ const path = join(cacheDir, `${providerKey}.json`);
14
+ if (!existsSync(path))
15
+ return undefined;
16
+ try {
17
+ const raw = readFileSync(path, "utf-8");
18
+ const parsed = JSON.parse(raw);
19
+ if (!parsed || !Array.isArray(parsed.models))
20
+ return undefined;
21
+ return parsed;
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ export function writeCache(cacheDir, providerKey, models) {
28
+ if (!existsSync(cacheDir))
29
+ mkdirSync(cacheDir, { recursive: true });
30
+ const payload = {
31
+ fetchedAt: new Date().toISOString(),
32
+ providerKey,
33
+ models,
34
+ };
35
+ writeFileSync(join(cacheDir, `${providerKey}.json`), JSON.stringify(payload, null, 2), "utf-8");
36
+ return payload;
37
+ }
38
+ export function isStale(file, now = Date.now()) {
39
+ const ts = Date.parse(file.fetchedAt);
40
+ if (!Number.isFinite(ts))
41
+ return true;
42
+ return now - ts > TTL_MS;
43
+ }
44
+ export function defaultCacheDir() {
45
+ return join(homedir(), ".code-shell", "cache", "models");
46
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Fetch a provider's model list from its official /v1/models endpoint
3
+ * (or the local OpenRouter snapshot). Normalizes wildly different
4
+ * response shapes into a uniform `CachedModel[]`, applies the kind's
5
+ * chat-only filter, and writes to disk cache.
6
+ *
7
+ * Network failures don't throw — they return `{ models: [], error }`
8
+ * so the UI can prompt the user to refresh later or fall back to
9
+ * manual entry.
10
+ */
11
+ import { type ProviderKindName } from "./provider-kinds.js";
12
+ import { type ModelCacheFile } from "./model-cache.js";
13
+ export interface FetcherProvider {
14
+ key: string;
15
+ kind: ProviderKindName;
16
+ baseUrl: string;
17
+ apiKey: string | undefined;
18
+ modelsPath?: string;
19
+ }
20
+ export interface FetchOptions {
21
+ cacheDir: string;
22
+ refresh?: boolean;
23
+ timeoutMs?: number;
24
+ }
25
+ export interface FetchResult extends ModelCacheFile {
26
+ error?: string;
27
+ fromCache?: boolean;
28
+ }
29
+ export declare function fetchModelList(provider: FetcherProvider, opts: FetchOptions): Promise<FetchResult>;
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Fetch a provider's model list from its official /v1/models endpoint
3
+ * (or the local OpenRouter snapshot). Normalizes wildly different
4
+ * response shapes into a uniform `CachedModel[]`, applies the kind's
5
+ * chat-only filter, and writes to disk cache.
6
+ *
7
+ * Network failures don't throw — they return `{ models: [], error }`
8
+ * so the UI can prompt the user to refresh later or fall back to
9
+ * manual entry.
10
+ */
11
+ import { readFileSync, existsSync } from "node:fs";
12
+ import { fileURLToPath } from "node:url";
13
+ import { dirname, join } from "node:path";
14
+ import { getKindMeta, } from "./provider-kinds.js";
15
+ import { readCache, writeCache, isStale, } from "./model-cache.js";
16
+ import { listStaticModels, hasStaticCatalog, } from "../data/static-catalogs.js";
17
+ import { findOpenRouterModel } from "../data/openrouter-models.js";
18
+ const HERE = dirname(fileURLToPath(import.meta.url));
19
+ const OPENROUTER_SNAPSHOT = join(HERE, "..", "data", "openrouter-models.json");
20
+ export async function fetchModelList(provider, opts) {
21
+ const meta = getKindMeta(provider.kind);
22
+ if (!opts.refresh) {
23
+ const cached = readCache(opts.cacheDir, provider.key);
24
+ if (cached && !isStale(cached))
25
+ return { ...cached, fromCache: true };
26
+ }
27
+ if (provider.kind === "openrouter") {
28
+ return loadOpenRouterSnapshot(provider.key, opts.cacheDir);
29
+ }
30
+ try {
31
+ const path = provider.modelsPath ?? meta.modelsPath;
32
+ const url = new URL(joinUrl(provider.baseUrl, path));
33
+ const headers = meta.authHeader(provider.apiKey ?? "");
34
+ if (meta.authQuery) {
35
+ const q = meta.authQuery(provider.apiKey ?? "");
36
+ for (const [k, v] of Object.entries(q))
37
+ url.searchParams.set(k, v);
38
+ }
39
+ const res = await fetch(url.toString(), {
40
+ headers: { Accept: "application/json", ...headers },
41
+ signal: AbortSignal.timeout(opts.timeoutMs ?? 20_000),
42
+ });
43
+ if (!res.ok) {
44
+ // 401/403 means the key is wrong (or revoked) — falling back to the
45
+ // static catalog would show the user a model list they can't actually
46
+ // call, deferring the real error to the first chat turn. Surface the
47
+ // auth failure now with an empty list.
48
+ const isAuth = res.status === 401 || res.status === 403;
49
+ return errorResult(provider.key, opts.cacheDir, `HTTP ${res.status}`, isAuth ? undefined : provider.kind);
50
+ }
51
+ const payload = (await res.json());
52
+ const raw = normalize(payload, meta.protocol);
53
+ const filtered = raw.filter((m) => meta.chatFilter(m.id));
54
+ const sorted = sortByRecency(filtered);
55
+ const enriched = enrichFromStaticCatalog(provider.kind, sorted);
56
+ const finalModels = enrichFromOpenRouterSnapshot(provider.kind, enriched);
57
+ const file = writeCache(opts.cacheDir, provider.key, finalModels);
58
+ return file;
59
+ }
60
+ catch (err) {
61
+ const msg = err.message || String(err);
62
+ return errorResult(provider.key, opts.cacheDir, msg, provider.kind);
63
+ }
64
+ }
65
+ /**
66
+ * Left-join static-catalog metadata onto live /models results. The live
67
+ * endpoint is the source of truth for which ids exist; the static table
68
+ * fills in contextLength / maxOutputTokens / pricing that most vendors
69
+ * don't expose on /v1/models. Live values are preserved when present.
70
+ *
71
+ * Models present only in the static table (not returned by the live API
72
+ * — e.g. newly-deprecated ids or vendor-hidden previews) are appended at
73
+ * the end so the picker can still show them.
74
+ */
75
+ function enrichFromStaticCatalog(kind, live) {
76
+ if (!hasStaticCatalog(kind))
77
+ return live;
78
+ const staticModels = listStaticModels(kind);
79
+ const staticById = new Map(staticModels.map((m) => [m.id, m]));
80
+ const liveIds = new Set(live.map((m) => m.id));
81
+ const merged = live.map((m) => {
82
+ const stat = staticById.get(m.id);
83
+ if (!stat)
84
+ return m;
85
+ return {
86
+ id: m.id,
87
+ contextLength: m.contextLength > 0 ? m.contextLength : stat.contextLength,
88
+ maxOutputTokens: m.maxOutputTokens > 0 ? m.maxOutputTokens : stat.maxOutputTokens,
89
+ };
90
+ });
91
+ for (const stat of staticModels) {
92
+ if (!liveIds.has(stat.id)) {
93
+ merged.push({
94
+ id: stat.id,
95
+ contextLength: stat.contextLength,
96
+ maxOutputTokens: stat.maxOutputTokens,
97
+ });
98
+ }
99
+ }
100
+ return merged;
101
+ }
102
+ /**
103
+ * Provider kind → OpenRouter vendor prefix. OpenRouter ids are
104
+ * `<vendor>/<model>`; native providers return bare model ids
105
+ * (`gpt-5.5`, `claude-opus-4.6`). To cross-reference, we prepend
106
+ * the kind's vendor prefix. Kinds that don't map to a single
107
+ * OpenRouter vendor (groq is infra not a model vendor, ollama is
108
+ * local, openrouter is itself, custom is unknown) are omitted —
109
+ * fallback simply does nothing for them.
110
+ */
111
+ const OPENROUTER_VENDOR_BY_KIND = {
112
+ openai: "openai",
113
+ anthropic: "anthropic",
114
+ deepseek: "deepseek",
115
+ google: "google",
116
+ zai: "z-ai",
117
+ xai: "x-ai",
118
+ mistral: "mistralai",
119
+ };
120
+ /**
121
+ * Final fallback: any model still missing contextLength or
122
+ * maxOutputTokens after the per-provider static catalog merge
123
+ * gets cross-referenced against the bundled OpenRouter snapshot
124
+ * (`<vendor>/<id>`). Live values from the upstream `/models`
125
+ * call always win; this only fills zeros.
126
+ */
127
+ function enrichFromOpenRouterSnapshot(kind, models) {
128
+ const vendor = OPENROUTER_VENDOR_BY_KIND[kind];
129
+ if (!vendor)
130
+ return models;
131
+ return models.map((m) => {
132
+ if (m.contextLength > 0 && m.maxOutputTokens > 0)
133
+ return m;
134
+ const hit = findOpenRouterModel(`${vendor}/${m.id}`);
135
+ if (!hit)
136
+ return m;
137
+ return {
138
+ id: m.id,
139
+ contextLength: m.contextLength > 0 ? m.contextLength : hit.contextLength,
140
+ maxOutputTokens: m.maxOutputTokens > 0 ? m.maxOutputTokens : hit.maxOutputTokens,
141
+ };
142
+ });
143
+ }
144
+ /**
145
+ * Newest-first ordering. Vendors reliably encode recency as a version
146
+ * suffix on the model family name: `gpt-5.5` > `gpt-5.4` > `gpt-5`,
147
+ * `claude-4.7` > `claude-4.6`, `gemini-2.5` > `gemini-2.0`. We extract
148
+ * that single "family version" number and sort descending.
149
+ *
150
+ * Versions can appear three ways:
151
+ * - decimal: `gpt-5.5`, `claude-4.7` → 5.5 / 4.7
152
+ * - dash-decimal: `claude-sonnet-4-6`, → 4.6
153
+ * `claude-3-5-haiku` → 3.5
154
+ * - bare integer: `gpt-4`, `o3`, `o4-mini` → 4 / 3 / 4
155
+ *
156
+ * Dash-decimal is Anthropic's house style: `claude-<family>-<major>-<minor>`.
157
+ * We only treat `<small int>-<small int>` as a version when both halves
158
+ * look like version components (1–2 digits each), so we don't accidentally
159
+ * turn snapshot-ish `gpt-4-0613` into 4.613.
160
+ *
161
+ * What we deliberately ignore:
162
+ * - 4-digit date-ish numbers like `0613`, `1106`, `0914` baked into
163
+ * legacy ids. These are snapshots, not versions.
164
+ *
165
+ * Tie-breaker: shorter id wins (so `gpt-5.5` sorts above `gpt-5.5-pro`),
166
+ * then alphabetic for stable output.
167
+ */
168
+ function sortByRecency(models) {
169
+ const versionOf = (id) => {
170
+ // Match a version *as a token boundary* — preceded by start or
171
+ // a non-digit, and not followed by another digit. Decimals win
172
+ // over bare integers if both match.
173
+ const decimal = id.match(/(?:^|[^\d])(\d+\.\d+)(?!\d)/);
174
+ if (decimal)
175
+ return Number(decimal[1]);
176
+ // Dash-decimal (Anthropic style): both halves 1–2 digits to avoid
177
+ // catching dated snapshots like `gpt-4-0613` (4-digit second half).
178
+ const dashDecimal = id.match(/(?:^|[^\d])(\d{1,2})-(\d{1,2})(?!\d)/);
179
+ if (dashDecimal)
180
+ return Number(`${dashDecimal[1]}.${dashDecimal[2]}`);
181
+ // Bare-integer version: 1–2 digits only (skips `0613`-style dates).
182
+ const integer = id.match(/(?:^|[^\d])(\d{1,2})(?!\d)/);
183
+ if (integer)
184
+ return Number(integer[1]);
185
+ return -1;
186
+ };
187
+ return [...models].sort((a, b) => {
188
+ const va = versionOf(a.id);
189
+ const vb = versionOf(b.id);
190
+ if (va !== vb)
191
+ return vb - va;
192
+ if (a.id.length !== b.id.length)
193
+ return a.id.length - b.id.length;
194
+ return a.id.localeCompare(b.id);
195
+ });
196
+ }
197
+ function normalize(payload, protocol) {
198
+ switch (protocol) {
199
+ case "ollama": {
200
+ const p = payload;
201
+ return (p.models ?? []).map((m) => ({ id: m.name, contextLength: 0, maxOutputTokens: 0 }));
202
+ }
203
+ case "anthropic-style": {
204
+ const p = payload;
205
+ return (p.data ?? []).map((m) => ({
206
+ id: m.id,
207
+ contextLength: m.context_window ?? 200_000,
208
+ maxOutputTokens: m.max_output_tokens ?? 0,
209
+ }));
210
+ }
211
+ case "gemini": {
212
+ const p = payload;
213
+ return (p.models ?? []).map((m) => ({
214
+ id: m.name.replace(/^models\//, ""),
215
+ contextLength: m.inputTokenLimit ?? 0,
216
+ maxOutputTokens: m.outputTokenLimit ?? 0,
217
+ }));
218
+ }
219
+ case "openai-compat": {
220
+ const p = payload;
221
+ return (p.data ?? []).map((m) => ({
222
+ id: m.id,
223
+ contextLength: m.context_window ?? m.context_length ?? 0,
224
+ maxOutputTokens: m.max_completion_tokens ?? 0,
225
+ }));
226
+ }
227
+ }
228
+ // exhaustiveness: TS error if a new ProviderProtocol is added.
229
+ const _exhaustive = protocol;
230
+ return _exhaustive;
231
+ }
232
+ function loadOpenRouterSnapshot(providerKey, cacheDir) {
233
+ if (!existsSync(OPENROUTER_SNAPSHOT)) {
234
+ return errorResult(providerKey, cacheDir, "openrouter snapshot missing");
235
+ }
236
+ try {
237
+ const snapshot = JSON.parse(readFileSync(OPENROUTER_SNAPSHOT, "utf-8"));
238
+ const models = (snapshot.models ?? []).map((m) => ({
239
+ id: m.id,
240
+ contextLength: m.contextLength ?? 0,
241
+ maxOutputTokens: m.maxOutputTokens ?? 0,
242
+ }));
243
+ return writeCache(cacheDir, providerKey, models);
244
+ }
245
+ catch (err) {
246
+ return errorResult(providerKey, cacheDir, err.message);
247
+ }
248
+ }
249
+ function errorResult(providerKey, cacheDir, error, kind) {
250
+ const stale = readCache(cacheDir, providerKey);
251
+ if (stale)
252
+ return { ...stale, error, fromCache: true };
253
+ if (kind && hasStaticCatalog(kind)) {
254
+ const models = listStaticModels(kind).map((m) => ({
255
+ id: m.id,
256
+ contextLength: m.contextLength,
257
+ maxOutputTokens: m.maxOutputTokens,
258
+ }));
259
+ return {
260
+ fetchedAt: new Date().toISOString(),
261
+ providerKey,
262
+ models,
263
+ error,
264
+ };
265
+ }
266
+ return {
267
+ fetchedAt: new Date().toISOString(),
268
+ providerKey,
269
+ models: [],
270
+ error,
271
+ };
272
+ }
273
+ function joinUrl(base, path) {
274
+ if (!base)
275
+ return path;
276
+ // Allow a per-provider override to specify an absolute URL — needed for
277
+ // providers like Gemini whose chat completions live under /v1beta/openai
278
+ // but model listing stays on /v1beta/models.
279
+ if (/^https?:\/\//i.test(path))
280
+ return path;
281
+ return `${base.replace(/\/$/, "")}${path.startsWith("/") ? "" : "/"}${path}`;
282
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * ModelPool — runtime model registry.
3
+ *
4
+ * Holds all available models loaded from settings. Provides:
5
+ * - `get(key?)` — retrieve a model config by key, or the active one
6
+ * - `switch(key)` — change the active model
7
+ * - `list()` — list all available models
8
+ * - `register(entry)` — add a model at runtime
9
+ *
10
+ * Consumers:
11
+ * - Engine/TurnLoop: `pool.get()` for the active model
12
+ * - Arena: `pool.get("sonnet")` to resolve participants by key
13
+ * - /model command: `pool.switch("haiku")` for hot-swap
14
+ */
15
+ import type { LLMConfig } from "../types.js";
16
+ export interface ModelEntry {
17
+ /** Short alias: "claude", "sonnet", "haiku", "gpt", "deepseek" */
18
+ key: string;
19
+ /** Human-readable label. Auto-generated from model path if not provided. */
20
+ label?: string;
21
+ provider: string;
22
+ /** Full model path: "anthropic/claude-opus-4-6" */
23
+ model: string;
24
+ baseUrl?: string;
25
+ apiKey?: string;
26
+ maxOutputTokens?: number;
27
+ /** Per-model context window size. Falls back to config.maxContextTokens → 200_000. */
28
+ maxContextTokens?: number;
29
+ /** Optional reference into ProviderCatalog. When set, baseUrl/apiKey
30
+ * come from the catalog unless the entry overrides them. */
31
+ providerKey?: string;
32
+ /**
33
+ * Per-model thinking override. Wins over the provider-level setting
34
+ * (ProviderCatalog entry's `thinking`). Useful when models in the same
35
+ * provider need different defaults — e.g. DeepSeek V4 Pro off but
36
+ * V4 Flash on.
37
+ */
38
+ thinking?: "enabled" | "disabled";
39
+ }
40
+ export declare class ModelPool {
41
+ private models;
42
+ private activeKey;
43
+ private providerCatalog;
44
+ private cacheDir;
45
+ setProviderCatalog(cat: import("./provider-catalog.js").ProviderCatalog): void;
46
+ setCacheDir(dir: string): void;
47
+ /**
48
+ * For each entry that lacks an explicit maxContextTokens but has a
49
+ * providerKey, fill it in. Lookup order:
50
+ * 1. The provider's cached /v1/models response (most authoritative —
51
+ * it's what the vendor itself returned at last sync).
52
+ * 2. The bundled OpenRouter snapshot, keyed by `<vendor>/<id>` — covers
53
+ * the common case where a direct-provider model (e.g. `gpt-5.5`)
54
+ * is also published on OpenRouter with full metadata.
55
+ * 3. A final 200k floor so unknown models still get *some* context
56
+ * window rather than tripping max-token math downstream.
57
+ *
58
+ * Entries with an explicit maxContextTokens (set by the user in settings
59
+ * or by a prior code path) are left alone — we never overwrite what the
60
+ * user typed in.
61
+ */
62
+ reloadCachedContextWindows(): void;
63
+ private resolveContextWindow;
64
+ /**
65
+ * Build a pool from an array of model entries.
66
+ * The first entry (or the one matching `defaultKey`) becomes active.
67
+ */
68
+ constructor(entries?: ModelEntry[], defaultKey?: string);
69
+ /** Register a model at runtime. */
70
+ register(entry: ModelEntry): void;
71
+ /** Fill in known defaults (e.g. context window for DeepSeek V4) when the entry doesn't specify them. */
72
+ private withBuiltinDefaults;
73
+ /** Switch the active model. Throws if key not found. */
74
+ switch(key: string): ModelEntry;
75
+ /** Get a model by key. No key = active model. Returns undefined if not found. */
76
+ get(key?: string): ModelEntry | undefined;
77
+ /** Get the active model key. */
78
+ getActiveKey(): string | undefined;
79
+ /** List all registered models. */
80
+ list(): ModelEntry[];
81
+ /** Number of registered models. */
82
+ get size(): number;
83
+ /** Check if a key exists. */
84
+ has(key: string): boolean;
85
+ /**
86
+ * Build an LLMConfig for a given model entry, merging with a base config
87
+ * (inherits apiKey, baseUrl, etc. from the base if not set on the entry).
88
+ */
89
+ toLLMConfig(entry: ModelEntry, base?: Partial<LLMConfig>): LLMConfig;
90
+ /**
91
+ * Build an LLMConfig for the active model (or a specific key),
92
+ * merging with a base config.
93
+ */
94
+ resolveLLMConfig(key?: string, base?: Partial<LLMConfig>): LLMConfig | undefined;
95
+ }