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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/README.md +13 -10
  2. package/dist/agent/agent-definition-registry.d.ts +3 -0
  3. package/dist/agent/agent-definition-registry.js +3 -1
  4. package/dist/agent/agent-definition.d.ts +15 -0
  5. package/dist/agent/agent-definition.js +27 -3
  6. package/dist/arena/context/context-tools.js +47 -4
  7. package/dist/arena/ledger.js +9 -1
  8. package/dist/arena/strategies/utils.d.ts +1 -4
  9. package/dist/arena/strategies/utils.js +7 -84
  10. package/dist/automation/cron-expr.d.ts +10 -0
  11. package/dist/automation/cron-expr.js +23 -5
  12. package/dist/automation/runner.d.ts +21 -4
  13. package/dist/automation/runner.js +48 -12
  14. package/dist/automation/scheduler.d.ts +38 -0
  15. package/dist/automation/scheduler.js +89 -12
  16. package/dist/automation/store.js +5 -2
  17. package/dist/capability-control/disabled-lists.d.ts +25 -0
  18. package/dist/capability-control/disabled-lists.js +57 -0
  19. package/dist/capability-control/overlay.d.ts +15 -0
  20. package/dist/capability-control/overlay.js +27 -0
  21. package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
  22. package/dist/cc-orchestrator/agent-adapter.js +133 -0
  23. package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
  24. package/dist/cc-orchestrator/cc-capability.js +53 -0
  25. package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
  26. package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
  27. package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
  28. package/dist/cc-orchestrator/codex-session-history.js +187 -0
  29. package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
  30. package/dist/cc-orchestrator/external-agent-changes.js +214 -0
  31. package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
  32. package/dist/cc-orchestrator/external-agent-driver.js +69 -0
  33. package/dist/cc-orchestrator/index.d.ts +8 -0
  34. package/dist/cc-orchestrator/index.js +8 -0
  35. package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
  36. package/dist/cc-orchestrator/relevance-judge.js +29 -0
  37. package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
  38. package/dist/cc-orchestrator/session-discovery.js +125 -0
  39. package/dist/cc-orchestrator/session-history.d.ts +19 -0
  40. package/dist/cc-orchestrator/session-history.js +67 -0
  41. package/dist/cli/agent-server-stdio.d.ts +15 -1
  42. package/dist/cli/agent-server-stdio.js +115 -17
  43. package/dist/cli/agent-server-tcp.js +40 -26
  44. package/dist/context/compaction.d.ts +56 -0
  45. package/dist/context/compaction.js +186 -0
  46. package/dist/context/manager.js +25 -4
  47. package/dist/cost-tracker.js +5 -61
  48. package/dist/credentials/cipher.d.ts +49 -0
  49. package/dist/credentials/cipher.js +45 -0
  50. package/dist/credentials/cookie-jar.d.ts +24 -0
  51. package/dist/credentials/cookie-jar.js +40 -0
  52. package/dist/credentials/index.d.ts +7 -0
  53. package/dist/credentials/index.js +5 -0
  54. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  55. package/dist/credentials/inject-credential-tool.js +130 -0
  56. package/dist/credentials/store.d.ts +72 -0
  57. package/dist/credentials/store.js +184 -0
  58. package/dist/credentials/types.d.ts +56 -0
  59. package/dist/credentials/use-credential-tool.d.ts +29 -0
  60. package/dist/credentials/use-credential-tool.js +205 -0
  61. package/dist/credentials/use-gate.d.ts +56 -0
  62. package/dist/credentials/use-gate.js +52 -0
  63. package/dist/data/model-metadata.d.ts +77 -0
  64. package/dist/data/model-metadata.js +56 -0
  65. package/dist/data/model-metadata.json +216 -0
  66. package/dist/data/openrouter-models.d.ts +18 -7
  67. package/dist/data/openrouter-models.js +35 -8
  68. package/dist/engine/aux-key.d.ts +10 -0
  69. package/dist/engine/aux-key.js +11 -0
  70. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  71. package/dist/engine/dynamic-tool-defs.js +36 -0
  72. package/dist/engine/engine.d.ts +267 -138
  73. package/dist/engine/engine.js +957 -191
  74. package/dist/engine/friendly-error.d.ts +18 -0
  75. package/dist/engine/friendly-error.js +63 -0
  76. package/dist/engine/goal.d.ts +145 -0
  77. package/dist/engine/goal.js +144 -0
  78. package/dist/engine/image-policy.d.ts +13 -0
  79. package/dist/engine/image-policy.js +24 -0
  80. package/dist/engine/model-connections-pool.d.ts +17 -0
  81. package/dist/engine/model-connections-pool.js +66 -0
  82. package/dist/engine/model-facade.d.ts +10 -0
  83. package/dist/engine/model-facade.js +25 -0
  84. package/dist/engine/patch-orphaned-tools.js +3 -0
  85. package/dist/engine/resolve-llm-config.d.ts +16 -0
  86. package/dist/engine/resolve-llm-config.js +44 -0
  87. package/dist/engine/runtime.js +2 -1
  88. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  89. package/dist/engine/sandbox-cache-key.js +9 -0
  90. package/dist/engine/sandbox-config.d.ts +31 -0
  91. package/dist/engine/sandbox-config.js +38 -0
  92. package/dist/engine/session-usage.d.ts +19 -0
  93. package/dist/engine/session-usage.js +25 -0
  94. package/dist/engine/steer-queue.d.ts +32 -0
  95. package/dist/engine/steer-queue.js +26 -0
  96. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  97. package/dist/engine/streaming-tool-queue.js +50 -10
  98. package/dist/engine/turn-loop.d.ts +67 -3
  99. package/dist/engine/turn-loop.js +292 -41
  100. package/dist/engine/types.d.ts +175 -0
  101. package/dist/engine/types.js +13 -0
  102. package/dist/external-agents/config.d.ts +2 -0
  103. package/dist/external-agents/config.js +15 -0
  104. package/dist/external-agents/types.d.ts +31 -0
  105. package/dist/external-agents/types.js +1 -0
  106. package/dist/git/utils.js +11 -6
  107. package/dist/git/worktree.d.ts +48 -0
  108. package/dist/git/worktree.js +86 -10
  109. package/dist/hooks/goal-stop-hook.d.ts +28 -0
  110. package/dist/hooks/goal-stop-hook.js +186 -9
  111. package/dist/hooks/registry.d.ts +8 -0
  112. package/dist/hooks/registry.js +19 -0
  113. package/dist/hooks/shell-runner.js +10 -21
  114. package/dist/index.d.ts +49 -6
  115. package/dist/index.js +60 -4
  116. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  117. package/dist/llm/capabilities/param-specs.js +62 -0
  118. package/dist/llm/capabilities/rules.js +4 -0
  119. package/dist/llm/capabilities/types.d.ts +10 -0
  120. package/dist/llm/client-base.d.ts +28 -1
  121. package/dist/llm/client-base.js +119 -13
  122. package/dist/llm/model-cache.js +4 -2
  123. package/dist/llm/model-pool.d.ts +14 -0
  124. package/dist/llm/model-pool.js +13 -0
  125. package/dist/llm/provider-auth.d.ts +41 -0
  126. package/dist/llm/provider-auth.js +76 -0
  127. package/dist/llm/provider-catalog.d.ts +4 -0
  128. package/dist/llm/providers/anthropic.js +64 -14
  129. package/dist/llm/providers/openai.d.ts +36 -0
  130. package/dist/llm/providers/openai.js +257 -51
  131. package/dist/llm/reasoning-setting.d.ts +3 -3
  132. package/dist/llm/reasoning-setting.js +9 -1
  133. package/dist/llm/stream-watchdog.js +5 -1
  134. package/dist/llm/token-counter.js +9 -2
  135. package/dist/llm/types.d.ts +4 -0
  136. package/dist/logging/sanitize-messages.js +22 -0
  137. package/dist/lsp/manager.d.ts +1 -1
  138. package/dist/lsp/manager.js +40 -10
  139. package/dist/model-catalog/builtin.d.ts +12 -0
  140. package/dist/model-catalog/builtin.js +407 -0
  141. package/dist/model-catalog/gen-connections.d.ts +20 -0
  142. package/dist/model-catalog/gen-connections.js +28 -0
  143. package/dist/model-catalog/index.d.ts +41 -0
  144. package/dist/model-catalog/index.js +90 -0
  145. package/dist/model-catalog/params.d.ts +20 -0
  146. package/dist/model-catalog/params.js +45 -0
  147. package/dist/model-catalog/resolve.d.ts +48 -0
  148. package/dist/model-catalog/resolve.js +33 -0
  149. package/dist/model-catalog/save-entry.d.ts +32 -0
  150. package/dist/model-catalog/save-entry.js +104 -0
  151. package/dist/model-catalog/types.d.ts +561 -0
  152. package/dist/model-catalog/types.js +93 -0
  153. package/dist/model-catalog/upsert.d.ts +9 -0
  154. package/dist/model-catalog/upsert.js +8 -0
  155. package/dist/onboarding.d.ts +12 -82
  156. package/dist/onboarding.js +61 -326
  157. package/dist/plugins/gitOps.d.ts +19 -0
  158. package/dist/plugins/gitOps.js +73 -4
  159. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  160. package/dist/plugins/installer/checkUpdate.js +32 -0
  161. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  162. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  163. package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
  164. package/dist/plugins/installer/codex/convertMcp.js +45 -5
  165. package/dist/plugins/installer/install.js +25 -1
  166. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  167. package/dist/plugins/installer/installFromArchive.js +134 -0
  168. package/dist/plugins/installer/installFromSource.js +8 -2
  169. package/dist/plugins/installer/loadPluginAgents.js +6 -2
  170. package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
  171. package/dist/plugins/installer/loadPluginMcp.js +35 -2
  172. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  173. package/dist/plugins/installer/pruneDisabled.js +73 -0
  174. package/dist/plugins/installer/types.d.ts +5 -2
  175. package/dist/plugins/installer/types.js +1 -0
  176. package/dist/plugins/installer/uninstall.js +4 -0
  177. package/dist/plugins/installer/unzip.d.ts +14 -0
  178. package/dist/plugins/installer/unzip.js +82 -0
  179. package/dist/plugins/installer/update.d.ts +14 -0
  180. package/dist/plugins/installer/update.js +53 -21
  181. package/dist/plugins/loadPluginHooks.d.ts +47 -1
  182. package/dist/plugins/loadPluginHooks.js +73 -1
  183. package/dist/plugins/marketplaceManager.d.ts +7 -0
  184. package/dist/plugins/marketplaceManager.js +20 -0
  185. package/dist/plugins/pluginCommandHook.js +4 -18
  186. package/dist/plugins/pluginContent.d.ts +30 -0
  187. package/dist/plugins/pluginContent.js +83 -0
  188. package/dist/plugins/pluginInstaller.d.ts +13 -0
  189. package/dist/plugins/pluginInstaller.js +42 -8
  190. package/dist/plugins/schemas.js +1 -0
  191. package/dist/plugins/types.d.ts +6 -0
  192. package/dist/preset/index.d.ts +7 -1
  193. package/dist/preset/index.js +96 -6
  194. package/dist/product/types.d.ts +1 -1
  195. package/dist/prompt/composer.d.ts +27 -0
  196. package/dist/prompt/composer.js +67 -21
  197. package/dist/prompt/instruction-scanner.js +5 -3
  198. package/dist/prompt/section-loader.js +1 -0
  199. package/dist/prompt/sections/base.md +1 -0
  200. package/dist/prompt/sections/browser.md +10 -0
  201. package/dist/prompt/sections/coding.md +4 -0
  202. package/dist/protocol/chat-session-manager.d.ts +8 -2
  203. package/dist/protocol/chat-session-manager.js +36 -0
  204. package/dist/protocol/chat-session.d.ts +65 -0
  205. package/dist/protocol/chat-session.js +94 -2
  206. package/dist/protocol/client.d.ts +27 -0
  207. package/dist/protocol/client.js +38 -0
  208. package/dist/protocol/server.d.ts +112 -0
  209. package/dist/protocol/server.js +586 -16
  210. package/dist/protocol/transport.js +3 -2
  211. package/dist/protocol/types.d.ts +46 -0
  212. package/dist/protocol/types.js +16 -0
  213. package/dist/quota/credentials.d.ts +3 -0
  214. package/dist/quota/credentials.js +80 -0
  215. package/dist/quota/index.d.ts +36 -0
  216. package/dist/quota/index.js +155 -0
  217. package/dist/quota/types.d.ts +48 -0
  218. package/dist/quota/types.js +13 -0
  219. package/dist/review/review-prompt.d.ts +28 -0
  220. package/dist/review/review-prompt.js +81 -0
  221. package/dist/run/FileRunStore.js +8 -3
  222. package/dist/run/RunApprovalBackend.js +25 -5
  223. package/dist/run/RunManager.d.ts +12 -0
  224. package/dist/run/RunManager.js +35 -0
  225. package/dist/run/factory.d.ts +1 -1
  226. package/dist/runtime/background-shell.d.ts +139 -0
  227. package/dist/runtime/background-shell.js +495 -0
  228. package/dist/runtime/output-clean.d.ts +24 -0
  229. package/dist/runtime/output-clean.js +41 -0
  230. package/dist/runtime/ring-file.d.ts +64 -0
  231. package/dist/runtime/ring-file.js +174 -0
  232. package/dist/runtime/safe-spawn.js +15 -34
  233. package/dist/runtime/spawn-common.d.ts +148 -0
  234. package/dist/runtime/spawn-common.js +303 -0
  235. package/dist/runtime/truncate-output.d.ts +22 -0
  236. package/dist/runtime/truncate-output.js +49 -0
  237. package/dist/runtime/utf8-cut.d.ts +11 -0
  238. package/dist/runtime/utf8-cut.js +23 -0
  239. package/dist/services/auto-dream.d.ts +4 -0
  240. package/dist/services/auto-dream.js +26 -26
  241. package/dist/services/diagnostics.d.ts +1 -2
  242. package/dist/services/diagnostics.js +12 -7
  243. package/dist/services/extract-memories.d.ts +14 -1
  244. package/dist/services/extract-memories.js +45 -6
  245. package/dist/services/memory-orchestrator.d.ts +21 -0
  246. package/dist/services/memory-orchestrator.js +125 -50
  247. package/dist/services/session-memory.js +24 -12
  248. package/dist/session/file-history.d.ts +124 -1
  249. package/dist/session/file-history.js +222 -6
  250. package/dist/session/memory.d.ts +116 -2
  251. package/dist/session/memory.js +250 -28
  252. package/dist/session/session-manager.d.ts +40 -0
  253. package/dist/session/session-manager.js +113 -3
  254. package/dist/session/simple-diff.d.ts +23 -0
  255. package/dist/session/simple-diff.js +84 -0
  256. package/dist/session/transcript.d.ts +25 -1
  257. package/dist/session/transcript.js +35 -2
  258. package/dist/session/undo-target.d.ts +67 -0
  259. package/dist/session/undo-target.js +144 -0
  260. package/dist/settings/disk-defaults.d.ts +9 -2
  261. package/dist/settings/disk-defaults.js +11 -2
  262. package/dist/settings/feature-flags.d.ts +64 -0
  263. package/dist/settings/feature-flags.js +61 -0
  264. package/dist/settings/manager.d.ts +68 -1
  265. package/dist/settings/manager.js +266 -29
  266. package/dist/settings/migrate-config.d.ts +45 -0
  267. package/dist/settings/migrate-config.js +125 -0
  268. package/dist/settings/schema-export.d.ts +25 -0
  269. package/dist/settings/schema-export.js +38 -0
  270. package/dist/settings/schema.d.ts +1186 -771
  271. package/dist/settings/schema.js +268 -97
  272. package/dist/skills/scanner.d.ts +9 -0
  273. package/dist/skills/scanner.js +30 -2
  274. package/dist/stt/resolve-transcribe.d.ts +31 -0
  275. package/dist/stt/resolve-transcribe.js +108 -0
  276. package/dist/stt/transcribe.d.ts +51 -0
  277. package/dist/stt/transcribe.js +65 -0
  278. package/dist/tool-system/browser-bridge.d.ts +226 -0
  279. package/dist/tool-system/browser-bridge.js +163 -0
  280. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  281. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  282. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  283. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  284. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  285. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  286. package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
  287. package/dist/tool-system/builtin/agent-registry.js +8 -0
  288. package/dist/tool-system/builtin/agent.d.ts +21 -1
  289. package/dist/tool-system/builtin/agent.js +489 -42
  290. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  291. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  292. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  293. package/dist/tool-system/builtin/apply-patch/index.js +0 -15
  294. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  295. package/dist/tool-system/builtin/background-jobs.js +124 -0
  296. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  297. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  298. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  299. package/dist/tool-system/builtin/background-work.js +86 -0
  300. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  301. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  302. package/dist/tool-system/builtin/bash.d.ts +5 -2
  303. package/dist/tool-system/builtin/bash.js +98 -62
  304. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  305. package/dist/tool-system/builtin/browser-tools.js +312 -0
  306. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  307. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  308. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  309. package/dist/tool-system/builtin/check-quota.js +34 -0
  310. package/dist/tool-system/builtin/config.js +7 -0
  311. package/dist/tool-system/builtin/cron.d.ts +7 -0
  312. package/dist/tool-system/builtin/cron.js +55 -3
  313. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  314. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  315. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  316. package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
  317. package/dist/tool-system/builtin/edit.js +20 -16
  318. package/dist/tool-system/builtin/eol.d.ts +29 -0
  319. package/dist/tool-system/builtin/eol.js +37 -0
  320. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  321. package/dist/tool-system/builtin/file-cache.js +8 -0
  322. package/dist/tool-system/builtin/generate-image.d.ts +35 -0
  323. package/dist/tool-system/builtin/generate-image.js +278 -50
  324. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  325. package/dist/tool-system/builtin/generate-video.js +361 -0
  326. package/dist/tool-system/builtin/glob.js +0 -7
  327. package/dist/tool-system/builtin/grep.js +6 -8
  328. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  329. package/dist/tool-system/builtin/image-providers.js +190 -0
  330. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  331. package/dist/tool-system/builtin/image-uploader.js +74 -0
  332. package/dist/tool-system/builtin/index.d.ts +7 -1
  333. package/dist/tool-system/builtin/index.js +249 -25
  334. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  335. package/dist/tool-system/builtin/memory.js +45 -7
  336. package/dist/tool-system/builtin/notebook-edit.js +0 -7
  337. package/dist/tool-system/builtin/powershell.js +4 -1
  338. package/dist/tool-system/builtin/read.js +10 -10
  339. package/dist/tool-system/builtin/repl.js +4 -1
  340. package/dist/tool-system/builtin/skill.js +9 -0
  341. package/dist/tool-system/builtin/sleep.js +3 -2
  342. package/dist/tool-system/builtin/tool-search.js +25 -7
  343. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  344. package/dist/tool-system/builtin/video-providers.js +235 -0
  345. package/dist/tool-system/builtin/web-fetch.js +12 -2
  346. package/dist/tool-system/builtin/web-search.js +21 -7
  347. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  348. package/dist/tool-system/builtin/worktree.js +31 -4
  349. package/dist/tool-system/builtin/write.js +0 -6
  350. package/dist/tool-system/context.d.ts +154 -6
  351. package/dist/tool-system/executor.d.ts +3 -1
  352. package/dist/tool-system/executor.js +172 -88
  353. package/dist/tool-system/investigation-guard.js +1 -1
  354. package/dist/tool-system/mcp-manager.d.ts +42 -4
  355. package/dist/tool-system/mcp-manager.js +186 -20
  356. package/dist/tool-system/path-policy.d.ts +5 -0
  357. package/dist/tool-system/path-policy.js +307 -8
  358. package/dist/tool-system/permission.d.ts +36 -1
  359. package/dist/tool-system/permission.js +281 -69
  360. package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
  361. package/dist/tool-system/plan-mode-allowlist.js +24 -2
  362. package/dist/tool-system/registry.d.ts +1 -0
  363. package/dist/tool-system/registry.js +16 -2
  364. package/dist/tool-system/sandbox/index.d.ts +8 -0
  365. package/dist/tool-system/sandbox/index.js +7 -2
  366. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  367. package/dist/tool-system/validate-tool-metadata.js +63 -0
  368. package/dist/types.d.ts +217 -6
  369. package/dist/updater.js +20 -9
  370. package/dist/utils/envUtils.d.ts +0 -9
  371. package/dist/utils/envUtils.js +3 -28
  372. package/dist/utils/exec.d.ts +40 -0
  373. package/dist/utils/exec.js +144 -0
  374. package/dist/utils/json.d.ts +12 -0
  375. package/dist/utils/json.js +92 -0
  376. package/dist/utils/theme.d.ts +1 -1
  377. package/dist/utils/theme.js +1 -1
  378. package/dist/utils/toolDisplay.js +0 -1
  379. package/package.json +13 -7
  380. package/dist/agent/coordinator.d.ts +0 -49
  381. package/dist/agent/coordinator.js +0 -77
  382. package/dist/settings/manager.test.js +0 -73
  383. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  384. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  385. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  386. package/dist/tool-system/builtin/send-message.js +0 -47
  387. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -0,0 +1,29 @@
