@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,625 @@
1
+ /**
2
+ * Onboarding data layer — provider catalog, env detection, key validation,
3
+ * settings persistence. The interactive flow itself is rendered by Ink
4
+ * (see src/ui/components/OnboardingPrompt.tsx); this module only exposes
5
+ * pure(-ish) helpers it consumes, so there's a single input stack.
6
+ */
7
+ import { mkdirSync, writeFileSync, readFileSync, existsSync, renameSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ import { homedir } from "node:os";
10
+ import { getOpenRouterModels } from "./data/openrouter-models.js";
11
+ import { sanitizeApiKey } from "./llm/api-key-sanitize.js";
12
+ export const PROVIDERS = [
13
+ {
14
+ id: "openrouter",
15
+ name: "OpenRouter (推荐 — 支持所有模型)",
16
+ envKey: "OPENROUTER_API_KEY",
17
+ provider: "openai",
18
+ baseUrl: "https://openrouter.ai/api/v1",
19
+ keyUrl: "https://openrouter.ai/keys",
20
+ keyPrefix: "sk-or-",
21
+ // First entry is the zero-config default (auto-activated when the
22
+ // user starts with only an env key, no onboarding). Sonnet beats Opus
23
+ // here because it's ~5x cheaper and a safer pick for someone who
24
+ // hasn't picked yet — Opus stays one slot away for anyone who wants it.
25
+ models: [
26
+ "anthropic/claude-sonnet-4.6",
27
+ "anthropic/claude-opus-4.7",
28
+ "anthropic/claude-haiku-4.5",
29
+ "openai/gpt-5",
30
+ "openai/gpt-5-mini",
31
+ "openai/gpt-4o",
32
+ "openai/o4-mini",
33
+ "openai/o3",
34
+ "google/gemini-2.5-pro",
35
+ "google/gemini-2.5-flash",
36
+ "deepseek/deepseek-chat",
37
+ "deepseek/deepseek-reasoner",
38
+ "qwen/qwen3-coder",
39
+ "meta-llama/llama-4-maverick",
40
+ ],
41
+ },
42
+ {
43
+ id: "anthropic",
44
+ name: "Anthropic (直连 Claude API)",
45
+ envKey: "ANTHROPIC_API_KEY",
46
+ provider: "anthropic",
47
+ baseUrl: "https://api.anthropic.com",
48
+ keyUrl: "https://console.anthropic.com/settings/keys",
49
+ keyPrefix: "sk-ant-",
50
+ models: [
51
+ "claude-sonnet-4-6",
52
+ "claude-opus-4-7",
53
+ "claude-haiku-4-5",
54
+ ],
55
+ },
56
+ {
57
+ id: "openai",
58
+ name: "OpenAI",
59
+ envKey: "OPENAI_API_KEY",
60
+ provider: "openai",
61
+ baseUrl: "https://api.openai.com/v1",
62
+ keyUrl: "https://platform.openai.com/api-keys",
63
+ keyPrefix: "sk-",
64
+ models: ["gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-4o", "o4-mini", "o3"],
65
+ },
66
+ {
67
+ id: "deepseek",
68
+ name: "DeepSeek (官方直连)",
69
+ envKey: "DEEPSEEK_API_KEY",
70
+ provider: "openai",
71
+ baseUrl: "https://api.deepseek.com/v1",
72
+ keyUrl: "https://platform.deepseek.com/api_keys",
73
+ keyPrefix: "sk-",
74
+ models: ["deepseek-v4-pro", "deepseek-v4-flash", "deepseek-chat"],
75
+ },
76
+ {
77
+ id: "zai",
78
+ name: "Z.AI (GLM 官方)",
79
+ envKey: "ZAI_API_KEY",
80
+ provider: "openai",
81
+ baseUrl: "https://api.z.ai/api/paas/v4",
82
+ keyUrl: "https://z.ai/manage-apikey/apikey-list",
83
+ keyPrefix: "",
84
+ models: ["glm-5.1", "glm-4.6", "glm-4.5-air"],
85
+ },
86
+ {
87
+ id: "gemini",
88
+ name: "Google Gemini (官方直连)",
89
+ envKey: "GEMINI_API_KEY",
90
+ provider: "openai",
91
+ baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
92
+ keyUrl: "https://aistudio.google.com/apikey",
93
+ keyPrefix: "",
94
+ models: [
95
+ "gemini-2.5-pro",
96
+ "gemini-2.5-flash",
97
+ "gemini-2.0-flash",
98
+ ],
99
+ },
100
+ {
101
+ id: "ollama",
102
+ name: "Ollama (本地,无需 Key)",
103
+ envKey: "",
104
+ provider: "openai",
105
+ baseUrl: "http://localhost:11434/v1",
106
+ keyUrl: "https://ollama.com/library",
107
+ keyPrefix: "",
108
+ models: ["llama3.1", "qwen2.5-coder", "deepseek-r1", "mistral", "gemma3"],
109
+ noKey: true,
110
+ },
111
+ {
112
+ id: "custom",
113
+ name: "自定义 (任何 OpenAI 兼容 API)",
114
+ envKey: "",
115
+ provider: "openai",
116
+ baseUrl: "",
117
+ keyUrl: "",
118
+ keyPrefix: "",
119
+ models: [],
120
+ },
121
+ ];
122
+ // ─── Dynamic model list (OpenRouter snapshot) ────────────────────
123
+ /**
124
+ * Curated vendors and how many of their newest models to surface in the
125
+ * onboarding picker. Order matters — first vendors appear first.
126
+ * Tweak this if a new vendor becomes worth exposing in the picker.
127
+ */
128
+ const OPENROUTER_VENDORS = [
129
+ { prefix: "anthropic/", take: 4 },
130
+ { prefix: "openai/", take: 5 },
131
+ { prefix: "google/", take: 3 },
132
+ { prefix: "deepseek/", take: 3 },
133
+ { prefix: "x-ai/", take: 2 },
134
+ { prefix: "qwen/", take: 2 },
135
+ { prefix: "meta-llama/", take: 2 },
136
+ { prefix: "mistralai/", take: 1 },
137
+ ];
138
+ /**
139
+ * Build the OpenRouter model picker list from the bundled snapshot.
140
+ * Filters out `:free`/preview variants for the default picker (still
141
+ * reachable via /models add). Returns the hardcoded list as fallback
142
+ * when the snapshot is empty (e.g. fresh checkout before first build).
143
+ */
144
+ function buildOpenRouterModelList(fallback) {
145
+ const all = getOpenRouterModels();
146
+ if (all.length === 0)
147
+ return fallback;
148
+ const skip = /(?:-guard|-embedding|-rerank|-vision-only|:free)/i;
149
+ const out = [];
150
+ for (const { prefix, take } of OPENROUTER_VENDORS) {
151
+ const candidates = all
152
+ .filter((m) => m.id.startsWith(prefix))
153
+ .filter((m) => !skip.test(m.id) && !m.id.includes("-preview"))
154
+ .slice(0, take);
155
+ out.push(...candidates.map((m) => m.id));
156
+ }
157
+ return out.length > 0 ? out : fallback;
158
+ }
159
+ /**
160
+ * Resolve the model list a provider should expose right now. For
161
+ * OpenRouter this comes from the snapshot; for direct providers it
162
+ * stays hardcoded (snapshot doesn't carry their native IDs).
163
+ */
164
+ export function resolveProviderModels(provider) {
165
+ if (provider.id === "openrouter") {
166
+ return buildOpenRouterModelList(provider.models);
167
+ }
168
+ return provider.models;
169
+ }
170
+ /**
171
+ * Scan environment for known provider API keys.
172
+ * Returns one entry per provider that has its envKey set.
173
+ */
174
+ export function detectEnvKeys() {
175
+ const found = [];
176
+ for (const p of PROVIDERS) {
177
+ if (!p.envKey)
178
+ continue;
179
+ const v = process.env[p.envKey];
180
+ if (!v)
181
+ continue;
182
+ // Env-sourced keys frequently carry CRLF/BOM/quotes from how the user set
183
+ // them (cmd `set FOO=...`, dotenv files with stray spaces, Windows clipboards
184
+ // pasted into a shell). Sanitize once at the boundary so downstream code
185
+ // never sees a dirty value.
186
+ const cleaned = sanitizeApiKey(v).value;
187
+ if (cleaned) {
188
+ found.push({ provider: p, envKey: p.envKey, apiKey: cleaned });
189
+ }
190
+ }
191
+ return found;
192
+ }
193
+ /** Mask a key for display: "sk-517f...b594" */
194
+ export function maskKey(key) {
195
+ if (key.length <= 12)
196
+ return key.slice(0, 2) + "***";
197
+ return `${key.slice(0, 6)}...${key.slice(-4)}`;
198
+ }
199
+ /**
200
+ * Find a provider definition that matches a given API key.
201
+ * Checks key prefix first, then env var match, then baseUrl.
202
+ */
203
+ export function detectProviderFromApiKey(apiKey, baseUrl) {
204
+ // 1. Try key prefix match
205
+ for (const p of PROVIDERS) {
206
+ if (p.keyPrefix && apiKey.startsWith(p.keyPrefix))
207
+ return p;
208
+ }
209
+ // 2. Try baseUrl match
210
+ if (baseUrl) {
211
+ for (const p of PROVIDERS) {
212
+ if (p.baseUrl && baseUrl.startsWith(p.baseUrl))
213
+ return p;
214
+ }
215
+ }
216
+ // 3. Try env var match
217
+ for (const p of PROVIDERS) {
218
+ if (!p.envKey)
219
+ continue;
220
+ const v = process.env[p.envKey];
221
+ if (v && sanitizeApiKey(v).value === apiKey)
222
+ return p;
223
+ }
224
+ return undefined;
225
+ }
226
+ // ─── API key validation ────────────────────────────────────────────
227
+ export async function validateApiKey(baseUrl, apiKey) {
228
+ try {
229
+ if (baseUrl.includes("openrouter")) {
230
+ const res = await fetch("https://openrouter.ai/api/v1/auth/key", {
231
+ headers: { Authorization: `Bearer ${apiKey}` },
232
+ });
233
+ const data = await res.json();
234
+ return !data.error;
235
+ }
236
+ const url = baseUrl.replace(/\/$/, "") + "/models";
237
+ const res = await fetch(url, {
238
+ headers: { Authorization: `Bearer ${apiKey}` },
239
+ });
240
+ return res.status !== 401 && res.status !== 403;
241
+ }
242
+ catch {
243
+ return true; // network error — can't validate, let it pass
244
+ }
245
+ }
246
+ // ─── Public API ────────────────────────────────────────────────────
247
+ /**
248
+ * Resolve an API key from the canonical fallback chain.
249
+ * Priority: 1) command-line option 2) settings.json 3) all provider env vars
250
+ */
251
+ export function resolveApiKey(optionsApiKey, settingsApiKey) {
252
+ if (optionsApiKey)
253
+ return optionsApiKey;
254
+ if (settingsApiKey)
255
+ return settingsApiKey;
256
+ for (const p of PROVIDERS) {
257
+ if (!p.envKey)
258
+ continue;
259
+ const v = process.env[p.envKey];
260
+ if (v && v.trim())
261
+ return v.trim();
262
+ }
263
+ return undefined;
264
+ }
265
+ /**
266
+ * Look up a previously-persisted API key for a given provider in
267
+ * ~/.code-shell/settings.json. Matches by baseUrl (each ProviderDef.baseUrl
268
+ * is unique, while `provider` is a generic kind like "openai" shared across
269
+ * multiple endpoints).
270
+ *
271
+ * Returns the first match found in: settings.models[] (preferred — newer),
272
+ * then settings.model (legacy top-level). undefined when nothing matches.
273
+ */
274
+ export function findSavedKeyForProvider(provider) {
275
+ const file = join(homedir(), ".code-shell", "settings.json");
276
+ if (!existsSync(file))
277
+ return undefined;
278
+ let data;
279
+ try {
280
+ data = JSON.parse(readFileSync(file, "utf-8"));
281
+ }
282
+ catch {
283
+ return undefined;
284
+ }
285
+ if (Array.isArray(data?.models)) {
286
+ for (const m of data.models) {
287
+ if (m?.apiKey && m?.baseUrl === provider.baseUrl) {
288
+ return { apiKey: String(m.apiKey), baseUrl: String(m.baseUrl) };
289
+ }
290
+ }
291
+ }
292
+ if (data?.model?.apiKey && data?.model?.baseUrl === provider.baseUrl) {
293
+ return {
294
+ apiKey: String(data.model.apiKey),
295
+ baseUrl: String(data.model.baseUrl),
296
+ };
297
+ }
298
+ return undefined;
299
+ }
300
+ /**
301
+ * Return the list of model IDs previously saved under this provider
302
+ * (matched by baseUrl). Used by the onboarding wizard to pre-populate the
303
+ * "model pool" step with the user's prior choices instead of resetting to
304
+ * just the provider's first model.
305
+ */
306
+ export function loadSavedModelsForProvider(provider) {
307
+ const file = join(homedir(), ".code-shell", "settings.json");
308
+ if (!existsSync(file))
309
+ return [];
310
+ let data;
311
+ try {
312
+ data = JSON.parse(readFileSync(file, "utf-8"));
313
+ }
314
+ catch {
315
+ return [];
316
+ }
317
+ if (!Array.isArray(data?.models))
318
+ return [];
319
+ const out = [];
320
+ for (const m of data.models) {
321
+ if (m?.baseUrl === provider.baseUrl && typeof m?.model === "string") {
322
+ out.push(m.model);
323
+ }
324
+ }
325
+ return out;
326
+ }
327
+ export function hasApiKey() {
328
+ // Env variables alone are NOT enough to skip onboarding — they're surfaced
329
+ // as a one-click option on the provider page instead. We only skip when the
330
+ // user has explicitly persisted a config. Checks all three locations the
331
+ // wizard might write to: top-level model.apiKey (legacy), models[].apiKey
332
+ // (per-pool-entry), providers[].apiKey (per-provider — what the current
333
+ // ProviderModelFlow actually writes). Missing any one of these made
334
+ // /logout look like a no-op when the others still held credentials.
335
+ // Reads ~/.code-shell/ only — ~/.claude/ compat was dropped because Claude
336
+ // Code's settings schema diverges and merging broke boot.
337
+ const p = join(homedir(), ".code-shell", "settings.json");
338
+ if (existsSync(p)) {
339
+ try {
340
+ const data = JSON.parse(readFileSync(p, "utf-8"));
341
+ if (data?.model?.apiKey)
342
+ return true;
343
+ if (Array.isArray(data?.models) && data.models.some((m) => m?.apiKey))
344
+ return true;
345
+ if (Array.isArray(data?.providers) && data.providers.some((p) => p?.apiKey))
346
+ return true;
347
+ }
348
+ catch { /* ignore */ }
349
+ }
350
+ return false;
351
+ }
352
+ // ─── Model pool helpers ───────────────────────────────────────────
353
+ /** Known max output tokens for common models. */
354
+ const KNOWN_MAX_OUTPUT = {
355
+ "anthropic/claude-opus-4.7": 32000,
356
+ "anthropic/claude-opus-4-7": 32000,
357
+ "claude-opus-4-7": 32000,
358
+ "anthropic/claude-sonnet-4.6": 16000,
359
+ "anthropic/claude-sonnet-4-6": 16000,
360
+ "claude-sonnet-4-6": 16000,
361
+ "anthropic/claude-haiku-4.5": 8192,
362
+ "anthropic/claude-haiku-4-5": 8192,
363
+ "claude-haiku-4-5": 8192,
364
+ "openai/gpt-5": 32000,
365
+ "openai/gpt-5-mini": 32000,
366
+ "openai/gpt-5-nano": 16000,
367
+ "gpt-5": 32000,
368
+ "gpt-5-mini": 32000,
369
+ "gpt-5-nano": 16000,
370
+ "openai/gpt-4o": 16384,
371
+ "gpt-4o": 16384,
372
+ "openai/o4-mini": 100000,
373
+ "o4-mini": 100000,
374
+ "openai/o3": 100000,
375
+ "o3": 100000,
376
+ "google/gemini-2.5-pro": 65536,
377
+ "google/gemini-2.5-flash": 65536,
378
+ "gemini-2.5-pro": 65536,
379
+ "gemini-2.5-flash": 65536,
380
+ "gemini-2.0-flash": 8192,
381
+ "deepseek/deepseek-v3.2": 8192,
382
+ "deepseek/deepseek-r1": 8192,
383
+ "deepseek-v4-flash": 8192,
384
+ "deepseek-v4-pro": 65536,
385
+ "deepseek-chat": 8192,
386
+ "qwen/qwen3-coder": 16384,
387
+ "meta-llama/llama-4-maverick": 32000,
388
+ };
389
+ /**
390
+ * Known context window sizes for direct-provider models (not routed through OpenRouter).
391
+ * These are the models whose IDs don't include a "vendor/" prefix.
392
+ */
393
+ const KNOWN_CONTEXT_WINDOWS = {
394
+ "deepseek-v4-pro": 1_000_000,
395
+ "deepseek-v4-flash": 1_000_000,
396
+ "deepseek-chat": 1_000_000,
397
+ "deepseek/deepseek-chat": 1_000_000,
398
+ "deepseek/deepseek-v4-pro": 1_000_000,
399
+ "deepseek/deepseek-v4-flash": 1_000_000,
400
+ };
401
+ /**
402
+ * Resolve a model's max-output-token budget. Lookup order:
403
+ * 1. KNOWN_MAX_OUTPUT (covers direct providers like Anthropic/DeepSeek
404
+ * whose IDs aren't in the OpenRouter snapshot)
405
+ * 2. OpenRouter snapshot (covers `vendor/model` style IDs)
406
+ * 3. undefined — caller falls back to its own default
407
+ *
408
+ * Returns undefined (not 0) when nothing is known, so callers can use
409
+ * `?? defaultValue` semantics.
410
+ */
411
+ export function resolveMaxOutput(model) {
412
+ if (KNOWN_MAX_OUTPUT[model])
413
+ return KNOWN_MAX_OUTPUT[model];
414
+ if (model.includes("/")) {
415
+ const hit = getOpenRouterModels().find((m) => m.id === model);
416
+ if (hit && hit.maxOutputTokens > 0)
417
+ return hit.maxOutputTokens;
418
+ }
419
+ return undefined;
420
+ }
421
+ /**
422
+ * Resolve a model's context window size. Lookup order:
423
+ * 1. KNOWN_CONTEXT_WINDOWS (covers direct providers like DeepSeek)
424
+ * 2. OpenRouter snapshot (covers `vendor/model` style IDs)
425
+ * 3. undefined — unknown
426
+ */
427
+ export function resolveContextWindow(model) {
428
+ if (KNOWN_CONTEXT_WINDOWS[model])
429
+ return KNOWN_CONTEXT_WINDOWS[model];
430
+ if (model.includes("/")) {
431
+ const hit = getOpenRouterModels().find((m) => m.id === model);
432
+ if (hit && hit.contextLength > 0)
433
+ return hit.contextLength;
434
+ }
435
+ return undefined;
436
+ }
437
+ /**
438
+ * Derive a pool key in `provider-model` form. Single source of truth for
439
+ * model alias generation — replaces the old modelKey() function which
440
+ * folded same-family models to one key (e.g. v4-flash and v4-pro both
441
+ * collapsed to "deepseek"), causing the pool to silently shadow entries.
442
+ *
443
+ * ("deepseek", "deepseek-v4-pro") → "deepseek-v4-pro"
444
+ * ("openai", "openai/gpt-5") → "openai-gpt-5"
445
+ * ("anthropic","claude-opus-4-7") → "anthropic-claude-opus-4-7"
446
+ *
447
+ * If the model id already starts with `<provider>-` (e.g. "deepseek-v4-pro"
448
+ * under provider "deepseek"), the prefix isn't duplicated.
449
+ *
450
+ * `used` is a set of already-taken keys; collisions are resolved with a
451
+ * `-2`, `-3`, ... suffix.
452
+ */
453
+ export function deriveModelPoolKey(providerKind, modelId, used = []) {
454
+ const slash = modelId.lastIndexOf("/");
455
+ const base = slash >= 0 ? modelId.slice(slash + 1) : modelId;
456
+ const prefix = providerKind.toLowerCase();
457
+ const candidate = base.toLowerCase().startsWith(`${prefix}-`) ? base : `${prefix}-${base}`;
458
+ const set = new Set(used);
459
+ if (!set.has(candidate))
460
+ return candidate;
461
+ for (let i = 2;; i++) {
462
+ const k = `${candidate}-${i}`;
463
+ if (!set.has(k))
464
+ return k;
465
+ }
466
+ }
467
+ /**
468
+ * Build model pool entries from a provider's model list.
469
+ */
470
+ export function buildModelPool(provider, apiKey) {
471
+ const models = resolveProviderModels(provider);
472
+ const used = [];
473
+ return models.map((m) => {
474
+ const key = deriveModelPoolKey(provider.id, m, used);
475
+ used.push(key);
476
+ return {
477
+ key,
478
+ label: modelDisplayName(m),
479
+ provider: provider.provider,
480
+ model: m,
481
+ baseUrl: provider.baseUrl,
482
+ apiKey,
483
+ maxOutputTokens: resolveMaxOutput(m),
484
+ maxContextTokens: resolveContextWindow(m),
485
+ };
486
+ });
487
+ }
488
+ // ─── Helpers ───────────────────────────────────────────────────────
489
+ export function modelDisplayName(model) {
490
+ const slash = model.lastIndexOf("/");
491
+ const base = slash >= 0 ? model.slice(slash + 1) : model;
492
+ const parts = base.split("-");
493
+ if (parts[0] === "claude") {
494
+ const variant = parts[1] ?? "";
495
+ return `Claude ${variant.charAt(0).toUpperCase() + variant.slice(1)}`;
496
+ }
497
+ if (base.startsWith("gpt-"))
498
+ return `GPT-${parts.slice(1).join("-")}`;
499
+ if (base.startsWith("gemini-"))
500
+ return `Gemini ${parts.slice(1).join("-")}`;
501
+ return base.charAt(0).toUpperCase() + base.slice(1);
502
+ }
503
+ export function saveSettings(result, providerDef, poolModels) {
504
+ const dir = join(homedir(), ".code-shell");
505
+ const file = join(dir, "settings.json");
506
+ mkdirSync(dir, { recursive: true });
507
+ let existing = {};
508
+ if (existsSync(file)) {
509
+ try {
510
+ existing = JSON.parse(readFileSync(file, "utf-8"));
511
+ }
512
+ catch { }
513
+ }
514
+ const updated = {
515
+ ...existing,
516
+ model: {
517
+ ...(typeof existing.model === "object" ? existing.model : {}),
518
+ provider: result.provider,
519
+ name: result.model,
520
+ apiKey: result.apiKey,
521
+ baseUrl: result.baseUrl,
522
+ },
523
+ };
524
+ // Merge model pool: keep entries from other providers (matched by baseUrl)
525
+ // and replace just the current provider's slice. A naive overwrite would
526
+ // wipe out every other provider's models every time the wizard runs.
527
+ if (providerDef && poolModels && poolModels.length > 0) {
528
+ const newEntries = buildModelPool(providerDef, result.apiKey).filter((e) => new Set(poolModels).has(e.model));
529
+ const existingModels = Array.isArray(existing.models)
530
+ ? existing.models
531
+ : [];
532
+ const otherProvider = existingModels.filter((e) => e?.baseUrl !== providerDef.baseUrl);
533
+ updated.models = [...otherProvider, ...newEntries];
534
+ }
535
+ writeFileSync(file, JSON.stringify(updated, null, 2) + "\n", "utf-8");
536
+ }
537
+ /**
538
+ * Append-only persistence for the new ProviderModelFlow-based onboarding.
539
+ *
540
+ * Writes the new shape:
541
+ * - settings.activeKey — primary source of truth for active model
542
+ * - settings.models[] — self-describing entries (key, provider,
543
+ * model, baseUrl, apiKey, maxOutput, maxContext)
544
+ * - settings.providers[] — credential source for the wizard
545
+ * - settings.model.* — legacy mirror of the active entry, kept in
546
+ * sync so legacy boot paths (cli/main.ts,
547
+ * repl.ts, run.ts) keep working without
548
+ * each having to learn about activeKey
549
+ *
550
+ * Append-only: never removes existing entries. To start over use /logout.
551
+ * Writes atomically via tmp+rename.
552
+ */
553
+ export function appendOnboardingResult(opts) {
554
+ const dir = join(homedir(), ".code-shell");
555
+ const file = join(dir, "settings.json");
556
+ mkdirSync(dir, { recursive: true });
557
+ let existing = {};
558
+ if (existsSync(file)) {
559
+ try {
560
+ existing = JSON.parse(readFileSync(file, "utf-8"));
561
+ }
562
+ catch {
563
+ /* ignore — corrupt file is replaced */
564
+ }
565
+ }
566
+ // Append provider (skip if key already present).
567
+ const existingProviders = Array.isArray(existing.providers)
568
+ ? existing.providers
569
+ : [];
570
+ let providersOut = existingProviders;
571
+ if (opts.addedProvider) {
572
+ const has = existingProviders.some((p) => p?.key === opts.addedProvider.key);
573
+ if (!has)
574
+ providersOut = [...existingProviders, opts.addedProvider];
575
+ }
576
+ // Append models (skip entries whose key already exists — the wizard
577
+ // already derives unique keys via deriveModelPoolKey, so a collision
578
+ // means the user re-added the exact same alias and we leave the older
579
+ // entry alone rather than silently overwriting credentials).
580
+ const existingModels = Array.isArray(existing.models)
581
+ ? existing.models
582
+ : [];
583
+ const existingKeys = new Set(existingModels.map((m) => m?.key));
584
+ const modelsToAppend = opts.addedModels.filter((m) => !existingKeys.has(m.key));
585
+ const updated = {
586
+ ...existing,
587
+ activeKey: opts.activeKey,
588
+ model: {
589
+ ...(typeof existing.model === "object" && existing.model ? existing.model : {}),
590
+ provider: opts.activeMirror.provider,
591
+ name: opts.activeMirror.model,
592
+ apiKey: opts.activeMirror.apiKey,
593
+ baseUrl: opts.activeMirror.baseUrl,
594
+ },
595
+ providers: providersOut,
596
+ models: [...existingModels, ...modelsToAppend],
597
+ };
598
+ // Atomic write: tmp file in the same dir, then rename (atomic on POSIX).
599
+ const tmp = `${file}.${process.pid}.tmp`;
600
+ writeFileSync(tmp, JSON.stringify(updated, null, 2) + "\n", "utf-8");
601
+ try {
602
+ renameSync(tmp, file);
603
+ }
604
+ catch {
605
+ // Fallback: best-effort direct write if rename fails (e.g. cross-device).
606
+ writeFileSync(file, JSON.stringify(updated, null, 2) + "\n", "utf-8");
607
+ }
608
+ }
609
+ // saveArenaSettings removed — replaced by saveArenaSettingsByKeys
610
+ export function saveArenaSettingsByKeys(keys) {
611
+ const dir = join(homedir(), ".code-shell");
612
+ const file = join(dir, "settings.json");
613
+ let existing = {};
614
+ if (existsSync(file)) {
615
+ try {
616
+ existing = JSON.parse(readFileSync(file, "utf-8"));
617
+ }
618
+ catch { }
619
+ }
620
+ const updated = {
621
+ ...existing,
622
+ arena: { participants: keys },
623
+ };
624
+ writeFileSync(file, JSON.stringify(updated, null, 2) + "\n", "utf-8");
625
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Minimal `git` subprocess wrappers used by the plugin marketplace. Each
3
+ * function returns a discriminated union so callers can produce useful
4
+ * error messages without try/catching. Mirrors Claude Code's
5
+ * utils/plugins/marketplaceManager.ts:loadAndCacheMarketplace at the
6
+ * subset we need for the MVP.
7
+ *
8
+ * Subprocess lifecycle (spawn, timeout cascade, IO drain, byte cap) is
9
+ * centralized in {@link safeSpawn}; gitOps only owns the error-shape
10
+ * mapping into GitResult.
11
+ *
12
+ * Trust: gitOps is invoked from marketplace install/update actions that the
13
+ * user initiates by typing `/plugin install ...` (or the equivalent). It is
14
+ * NOT exposed to the LLM via tool calls, so it does not need permission
15
+ * classification. See docs/architecture/17 for the trust framing.
16
+ */
17
+ export type GitResult = {
18
+ ok: true;
19
+ stdout: string;
20
+ } | {
21
+ ok: false;
22
+ error: string;
23
+ };
24
+ export declare function gitClone(url: string, destDir: string, options?: {
25
+ ref?: string;
26
+ }): Promise<GitResult>;
27
+ export declare function gitRevParseHead(repoDir: string): Promise<GitResult>;
28
+ export declare function gitFetchAndReset(repoDir: string, ref?: string): Promise<GitResult>;
29
+ /**
30
+ * Github source helper: convert "owner/repo" to an https clone URL.
31
+ */
32
+ export declare function githubRepoToCloneUrl(repo: string): string;