1
+ /**
2
+ * EOL (line-ending) helpers for file-editing tools.
3
+ *
4
+ * Windows files are typically CRLF (`\r\n`); the model emits LF (`\n`). The
5
+ * file tools match the model's strings against file content and write the
6
+ * result back. Without normalization:
7
+ * - an LF `old_string` never matches a CRLF file → "old_string not found";
8
+ * - a successful write that re-joins with LF silently converts a CRLF file
9
+ * to LF, so `git diff` shows the whole file changed (and an .editorconfig
10
+ * /prettier may flip it right back → churn).
11
+ *
12
+ * The contract these helpers enforce:
13
+ * 1. Detect the file's dominant EOL.
14
+ * 2. Compare/replace in LF space (normalize both file content and the
15
+ * model's needle to LF first).
16
+ * 3. Write back in the ORIGINAL EOL so the file's line-ending style is
17
+ * preserved.
18
+ */
19
+ export type Eol = "\r\n" | "\n";
20
+ /**
21
+ * The file's dominant line ending. CRLF if the content contains ANY `\r\n`
22
+ * (Windows editors are all-or-nothing in practice); otherwise LF. Empty/no-
23
+ * newline content defaults to LF.
24
+ */
25
+ export declare function detectEol(content: string): Eol;
26
+ /** Collapse all CRLF (and lone CR) to LF for comparison/replacement. */
27
+ export declare function toLf(s: string): string;
28
+ /** Re-apply an EOL to LF-normalized text. No-op for LF. */
29
+ export declare function applyEol(s: string, eol: Eol): string;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * EOL (line-ending) helpers for file-editing tools.
3
+ *
4
+ * Windows files are typically CRLF (`\r\n`); the model emits LF (`\n`). The
5
+ * file tools match the model's strings against file content and write the
6
+ * result back. Without normalization:
7
+ * - an LF `old_string` never matches a CRLF file → "old_string not found";
8
+ * - a successful write that re-joins with LF silently converts a CRLF file
9
+ * to LF, so `git diff` shows the whole file changed (and an .editorconfig
10
+ * /prettier may flip it right back → churn).
11
+ *
12
+ * The contract these helpers enforce:
13
+ * 1. Detect the file's dominant EOL.
14
+ * 2. Compare/replace in LF space (normalize both file content and the
15
+ * model's needle to LF first).
16
+ * 3. Write back in the ORIGINAL EOL so the file's line-ending style is
17
+ * preserved.
18
+ */
19
+ /**
20
+ * The file's dominant line ending. CRLF if the content contains ANY `\r\n`
21
+ * (Windows editors are all-or-nothing in practice); otherwise LF. Empty/no-
22
+ * newline content defaults to LF.
23
+ */
24
+ export function detectEol(content) {
25
+ return content.includes("\r\n") ? "\r\n" : "\n";
26
+ }
27
+ /** Collapse all CRLF (and lone CR) to LF for comparison/replacement. */
28
+ export function toLf(s) {
29
+ return s.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
30
+ }
31
+ /** Re-apply an EOL to LF-normalized text. No-op for LF. */
32
+ export function applyEol(s, eol) {
33
+ if (eol === "\n")
34
+ return s;
35
+ // s is already LF-normalized by callers; map every LF back to CRLF.
36
+ return s.replace(/\n/g, "\r\n");
37
+ }
@@ -5,6 +5,12 @@ declare class FileStateCache {
5
5
  /** Invalidate a specific path (after Write/Edit). */
6
6
  invalidate(filePath: string): void;
7
7
  clear(): void;
8
+ /**
9
+ * True if a cache entry for `filePath` is currently held. Pure key-presence
10
+ * check — does NOT stat/self-heal like `get()`, so a test can assert a manual
11
+ * `invalidate()` actually removed the key without the mtime path masking it.
12
+ */
13
+ has(filePath: string): boolean;
8
14
  get size(): number;
9
15
  }
10
16
  export declare const fileCache: FileStateCache;
@@ -32,6 +32,14 @@ class FileStateCache {
32
32
  clear() {
33
33
  this.cache.clear();
34
34
  }
35
+ /**
36
+ * True if a cache entry for `filePath` is currently held. Pure key-presence
37
+ * check — does NOT stat/self-heal like `get()`, so a test can assert a manual
38
+ * `invalidate()` actually removed the key without the mtime path masking it.
39
+ */
40
+ has(filePath) {
41
+ return this.cache.has(filePath);
42
+ }
35
43
  get size() {
36
44
  return this.cache.size;
37
45
  }
@@ -20,6 +20,41 @@
20
20
  */
21
21
  import type { ToolDefinition } from "../../types.js";
22
22
  import type { ToolContext } from "../context.js";
23
+ /** A configured imageGen/videoGen instance (subset used here). */
24
+ interface GenInstance {
25
+ id: string;
26
+ kind: string;
27
+ baseUrl: string;
28
+ apiKey?: string;
29
+ defaultModel?: string;
30
+ catalogId?: string;
31
+ apiKeyRef?: string;
32
+ }
33
+ /**
34
+ * Effective key for an instance: its own `apiKey`, or — when empty and
35
+ * `apiKeyRef` is set — the key of the referenced instance in the same list
36
+ * (reuse-key feature). Returns undefined when neither yields a key.
37
+ */
38
+ export declare function effectiveApiKey(inst: GenInstance, list: GenInstance[]): string | undefined;
23
39
  export declare const generateImageToolDef: ToolDefinition;
40
+ /**
41
+ * List the configured, usable image providers for a workspace (TODO 7.1) —
42
+ * either `imageGen.providers[]` ids+kinds, or the back-compat LLM-provider
43
+ * kinds. Used to build a dynamic tool description so the model sees which
44
+ * backends are actually available. Returns [] on any read error.
45
+ */
46
+ export declare function listConfiguredImageProviders(cwd?: string): Array<{
47
+ id?: string;
48
+ kind: string;
49
+ catalogId?: string;
50
+ }>;
51
+ /**
52
+ * Build the GenerateImage tool description for a workspace, appending the
53
+ * configured providers so the model knows what's available and which `provider`
54
+ * values are valid (TODO 7.1). Falls back to the static description when none
55
+ * are configured (the guard hides the tool in that case anyway).
56
+ */
57
+ export declare function generateImageToolDefFor(cwd: string): ToolDefinition;
24
58
  export declare function isGenerateImageAvailable(cwd?: string, nowMs?: number): boolean;
25
59
  export declare function generateImageTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
60
+ export {};
@@ -18,18 +18,58 @@
18
18
  *
19
19
  * Uses the native `fetch` (codeshell does not depend on the `openai` SDK).
20
20
  */
21
- import { writeFile, mkdir } from "node:fs/promises";
22
- import { join } from "node:path";
21
+ import { writeFile, mkdir, readFile } from "node:fs/promises";
22
+ import { join, isAbsolute, resolve as resolvePath, basename, extname } from "node:path";
23
+ import { randomBytes } from "node:crypto";
23
24
  import { SettingsManager } from "../../settings/manager.js";
25
+ import { getImageProvider, DEFAULT_IMAGE_MODEL, } from "./image-providers.js";
26
+ import { getMergedCatalog, findCatalogEntry } from "../../model-catalog/index.js";
27
+ import { genInstancesFromConnections } from "../../model-catalog/gen-connections.js";
28
+ /**
29
+ * Effective key for an instance: its own `apiKey`, or — when empty and
30
+ * `apiKeyRef` is set — the key of the referenced instance in the same list
31
+ * (reuse-key feature). Returns undefined when neither yields a key.
32
+ */
33
+ export function effectiveApiKey(inst, list) {
34
+ if (inst.apiKey)
35
+ return inst.apiKey;
36
+ if (inst.apiKeyRef) {
37
+ const ref = list.find((p) => p.id === inst.apiKeyRef);
38
+ if (ref?.apiKey)
39
+ return ref.apiKey;
40
+ }
41
+ return undefined;
42
+ }
43
+ /**
44
+ * Resolve a ResolvedImageProvider from a candidate list whose entries already
45
+ * carry a direct `apiKey` (the unified store dereferences credentials upfront).
46
+ * `prefer` selects by id (explicit → no silent fallback); else `def` then the
47
+ * first usable. Shared by the unified-store path.
48
+ */
49
+ function resolveFromGenList(list, prefer, def) {
50
+ const usable = (p) => !!p.apiKey && getImageProvider(p.kind) !== null;
51
+ const credsOf = (p) => ({ baseUrl: p.baseUrl, apiKey: p.apiKey });
52
+ if (prefer) {
53
+ const chosen = list.find((p) => p.id === prefer);
54
+ if (chosen && usable(chosen))
55
+ return { kind: chosen.kind, creds: credsOf(chosen), defaultModel: chosen.defaultModel };
56
+ return null;
57
+ }
58
+ const preferred = def ? list.find((p) => p.id === def) : undefined;
59
+ const chosen = (preferred && usable(preferred) ? preferred : undefined) ?? list.find(usable);
60
+ return chosen ? { kind: chosen.kind, creds: credsOf(chosen), defaultModel: chosen.defaultModel } : null;
61
+ }
24
62
  const DEFAULT_SIZE = "1024x1024";
25
63
  const DEFAULT_QUALITY = "auto";
26
- const MODEL = "gpt-image-2";
64
+ /** Provider `kind`s that have an image adapter, in resolution preference. */
65
+ const IMAGE_PROVIDER_KINDS = ["openai", "google"];
27
66
  export const generateImageToolDef = {
28
67
  name: "GenerateImage",
29
- description: "Generate an image from a text prompt using the OpenAI Images API (gpt-image-2). " +
30
- "Saves a PNG into the workspace and returns its absolute path; read or reference " +
31
- "that path on later turns. Requires an OpenAI provider (kind: \"openai\") configured " +
32
- "in settings. For raster assets (photos, illustrations, mockups, textures) — not for " +
68
+ description: "Generate an image from a text prompt, or edit/re-imagine existing image(s) by passing " +
69
+ "`referenceImages` (image-to-image). Saves a PNG into the workspace and returns its " +
70
+ "absolute path; read or reference that path on later turns. Defaults to the OpenAI Images " +
71
+ "API (gpt-image-2); requires a matching provider configured in settings. " +
72
+ "For raster assets (photos, illustrations, mockups, textures) — not for " +
33
73
  "SVG/vector icons or anything better built directly in code.",
34
74
  inputSchema: {
35
75
  type: "object",
@@ -48,17 +88,100 @@ export const generateImageToolDef = {
48
88
  enum: ["low", "medium", "high", "auto"],
49
89
  description: "Render quality (default auto). Use low for drafts, high for final assets.",
50
90
  },
91
+ provider: {
92
+ type: "string",
93
+ description: "Image provider to use. With imageGen configured, this is the instance `id` " +
94
+ "(e.g. \"gemini\"); otherwise it's a provider kind (e.g. \"openai\"). " +
95
+ "Defaults to the configured default / first available. Only specify to override.",
96
+ },
97
+ model: {
98
+ type: "string",
99
+ description: "Image model id (e.g. \"gpt-image-2\"). Defaults to the provider's default model. " +
100
+ "Only specify to override.",
101
+ },
102
+ referenceImages: {
103
+ type: "array",
104
+ items: { type: "string" },
105
+ description: "Optional workspace image path(s) to use as visual references (image-to-image / " +
106
+ "edit). When provided, the prompt edits/re-imagines these inputs instead of " +
107
+ "generating from scratch — use it to keep a subject, style, or composition. " +
108
+ "Paths are relative to the workspace (or absolute). PNG/JPEG/WebP, up to 16.",
109
+ },
51
110
  },
52
111
  required: ["prompt"],
53
112
  },
54
113
  };
55
- /** Resolve the OpenAI provider's apiKey + baseUrl from settings, or null. */
56
- function resolveOpenAIProvider(cwd) {
114
+ /**
115
+ * Resolve an image provider from settings (TODO 7.1). Preference order:
116
+ *
117
+ * 1. `imageGen.providers[]` — the canonical, LLM-decoupled config. `prefer`
118
+ * selects an instance by its `id`; otherwise `imageGen.defaultProvider`,
119
+ * else the first entry. Each instance names its own adapter `kind`.
120
+ * 2. Fallback (no `imageGen`): scan LLM `providers[]` for an image-capable
121
+ * `kind` — keeps existing configs working with no migration. Here
122
+ * `prefer` is treated as a kind.
123
+ *
124
+ * Returns null when nothing usable is configured (or the requested one lacks
125
+ * a key / has no adapter).
126
+ */
127
+ function resolveImageProvider(cwd, prefer) {
57
128
  const settings = new SettingsManager(cwd, "full").get();
58
- const provider = settings.providers.find((p) => p.kind === "openai");
59
- if (!provider || !provider.apiKey)
129
+ // 0. Unified store (统一模型接入方案): modelConnections (tag=image) +
130
+ // credentials. Takes precedence over the legacy imageGen.providers[] so the
131
+ // unified connection page drives image generation. Falls through to the
132
+ // legacy paths below when no image connection is configured.
133
+ const conns = settings.modelConnections;
134
+ const creds = settings.credentials;
135
+ if (Array.isArray(conns) && conns.some((c) => c.tag === "image")) {
136
+ const list = genInstancesFromConnections(conns, (Array.isArray(creds) ? creds : []), getMergedCatalog(), "image");
137
+ const def = settings.defaults?.image;
138
+ const resolved = resolveFromGenList(list, prefer, def);
139
+ if (resolved)
140
+ return resolved;
141
+ if (prefer)
142
+ return null; // explicit request not usable → don't silently fall back
143
+ }
144
+ // 1. Canonical imageGen config.
145
+ const imageGen = settings.imageGen;
146
+ if (imageGen && Array.isArray(imageGen.providers) && imageGen.providers.length > 0) {
147
+ const list = imageGen.providers;
148
+ const usable = (p) => !!effectiveApiKey(p, list) && getImageProvider(p.kind) !== null;
149
+ const credsOf = (p) => ({ baseUrl: p.baseUrl, apiKey: effectiveApiKey(p, list) });
150
+ if (prefer) {
151
+ // Explicit request — respect the user's intent. If that exact instance
152
+ // isn't usable (no key / no adapter), DON'T silently use another one.
153
+ const chosen = list.find((p) => p.id === prefer);
154
+ if (chosen && usable(chosen)) {
155
+ return { kind: chosen.kind, creds: credsOf(chosen), defaultModel: chosen.defaultModel };
156
+ }
157
+ return null;
158
+ }
159
+ // No explicit request: prefer defaultProvider, but if it isn't usable
160
+ // (e.g. configured but no key yet) fall back to the first usable entry,
161
+ // rather than erroring. (User-confirmed: default-with-no-key → fall back.)
162
+ const preferred = imageGen.defaultProvider
163
+ ? list.find((p) => p.id === imageGen.defaultProvider)
164
+ : undefined;
165
+ const chosen = (preferred && usable(preferred) ? preferred : undefined) ?? list.find(usable);
166
+ if (chosen) {
167
+ return { kind: chosen.kind, creds: credsOf(chosen), defaultModel: chosen.defaultModel };
168
+ }
60
169
  return null;
61
- return { baseUrl: provider.baseUrl, apiKey: provider.apiKey };
170
+ }
171
+ // 2. Back-compat: resolve from legacy LLM providers[] by kind. The field was
172
+ // dropped from the schema; un-migrated settings.json still carry it via the
173
+ // schema's .passthrough(), so read it through an inline cast.
174
+ const legacyProviders = settings.providers ?? [];
175
+ const kinds = prefer ? [prefer] : [...IMAGE_PROVIDER_KINDS];
176
+ for (const kind of kinds) {
177
+ if (!prefer && !IMAGE_PROVIDER_KINDS.includes(kind))
178
+ continue;
179
+ const provider = legacyProviders.find((p) => p.kind === kind);
180
+ if (provider && provider.apiKey) {
181
+ return { kind, creds: { baseUrl: provider.baseUrl, apiKey: provider.apiKey } };
182
+ }
183
+ }
184
+ return null;
62
185
  }
63
186
  /**
64
187
  * Tool-visibility guard: GenerateImage needs a kind:"openai" provider with a
@@ -73,13 +196,69 @@ function resolveOpenAIProvider(cwd) {
73
196
  */
74
197
  const availCache = new Map();
75
198
  const AVAIL_TTL_MS = 1000;
199
+ /**
200
+ * List the configured, usable image providers for a workspace (TODO 7.1) —
201
+ * either `imageGen.providers[]` ids+kinds, or the back-compat LLM-provider
202
+ * kinds. Used to build a dynamic tool description so the model sees which
203
+ * backends are actually available. Returns [] on any read error.
204
+ */
205
+ export function listConfiguredImageProviders(cwd = process.cwd()) {
206
+ try {
207
+ const settings = new SettingsManager(cwd, "full").get();
208
+ const imageGen = settings.imageGen;
209
+ if (imageGen?.providers?.length) {
210
+ const list = imageGen.providers;
211
+ return list
212
+ .filter((p) => !!effectiveApiKey(p, list) && getImageProvider(p.kind) !== null)
213
+ .map((p) => ({ id: p.id, kind: p.kind, catalogId: p.catalogId }));
214
+ }
215
+ // Legacy LLM providers[] back-compat (field dropped from schema; read via
216
+ // .passthrough() with an inline cast).
217
+ const legacyProviders = settings.providers ?? [];
218
+ return legacyProviders
219
+ .filter((p) => p.apiKey &&
220
+ IMAGE_PROVIDER_KINDS.includes(p.kind))
221
+ .map((p) => ({ kind: p.kind }));
222
+ }
223
+ catch {
224
+ return [];
225
+ }
226
+ }
227
+ /**
228
+ * Build the GenerateImage tool description for a workspace, appending the
229
+ * configured providers so the model knows what's available and which `provider`
230
+ * values are valid (TODO 7.1). Falls back to the static description when none
231
+ * are configured (the guard hides the tool in that case anyway).
232
+ */
233
+ export function generateImageToolDefFor(cwd) {
234
+ const providers = listConfiguredImageProviders(cwd);
235
+ if (providers.length === 0)
236
+ return generateImageToolDef;
237
+ const names = providers.map((p) => p.id ?? p.kind).join(", ");
238
+ // Per-instance params hints from the catalog (paramsDoc) — so the model knows
239
+ // what each configured model accepts (different models differ).
240
+ const catalog = getMergedCatalog();
241
+ const paramLines = providers
242
+ .map((p) => {
243
+ const entry = findCatalogEntry(catalog, p.catalogId, p.kind);
244
+ return entry?.paramsDoc ? ` - ${p.id ?? p.kind}: ${entry.paramsDoc}` : null;
245
+ })
246
+ .filter((x) => x !== null);
247
+ const paramsBlock = paramLines.length ? `\nParams per provider:\n${paramLines.join("\n")}` : "";
248
+ return {
249
+ ...generateImageToolDef,
250
+ description: generateImageToolDef.description +
251
+ ` Configured provider(s): ${names}. Pass \`provider\` to pick one.` +
252
+ paramsBlock,
253
+ };
254
+ }
76
255
  export function isGenerateImageAvailable(cwd = process.cwd(), nowMs = Date.now()) {
77
256
  const hit = availCache.get(cwd);
78
257
  if (hit && nowMs - hit.at < AVAIL_TTL_MS)
79
258
  return hit.value;
80
259
  let value = false;
81
260
  try {
82
- value = resolveOpenAIProvider(cwd) !== null;
261
+ value = resolveImageProvider(cwd) !== null;
83
262
  }
84
263
  catch {
85
264
  value = false;
@@ -87,6 +266,48 @@ export function isGenerateImageAvailable(cwd = process.cwd(), nowMs = Date.now()
87
266
  availCache.set(cwd, { at: nowMs, value });
88
267
  return value;
89
268
  }
269
+ /** Map a file extension to an image MIME type the image APIs accept. */
270
+ const IMAGE_MIME_BY_EXT = {
271
+ ".png": "image/png",
272
+ ".jpg": "image/jpeg",
273
+ ".jpeg": "image/jpeg",
274
+ ".webp": "image/webp",
275
+ ".gif": "image/gif",
276
+ };
277
+ /**
278
+ * Read reference-image paths (workspace-relative or absolute) into decoded
279
+ * {@link InputImage}s for image-to-image. Returns either the loaded images or a
280
+ * user-facing error string (bad path, unreadable, unsupported type, too many).
281
+ */
282
+ async function loadReferenceImages(paths, cwd) {
283
+ if (paths.length > 16) {
284
+ return { ok: false, error: `too many reference images (${paths.length}); max is 16` };
285
+ }
286
+ const images = [];
287
+ for (const p of paths) {
288
+ if (typeof p !== "string" || !p.trim()) {
289
+ return { ok: false, error: "referenceImages entries must be non-empty path strings" };
290
+ }
291
+ const ext = extname(p).toLowerCase();
292
+ const mimeType = IMAGE_MIME_BY_EXT[ext];
293
+ if (!mimeType) {
294
+ return {
295
+ ok: false,
296
+ error: `unsupported reference image type "${ext || "(none)"}" for ${p}; use PNG/JPEG/WebP/GIF`,
297
+ };
298
+ }
299
+ const abs = isAbsolute(p) ? p : resolvePath(cwd, p);
300
+ let bytes;
301
+ try {
302
+ bytes = await readFile(abs);
303
+ }
304
+ catch (err) {
305
+ return { ok: false, error: `could not read reference image ${p}: ${err.message}` };
306
+ }
307
+ images.push({ filename: basename(abs), mimeType, bytes });
308
+ }
309
+ return { ok: true, images };
310
+ }
90
311
  export async function generateImageTool(args, ctx) {
91
312
  const prompt = args.prompt;
92
313
  if (typeof prompt !== "string" || !prompt.trim()) {
@@ -94,51 +315,58 @@ export async function generateImageTool(args, ctx) {
94
315
  }
95
316
  const size = typeof args.size === "string" ? args.size : DEFAULT_SIZE;
96
317
  const quality = typeof args.quality === "string" ? args.quality : DEFAULT_QUALITY;
318
+ const preferKind = typeof args.provider === "string" && args.provider ? args.provider : undefined;
319
+ const overrideModel = typeof args.model === "string" && args.model ? args.model : undefined;
97
320
  const cwd = ctx?.cwd ?? process.cwd();
98
- const provider = resolveOpenAIProvider(cwd);
99
- if (!provider) {
100
- return ('Error: no OpenAI provider available. Configure a provider with kind: "openai" ' +
101
- "(including an apiKey) in your code-shell settings to use GenerateImage.");
102
- }
103
- // Trim a trailing slash so `${baseUrl}/images/generations` doesn't double up.
104
- const baseUrl = provider.baseUrl.replace(/\/+$/, "");
105
- let resp;
106
- try {
107
- resp = await fetch(`${baseUrl}/images/generations`, {
108
- method: "POST",
109
- headers: {
110
- Authorization: `Bearer ${provider.apiKey}`,
111
- "Content-Type": "application/json",
112
- },
113
- body: JSON.stringify({ model: MODEL, prompt, size, quality, n: 1 }),
114
- signal: ctx?.signal,
115
- });
321
+ // Optional reference images → image-to-image. Resolve + decode before the
322
+ // provider call so a bad path fails fast with a clear message.
323
+ let inputImages;
324
+ if (Array.isArray(args.referenceImages) && args.referenceImages.length > 0) {
325
+ const loaded = await loadReferenceImages(args.referenceImages, cwd);
326
+ if (!loaded.ok)
327
+ return `Error: ${loaded.error}`;
328
+ inputImages = loaded.images;
116
329
  }
117
- catch (err) {
118
- return `Error generating image: ${err.message}`;
119
- }
120
- if (!resp.ok) {
121
- const body = (await resp.text().catch(() => "")).slice(0, 500);
122
- return `Error: image API returned ${resp.status}: ${body}`;
330
+ const resolved = resolveImageProvider(cwd, preferKind);
331
+ if (!resolved) {
332
+ return preferKind
333
+ ? `Error: no image provider "${preferKind}" is available (unknown id/kind, or it has no API key). Configure it in your code-shell settings, or omit \`provider\` to use the default.`
334
+ : 'Error: no image provider available. Configure an image provider (including an apiKey) ' +
335
+ "in your code-shell settings to use GenerateImage.";
123
336
  }
124
- let json;
125
- try {
126
- json = await resp.json();
127
- }
128
- catch (err) {
129
- return `Error: could not parse image API response: ${err.message}`;
337
+ const adapter = getImageProvider(resolved.kind);
338
+ if (!adapter) {
339
+ return `Error: image generation is not supported for provider kind "${resolved.kind}".`;
130
340
  }
131
- const b64 = json?.data?.[0]?.b64_json;
132
- if (typeof b64 !== "string" || !b64) {
133
- const preview = JSON.stringify(json).slice(0, 500);
134
- return `Error: no image in response: ${preview}`;
341
+ // Model precedence: call arg > instance defaultModel (imageGen) > kind default.
342
+ const model = overrideModel ?? resolved.defaultModel ?? DEFAULT_IMAGE_MODEL[resolved.kind] ?? "gpt-image-2";
343
+ const result = await adapter.generate({
344
+ prompt,
345
+ size,
346
+ quality,
347
+ model,
348
+ creds: resolved.creds,
349
+ inputImages,
350
+ signal: ctx?.signal,
351
+ });
352
+ if (!result.ok) {
353
+ return `Error generating image: ${result.error}`;
135
354
  }
136
355
  try {
137
356
  const dir = join(cwd, ".code-shell", "generated_images");
138
357
  await mkdir(dir, { recursive: true });
139
- const path = join(dir, `${Date.now()}.png`);
140
- await writeFile(path, Buffer.from(b64, "base64"));
141
- return `Generated image saved to ${path}`;
358
+ // Timestamp keeps names sortable/recognizable; the random suffix prevents
359
+ // collisions when multiple GenerateImage calls run concurrently in one turn
360
+ // (Date.now() alone repeats within the same millisecond → writeFile would
361
+ // silently overwrite and drop an image).
362
+ const path = join(dir, `${Date.now()}-${randomBytes(3).toString("hex")}.png`);
363
+ await writeFile(path, Buffer.from(result.b64, "base64"));
364
+ // Name the provider/model actually used, so the user/agent knows which
365
+ // image backend produced this (esp. when a default fell back to another).
366
+ const mode = inputImages?.length
367
+ ? ` from ${inputImages.length} reference image(s)`
368
+ : "";
369
+ return `Generated image with ${resolved.kind} (${model})${mode}, saved to ${path}`;
142
370
  }
143
371
  catch (err) {
144
372
  return `Error saving generated image: ${err.message}`;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Built-in GenerateVideo tool (TODO 7.1 块3) — text-to-video via a
3
+ * {@link VideoProvider} adapter (submit / poll / download).
4
+ *
5
+ * Video generation is always slow (tens of seconds to minutes), so this tool
6
+ * is fire-and-forget by design: it submits the job, returns a handle
7
+ * immediately, and polls in the BACKGROUND. When the job finishes it writes
8
+ * the file to `<cwd>/.code-shell/generated_videos/` and enqueues a completion
9
+ * notification (same notificationQueue path as background agents / shells), so
10
+ * the main turn is never blocked (consistent with TODO 3.2 / 4.1).
11
+ *
12
+ * Concrete provider adapters (Seedance / Kling) are not wired yet — their
13
+ * private APIs need confirmed docs. Until then the only resolvable provider is
14
+ * the test-injected fake, so in production this tool is dormant (returns a
15
+ * "no video provider configured" message) rather than half-working.
16
+ */
17
+ import type { ToolDefinition } from "../../types.js";
18
+ import type { ToolContext } from "../context.js";
19
+ import { type VideoProvider, type VideoProviderCreds } from "./video-providers.js";
20
+ import { type ImageUploader, type UploaderCreds } from "./image-uploader.js";
21
+ /**
22
+ * Normalize image inputs (URLs or local paths) into public URLs the provider
23
+ * can consume. `images[]` wins over the single `image`. Local paths are
24
+ * uploaded via the injected {@link ImageUploader}; URLs pass through. Caps at
25
+ * {@link MAX_IMAGES} (fal reference-to-video allows up to 9).
26
+ */
27
+ export declare function __normalizeImagesForTests(images: string[] | undefined, image: string | undefined, uploader: ImageUploader, creds: UploaderCreds, signal?: AbortSignal): Promise<{
28
+ ok: true;
29
+ urls: string[];
30
+ } | {
31
+ ok: false;
32
+ error: string;
33
+ }>;
34
+ export declare const generateVideoToolDef: ToolDefinition;
35
+ export declare function __setVideoProviderForTests(p: VideoProvider | null): void;
36
+ export declare function isGenerateVideoAvailable(cwd?: string, nowMs?: number): boolean;
37
+ /**
38
+ * List configured, usable video providers (TODO 7.1). Returns [] when no
39
+ * adapters are wired (VIDEO_PROVIDER_KINDS empty) or none configured.
40
+ */
41
+ export declare function listConfiguredVideoProviders(cwd?: string): Array<{
42
+ id?: string;
43
+ kind: string;
44
+ catalogId?: string;
45
+ }>;
46
+ /** Dynamic GenerateVideo description naming configured providers (TODO 7.1). */
47
+ export declare function generateVideoToolDefFor(cwd: string): ToolDefinition;
48
+ interface ResolvedVideoProvider {
49
+ kind: string;
50
+ creds: VideoProviderCreds;
51
+ defaultModel?: string;
52
+ }
53
+ export declare function __resolveVideoProviderForTests(cwd: string, preferKind?: string): ResolvedVideoProvider | null;
54
+ export declare function generateVideoTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
55
+ export {};