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

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 (396) 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 +86 -0
  45. package/dist/context/compaction.js +279 -0
  46. package/dist/context/manager.d.ts +18 -0
  47. package/dist/context/manager.js +181 -48
  48. package/dist/context/token-counter.js +13 -0
  49. package/dist/cost-tracker.js +5 -61
  50. package/dist/credentials/cipher.d.ts +49 -0
  51. package/dist/credentials/cipher.js +45 -0
  52. package/dist/credentials/cookie-jar.d.ts +24 -0
  53. package/dist/credentials/cookie-jar.js +40 -0
  54. package/dist/credentials/index.d.ts +7 -0
  55. package/dist/credentials/index.js +5 -0
  56. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  57. package/dist/credentials/inject-credential-tool.js +130 -0
  58. package/dist/credentials/store.d.ts +72 -0
  59. package/dist/credentials/store.js +184 -0
  60. package/dist/credentials/types.d.ts +56 -0
  61. package/dist/credentials/use-credential-tool.d.ts +29 -0
  62. package/dist/credentials/use-credential-tool.js +205 -0
  63. package/dist/credentials/use-gate.d.ts +56 -0
  64. package/dist/credentials/use-gate.js +52 -0
  65. package/dist/data/model-metadata.d.ts +77 -0
  66. package/dist/data/model-metadata.js +56 -0
  67. package/dist/data/model-metadata.json +216 -0
  68. package/dist/data/openrouter-models.d.ts +18 -7
  69. package/dist/data/openrouter-models.js +35 -8
  70. package/dist/engine/aux-key.d.ts +10 -0
  71. package/dist/engine/aux-key.js +11 -0
  72. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  73. package/dist/engine/dynamic-tool-defs.js +36 -0
  74. package/dist/engine/engine.d.ts +280 -141
  75. package/dist/engine/engine.js +1193 -245
  76. package/dist/engine/friendly-error.d.ts +18 -0
  77. package/dist/engine/friendly-error.js +63 -0
  78. package/dist/engine/goal.d.ts +145 -0
  79. package/dist/engine/goal.js +144 -0
  80. package/dist/engine/image-policy.d.ts +13 -0
  81. package/dist/engine/image-policy.js +24 -0
  82. package/dist/engine/model-connections-pool.d.ts +17 -0
  83. package/dist/engine/model-connections-pool.js +67 -0
  84. package/dist/engine/model-facade.d.ts +10 -0
  85. package/dist/engine/model-facade.js +15 -0
  86. package/dist/engine/patch-orphaned-tools.js +3 -0
  87. package/dist/engine/query.js +2 -0
  88. package/dist/engine/resolve-llm-config.d.ts +16 -0
  89. package/dist/engine/resolve-llm-config.js +44 -0
  90. package/dist/engine/runtime.d.ts +2 -0
  91. package/dist/engine/runtime.js +27 -1
  92. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  93. package/dist/engine/sandbox-cache-key.js +9 -0
  94. package/dist/engine/sandbox-config.d.ts +31 -0
  95. package/dist/engine/sandbox-config.js +38 -0
  96. package/dist/engine/session-usage.d.ts +31 -0
  97. package/dist/engine/session-usage.js +81 -0
  98. package/dist/engine/steer-queue.d.ts +33 -0
  99. package/dist/engine/steer-queue.js +26 -0
  100. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  101. package/dist/engine/streaming-tool-queue.js +50 -10
  102. package/dist/engine/turn-loop.d.ts +94 -4
  103. package/dist/engine/turn-loop.js +432 -54
  104. package/dist/engine/types.d.ts +175 -0
  105. package/dist/engine/types.js +13 -0
  106. package/dist/external-agents/config.d.ts +2 -0
  107. package/dist/external-agents/config.js +15 -0
  108. package/dist/external-agents/types.d.ts +31 -0
  109. package/dist/external-agents/types.js +1 -0
  110. package/dist/git/utils.d.ts +12 -0
  111. package/dist/git/utils.js +38 -6
  112. package/dist/git/worktree.d.ts +48 -0
  113. package/dist/git/worktree.js +86 -10
  114. package/dist/hooks/goal-stop-hook.d.ts +28 -0
  115. package/dist/hooks/goal-stop-hook.js +186 -9
  116. package/dist/hooks/registry.d.ts +8 -0
  117. package/dist/hooks/registry.js +19 -0
  118. package/dist/hooks/shell-runner.js +10 -21
  119. package/dist/index.d.ts +51 -7
  120. package/dist/index.js +62 -5
  121. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  122. package/dist/llm/capabilities/param-specs.js +62 -0
  123. package/dist/llm/capabilities/rules.js +5 -1
  124. package/dist/llm/capabilities/types.d.ts +10 -0
  125. package/dist/llm/client-base.d.ts +28 -1
  126. package/dist/llm/client-base.js +119 -13
  127. package/dist/llm/model-cache.js +4 -2
  128. package/dist/llm/model-pool.d.ts +21 -0
  129. package/dist/llm/model-pool.js +21 -1
  130. package/dist/llm/provider-auth.d.ts +41 -0
  131. package/dist/llm/provider-auth.js +76 -0
  132. package/dist/llm/provider-catalog.d.ts +4 -0
  133. package/dist/llm/providers/anthropic.js +64 -14
  134. package/dist/llm/providers/openai.d.ts +36 -0
  135. package/dist/llm/providers/openai.js +257 -51
  136. package/dist/llm/reasoning-setting.d.ts +3 -3
  137. package/dist/llm/reasoning-setting.js +9 -1
  138. package/dist/llm/stream-watchdog.js +5 -1
  139. package/dist/llm/token-counter.js +9 -2
  140. package/dist/llm/types.d.ts +4 -0
  141. package/dist/logging/sanitize-messages.js +22 -0
  142. package/dist/lsp/manager.d.ts +1 -1
  143. package/dist/lsp/manager.js +40 -10
  144. package/dist/model-catalog/builtin.d.ts +12 -0
  145. package/dist/model-catalog/builtin.js +412 -0
  146. package/dist/model-catalog/gen-connections.d.ts +20 -0
  147. package/dist/model-catalog/gen-connections.js +28 -0
  148. package/dist/model-catalog/index.d.ts +41 -0
  149. package/dist/model-catalog/index.js +90 -0
  150. package/dist/model-catalog/params.d.ts +20 -0
  151. package/dist/model-catalog/params.js +45 -0
  152. package/dist/model-catalog/resolve.d.ts +48 -0
  153. package/dist/model-catalog/resolve.js +33 -0
  154. package/dist/model-catalog/save-entry.d.ts +32 -0
  155. package/dist/model-catalog/save-entry.js +104 -0
  156. package/dist/model-catalog/types.d.ts +561 -0
  157. package/dist/model-catalog/types.js +93 -0
  158. package/dist/model-catalog/upsert.d.ts +9 -0
  159. package/dist/model-catalog/upsert.js +8 -0
  160. package/dist/onboarding.d.ts +12 -82
  161. package/dist/onboarding.js +61 -326
  162. package/dist/plugins/gitOps.d.ts +19 -0
  163. package/dist/plugins/gitOps.js +73 -4
  164. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  165. package/dist/plugins/installer/checkUpdate.js +32 -0
  166. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  167. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  168. package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
  169. package/dist/plugins/installer/codex/convertMcp.js +45 -5
  170. package/dist/plugins/installer/install.js +25 -1
  171. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  172. package/dist/plugins/installer/installFromArchive.js +134 -0
  173. package/dist/plugins/installer/installFromSource.js +8 -2
  174. package/dist/plugins/installer/loadPluginAgents.js +6 -2
  175. package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
  176. package/dist/plugins/installer/loadPluginMcp.js +35 -2
  177. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  178. package/dist/plugins/installer/pruneDisabled.js +73 -0
  179. package/dist/plugins/installer/types.d.ts +5 -2
  180. package/dist/plugins/installer/types.js +1 -0
  181. package/dist/plugins/installer/uninstall.js +4 -0
  182. package/dist/plugins/installer/unzip.d.ts +14 -0
  183. package/dist/plugins/installer/unzip.js +82 -0
  184. package/dist/plugins/installer/update.d.ts +14 -0
  185. package/dist/plugins/installer/update.js +53 -21
  186. package/dist/plugins/loadPluginHooks.d.ts +47 -1
  187. package/dist/plugins/loadPluginHooks.js +73 -1
  188. package/dist/plugins/marketplaceManager.d.ts +7 -0
  189. package/dist/plugins/marketplaceManager.js +20 -0
  190. package/dist/plugins/pluginCommandHook.js +4 -18
  191. package/dist/plugins/pluginContent.d.ts +30 -0
  192. package/dist/plugins/pluginContent.js +83 -0
  193. package/dist/plugins/pluginInstaller.d.ts +13 -0
  194. package/dist/plugins/pluginInstaller.js +42 -8
  195. package/dist/plugins/schemas.js +1 -0
  196. package/dist/plugins/types.d.ts +6 -0
  197. package/dist/preset/index.d.ts +11 -1
  198. package/dist/preset/index.js +115 -6
  199. package/dist/product/types.d.ts +1 -1
  200. package/dist/prompt/composer.d.ts +32 -0
  201. package/dist/prompt/composer.js +75 -21
  202. package/dist/prompt/instruction-scanner.js +5 -3
  203. package/dist/prompt/section-loader.js +1 -0
  204. package/dist/prompt/sections/base.md +2 -0
  205. package/dist/prompt/sections/browser.md +10 -0
  206. package/dist/prompt/sections/coding.md +4 -0
  207. package/dist/protocol/chat-session-manager.d.ts +9 -2
  208. package/dist/protocol/chat-session-manager.js +38 -0
  209. package/dist/protocol/chat-session.d.ts +69 -1
  210. package/dist/protocol/chat-session.js +102 -4
  211. package/dist/protocol/client.d.ts +31 -0
  212. package/dist/protocol/client.js +44 -0
  213. package/dist/protocol/server.d.ts +120 -7
  214. package/dist/protocol/server.js +753 -51
  215. package/dist/protocol/transport.js +3 -2
  216. package/dist/protocol/types.d.ts +60 -0
  217. package/dist/protocol/types.js +16 -0
  218. package/dist/quota/credentials.d.ts +3 -0
  219. package/dist/quota/credentials.js +80 -0
  220. package/dist/quota/index.d.ts +36 -0
  221. package/dist/quota/index.js +155 -0
  222. package/dist/quota/types.d.ts +48 -0
  223. package/dist/quota/types.js +13 -0
  224. package/dist/review/review-prompt.d.ts +28 -0
  225. package/dist/review/review-prompt.js +81 -0
  226. package/dist/run/FileRunStore.js +8 -3
  227. package/dist/run/RunApprovalBackend.js +25 -5
  228. package/dist/run/RunManager.d.ts +12 -0
  229. package/dist/run/RunManager.js +35 -0
  230. package/dist/run/factory.d.ts +1 -1
  231. package/dist/runtime/background-shell.d.ts +139 -0
  232. package/dist/runtime/background-shell.js +509 -0
  233. package/dist/runtime/output-clean.d.ts +24 -0
  234. package/dist/runtime/output-clean.js +41 -0
  235. package/dist/runtime/ring-file.d.ts +64 -0
  236. package/dist/runtime/ring-file.js +174 -0
  237. package/dist/runtime/safe-spawn.js +98 -39
  238. package/dist/runtime/spawn-common.d.ts +159 -0
  239. package/dist/runtime/spawn-common.js +404 -0
  240. package/dist/runtime/truncate-output.d.ts +22 -0
  241. package/dist/runtime/truncate-output.js +49 -0
  242. package/dist/runtime/utf8-cut.d.ts +11 -0
  243. package/dist/runtime/utf8-cut.js +23 -0
  244. package/dist/services/auto-dream.d.ts +4 -0
  245. package/dist/services/auto-dream.js +26 -26
  246. package/dist/services/diagnostics.d.ts +1 -2
  247. package/dist/services/diagnostics.js +12 -7
  248. package/dist/services/extract-memories.d.ts +14 -1
  249. package/dist/services/extract-memories.js +45 -6
  250. package/dist/services/memory-orchestrator.d.ts +21 -0
  251. package/dist/services/memory-orchestrator.js +125 -50
  252. package/dist/services/session-memory.js +24 -12
  253. package/dist/session/file-history.d.ts +124 -1
  254. package/dist/session/file-history.js +222 -6
  255. package/dist/session/memory.d.ts +116 -2
  256. package/dist/session/memory.js +250 -28
  257. package/dist/session/session-manager.d.ts +40 -0
  258. package/dist/session/session-manager.js +119 -3
  259. package/dist/session/simple-diff.d.ts +23 -0
  260. package/dist/session/simple-diff.js +84 -0
  261. package/dist/session/transcript.d.ts +29 -1
  262. package/dist/session/transcript.js +56 -2
  263. package/dist/session/undo-target.d.ts +67 -0
  264. package/dist/session/undo-target.js +144 -0
  265. package/dist/settings/disk-defaults.d.ts +9 -2
  266. package/dist/settings/disk-defaults.js +11 -2
  267. package/dist/settings/feature-flags.d.ts +64 -0
  268. package/dist/settings/feature-flags.js +61 -0
  269. package/dist/settings/manager.d.ts +68 -1
  270. package/dist/settings/manager.js +266 -29
  271. package/dist/settings/migrate-config.d.ts +45 -0
  272. package/dist/settings/migrate-config.js +125 -0
  273. package/dist/settings/schema-export.d.ts +25 -0
  274. package/dist/settings/schema-export.js +38 -0
  275. package/dist/settings/schema.d.ts +1186 -771
  276. package/dist/settings/schema.js +268 -97
  277. package/dist/skills/scanner.d.ts +9 -0
  278. package/dist/skills/scanner.js +30 -2
  279. package/dist/stt/resolve-transcribe.d.ts +31 -0
  280. package/dist/stt/resolve-transcribe.js +108 -0
  281. package/dist/stt/transcribe.d.ts +51 -0
  282. package/dist/stt/transcribe.js +65 -0
  283. package/dist/tool-system/browser-bridge.d.ts +226 -0
  284. package/dist/tool-system/browser-bridge.js +163 -0
  285. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  286. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  287. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  288. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  289. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  290. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  291. package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
  292. package/dist/tool-system/builtin/agent-registry.js +8 -0
  293. package/dist/tool-system/builtin/agent.d.ts +21 -1
  294. package/dist/tool-system/builtin/agent.js +489 -42
  295. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  296. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  297. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  298. package/dist/tool-system/builtin/apply-patch/index.js +0 -15
  299. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  300. package/dist/tool-system/builtin/background-jobs.js +124 -0
  301. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  302. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  303. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  304. package/dist/tool-system/builtin/background-work.js +86 -0
  305. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  306. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  307. package/dist/tool-system/builtin/bash.d.ts +5 -2
  308. package/dist/tool-system/builtin/bash.js +101 -64
  309. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  310. package/dist/tool-system/builtin/browser-tools.js +312 -0
  311. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  312. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  313. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  314. package/dist/tool-system/builtin/check-quota.js +34 -0
  315. package/dist/tool-system/builtin/config.js +7 -0
  316. package/dist/tool-system/builtin/cron.d.ts +7 -0
  317. package/dist/tool-system/builtin/cron.js +64 -4
  318. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  319. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  320. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  321. package/dist/tool-system/builtin/edit-model-catalog.js +104 -0
  322. package/dist/tool-system/builtin/edit.js +20 -16
  323. package/dist/tool-system/builtin/eol.d.ts +29 -0
  324. package/dist/tool-system/builtin/eol.js +37 -0
  325. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  326. package/dist/tool-system/builtin/file-cache.js +8 -0
  327. package/dist/tool-system/builtin/generate-image.d.ts +35 -0
  328. package/dist/tool-system/builtin/generate-image.js +278 -50
  329. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  330. package/dist/tool-system/builtin/generate-video.js +364 -0
  331. package/dist/tool-system/builtin/glob.js +0 -7
  332. package/dist/tool-system/builtin/grep.d.ts +9 -0
  333. package/dist/tool-system/builtin/grep.js +106 -11
  334. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  335. package/dist/tool-system/builtin/image-providers.js +190 -0
  336. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  337. package/dist/tool-system/builtin/image-uploader.js +74 -0
  338. package/dist/tool-system/builtin/index.d.ts +10 -2
  339. package/dist/tool-system/builtin/index.js +251 -27
  340. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  341. package/dist/tool-system/builtin/memory.js +45 -7
  342. package/dist/tool-system/builtin/notebook-edit.js +0 -7
  343. package/dist/tool-system/builtin/powershell.js +8 -2
  344. package/dist/tool-system/builtin/read.js +10 -10
  345. package/dist/tool-system/builtin/repl.js +4 -1
  346. package/dist/tool-system/builtin/skill.js +9 -0
  347. package/dist/tool-system/builtin/sleep.js +8 -2
  348. package/dist/tool-system/builtin/tool-search.js +25 -7
  349. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  350. package/dist/tool-system/builtin/video-providers.js +235 -0
  351. package/dist/tool-system/builtin/web-fetch.js +12 -2
  352. package/dist/tool-system/builtin/web-search.js +21 -7
  353. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  354. package/dist/tool-system/builtin/worktree.js +31 -4
  355. package/dist/tool-system/builtin/write.js +0 -6
  356. package/dist/tool-system/context.d.ts +164 -6
  357. package/dist/tool-system/executor.d.ts +3 -1
  358. package/dist/tool-system/executor.js +197 -90
  359. package/dist/tool-system/investigation-guard.js +1 -1
  360. package/dist/tool-system/mcp-manager.d.ts +42 -4
  361. package/dist/tool-system/mcp-manager.js +203 -20
  362. package/dist/tool-system/mcp-stdio-diagnostics.d.ts +9 -0
  363. package/dist/tool-system/mcp-stdio-diagnostics.js +93 -0
  364. package/dist/tool-system/path-policy.d.ts +5 -0
  365. package/dist/tool-system/path-policy.js +307 -8
  366. package/dist/tool-system/permission.d.ts +39 -2
  367. package/dist/tool-system/permission.js +283 -70
  368. package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
  369. package/dist/tool-system/plan-mode-allowlist.js +24 -2
  370. package/dist/tool-system/registry.d.ts +1 -0
  371. package/dist/tool-system/registry.js +16 -2
  372. package/dist/tool-system/sandbox/index.d.ts +8 -0
  373. package/dist/tool-system/sandbox/index.js +7 -2
  374. package/dist/tool-system/sandbox/off.js +7 -1
  375. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  376. package/dist/tool-system/validate-tool-metadata.js +63 -0
  377. package/dist/types.d.ts +252 -7
  378. package/dist/updater.js +20 -9
  379. package/dist/utils/envUtils.d.ts +0 -9
  380. package/dist/utils/envUtils.js +3 -28
  381. package/dist/utils/exec.d.ts +48 -0
  382. package/dist/utils/exec.js +154 -0
  383. package/dist/utils/json.d.ts +12 -0
  384. package/dist/utils/json.js +92 -0
  385. package/dist/utils/theme.d.ts +1 -1
  386. package/dist/utils/theme.js +1 -1
  387. package/dist/utils/toolDisplay.js +0 -1
  388. package/package.json +13 -7
  389. package/dist/agent/coordinator.d.ts +0 -49
  390. package/dist/agent/coordinator.js +0 -77
  391. package/dist/settings/manager.test.js +0 -73
  392. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  393. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  394. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  395. package/dist/tool-system/builtin/send-message.js +0 -47
  396. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -2,7 +2,6 @@
2
2
  * Settings schema with Zod validation.
3
3
  */
4
4
  import { z } from "zod";
5
- import { ReasoningSettingSchema } from "../llm/reasoning-setting.js";
6
5
  /**
7
6
  * Tri-state project capability overlay. Lives in PROJECT settings only and
8
7
  * layers over the global baseline (disabledSkills / disabledPlugins /
@@ -21,6 +20,14 @@ export const CapabilityOverridesSchema = z
21
20
  agents: z.record(CapabilityOverrideSchema).optional(),
22
21
  mcp: z.record(CapabilityOverrideSchema).optional(),
23
22
  builtin: z.record(CapabilityOverrideSchema).optional(),
23
+ /**
24
+ * Per-hook overlay for PLUGIN-provided hooks, keyed by
25
+ * `pluginHookKey()` (`<plugin>:<RawEvent>:<command>`). Finer-grained
26
+ * than `plugins` (which kills a whole plugin): "off" suppresses one
27
+ * hook for this project only. Only "off" is meaningful today — plugin
28
+ * hooks have no global disable list to force back "on" from.
29
+ */
30
+ pluginHooks: z.record(CapabilityOverrideSchema).optional(),
24
31
  })
25
32
  .optional();
26
33
  export const SettingsSchema = z
@@ -43,23 +50,6 @@ export const SettingsSchema = z
43
50
  .optional(),
44
51
  })
45
52
  .default({}),
46
- /**
47
- * Primary source of truth for the active model is settings.activeKey
48
- * (points at models[].key). settings.model is a derived mirror of that
49
- * entry kept in sync for legacy boot paths (cli/main.ts, repl.ts, etc.)
50
- * which read provider/name/apiKey/baseUrl directly. Writers must update
51
- * both — appendOnboardingResult does this in one shot.
52
- */
53
- activeKey: z.string().optional(),
54
- /**
55
- * Auxiliary-task model — points at a models[].key. Background, non-user-
56
- * facing LLM calls (memory extraction, the auto-dream loop) use this model
57
- * instead of the active one, so per-turn book-keeping doesn't burn the
58
- * expensive primary model. Pick something fast/cheap (e.g. a Haiku or
59
- * DeepSeek key). When unset, those calls fall back to the active model
60
- * (legacy behavior). An invalid/missing key also falls back to active.
61
- */
62
- auxModelKey: z.string().optional(),
63
53
  /**
64
54
  * Toggle background auto-update. When true (default), code-shell checks
65
55
  * npm for newer versions and — if the npm global prefix is writable —
@@ -68,84 +58,115 @@ export const SettingsSchema = z
68
58
  * Can also be disabled via env var `DISABLE_AUTOUPDATER=1`.
69
59
  */
70
60
  autoUpdates: z.boolean().default(true),
71
- model: z
61
+ /**
62
+ * Image generation is a general capability, decoupled from LLM providers
63
+ * (TODO 7.1): a vendor may use different keys/endpoints/models for chat vs
64
+ * image, and image vendors (Gemini, and later 国内 模型) don't fit the LLM
65
+ * `providers[].kind` enum. `imageGen.providers[]` is the canonical config;
66
+ * each entry has a user-chosen `id` (selected via GenerateImage's
67
+ * `provider` arg) and a `kind` that picks the adapter. When `imageGen` is
68
+ * absent, resolution falls back to scanning LLM `providers[]` for an
69
+ * image-capable kind — so existing configs keep working with no migration.
70
+ */
71
+ imageGen: z
72
72
  .object({
73
- provider: z.string().default("openai"),
74
- name: z.string().default("anthropic/claude-opus-4-6"),
75
- apiKey: z.string().optional(),
76
- baseUrl: z.string().default("https://openrouter.ai/api/v1"),
77
- temperature: z.number().min(0).max(2).default(0.3),
78
- maxTokens: z.number().default(8192),
73
+ defaultProvider: z.string().optional(),
74
+ providers: z
75
+ .array(z.object({
76
+ /** User-chosen instance name; GenerateImage(provider) selects by this. */
77
+ id: z.string(),
78
+ /** Adapter selector — e.g. "openai", "google". */
79
+ kind: z.string(),
80
+ baseUrl: z.string(),
81
+ apiKey: z.string().optional(),
82
+ /** Default model for this instance when the call omits `model`. */
83
+ defaultModel: z.string().optional(),
84
+ /** Catalog template this instance was created from (for paramsDoc / displayName回显). */
85
+ catalogId: z.string().optional(),
86
+ /** Reuse another instance's key: id of the instance whose apiKey to use (when apiKey is empty). */
87
+ apiKeyRef: z.string().optional(),
88
+ }))
89
+ .default([]),
79
90
  })
80
- .default({}),
81
- providers: z
91
+ .optional(),
92
+ /**
93
+ * Video generation config (TODO 7.1) — same shape as imageGen, decoupled
94
+ * from LLM providers. `videoGen.providers[]` each carry an `id` (selected
95
+ * via GenerateVideo's `provider` arg) + a `kind` picking the adapter. With
96
+ * no real adapters wired yet, this is config-ready: a future getVideoProvider
97
+ * case lights it up. Falls back to scanning LLM providers[] when absent.
98
+ */
99
+ videoGen: z
100
+ .object({
101
+ defaultProvider: z.string().optional(),
102
+ providers: z
103
+ .array(z.object({
104
+ id: z.string(),
105
+ kind: z.string(),
106
+ baseUrl: z.string(),
107
+ apiKey: z.string().optional(),
108
+ defaultModel: z.string().optional(),
109
+ /** Catalog template this instance was created from (for paramsDoc / displayName回显). */
110
+ catalogId: z.string().optional(),
111
+ /** Reuse another instance's key: id of the instance whose apiKey to use (when apiKey is empty). */
112
+ apiKeyRef: z.string().optional(),
113
+ }))
114
+ .default([]),
115
+ })
116
+ .optional(),
117
+ /**
118
+ * Credentials — independent key entities (统一模型接入方案 §3.3). A key
119
+ * lives here, not inlined on a connection, so deleting a connection never
120
+ * loses a key and many connections share one key by referencing the same
121
+ * credential id (LiteLLM credential_list model).
122
+ */
123
+ credentials: z
82
124
  .array(z.object({
83
- key: z.string(),
84
- label: z.string().optional(),
85
- kind: z.enum([
86
- "openai",
87
- "anthropic",
88
- "deepseek",
89
- "zai",
90
- "xai",
91
- "mistral",
92
- "groq",
93
- "google",
94
- "openrouter",
95
- "ollama",
96
- "custom",
97
- ]),
98
- baseUrl: z.string(),
125
+ /** User-chosen unique credential name. */
126
+ id: z.string(),
127
+ /** Catalog template this credential is for (a key belongs to one provider). */
128
+ catalogId: z.string(),
99
129
  apiKey: z.string().optional(),
100
- protocol: z.enum(["openai-compat", "anthropic-style"]).optional(),
101
- modelsPath: z.string().optional(),
102
- /**
103
- * Default reasoning/thinking setting for this provider's models.
104
- * Rich shape: {mode:"off"|"on"} | {mode:"effort",effort} |
105
- * {mode:"budget",budgetTokens}. Per-model `reasoning` wins.
106
- */
107
- reasoning: ReasoningSettingSchema.optional(),
130
+ baseUrl: z.string().optional(),
108
131
  }))
109
132
  .default([]),
110
- models: z
111
- .array(z
112
- .object({
113
- key: z.string(),
114
- label: z.string().optional(),
115
- providerKey: z.string().optional(),
133
+ /**
134
+ * Unified instance layer (统一模型接入方案, see
135
+ * docs/superpowers/specs/2026-06-15-unified-model-catalog-design.md §3.3).
136
+ * One store for text/image/video connections, each pointing at a catalog
137
+ * entry (catalogId), a credential (credentialId), its chosen model, and the
138
+ * param values the user picked. Replaces the legacy split of
139
+ * providers[]/models[]/imageGen/videoGen.
140
+ */
141
+ modelConnections: z
142
+ .array(z.object({
143
+ /** User-chosen unique instance name. */
144
+ id: z.string(),
145
+ /** Catalog template this instance was created from. */
146
+ catalogId: z.string(),
147
+ tag: z.enum(["text", "image", "video", "audio"]),
148
+ /** Selected modelId (from the entry's modelPresets). */
116
149
  model: z.string(),
117
- maxOutputTokens: z.number().optional(),
118
- maxContextTokens: z.number().optional(),
119
- /**
120
- * Which LLM client to use ("openai" or "anthropic"). New name —
121
- * the legacy field is `provider`, which we still accept and
122
- * fold into `protocol` below so old configs keep working.
123
- * NOT the brand/vendor — that's providerKey above.
124
- */
125
- protocol: z.string().optional(),
126
- provider: z.string().optional(),
150
+ /** Per-connection baseUrl override (else the credential's / catalog's). */
127
151
  baseUrl: z.string().optional(),
128
- apiKey: z.string().optional(),
129
- /**
130
- * Per-model reasoning override. Wins over the provider-level
131
- * `reasoning` setting (settings.providers[].reasoning). Use this
132
- * when different models under the same provider need different
133
- * defaults — e.g. one model off (faster) and another on.
134
- */
135
- reasoning: ReasoningSettingSchema.optional(),
136
- })
137
- .transform((m) => {
138
- // Normalize: prefer `protocol`; fall back to legacy `provider`.
139
- // We keep `provider` populated as a mirror because engine code
140
- // and a few downstream readers still query it directly.
141
- const effective = m.protocol ?? m.provider;
142
- return {
143
- ...m,
144
- protocol: effective,
145
- provider: effective,
146
- };
152
+ /** Which credential supplies this connection's key. */
153
+ credentialId: z.string().optional(),
154
+ /** Values the user picked for the model's params, e.g. { reasoning: "high" }. */
155
+ paramValues: z.record(z.string(), z.unknown()).optional(),
147
156
  }))
148
157
  .default([]),
158
+ /** Default instance id per tag (replaces activeKey / defaultProvider). */
159
+ defaults: z
160
+ .object({
161
+ text: z.string().optional(),
162
+ image: z.string().optional(),
163
+ video: z.string().optional(),
164
+ /** Default speech-to-text (voice input) connection. */
165
+ audio: z.string().optional(),
166
+ /** Background-task model (replaces auxModelKey). */
167
+ auxText: z.string().optional(),
168
+ })
169
+ .default({}),
149
170
  permissions: z
150
171
  .object({
151
172
  defaultMode: z
@@ -164,8 +185,27 @@ export const SettingsSchema = z
164
185
  context: z
165
186
  .object({
166
187
  maxTokens: z.number().default(200_000),
167
- compactAtRatio: z.number().default(0.6),
168
- summarizeAtRatio: z.number().default(0.8),
188
+ // 压缩阈值(占上下文窗口的比例)。窗口越大可调越高:1M 窗口的模型
189
+ // 把 compactAtRatio 调到 0.95 能少浪费几十万 token。三档须满足
190
+ // floor < compact < summarize,否则运行时会 clamp 回安全顺序。
191
+ compactAtRatio: z
192
+ .number()
193
+ .min(0.1)
194
+ .max(0.98)
195
+ .default(0.85)
196
+ .describe("达到该比例开始压缩历史(先试摘要,再退化为窗口裁剪)。默认 0.85。"),
197
+ summarizeAtRatio: z
198
+ .number()
199
+ .min(0.1)
200
+ .max(0.99)
201
+ .default(0.92)
202
+ .describe("紧急阈值:到此比例做最激进的窗口压缩。须 ≥ compactAtRatio。默认 0.92。"),
203
+ microcompactFloorRatio: z
204
+ .number()
205
+ .min(0.1)
206
+ .max(0.95)
207
+ .default(0.7)
208
+ .describe("低于该比例不做 microcompact,保留早期工具输出、保住 prompt cache 前缀。默认 0.7。"),
169
209
  })
170
210
  .default({}),
171
211
  session: z
@@ -174,8 +214,31 @@ export const SettingsSchema = z
174
214
  maxHistory: z.number().default(100),
175
215
  })
176
216
  .default({}),
217
+ // The record key IS the server name at runtime (MCPManager.connectAll
218
+ // uses Object.entries keys; desktop's persist strips the `name` field and
219
+ // keys by it via stripNameFromServer). So `name` here is optional and
220
+ // backfilled from the key — a config keyed `{"23": {…}}` with no `name`
221
+ // field is valid, not a crash. The preprocess also tolerates a legacy
222
+ // array form (`[{name, …}]`) by re-keying it into a name → config record.
177
223
  mcpServers: z
178
- .record(z.object({
224
+ .preprocess((value) => {
225
+ const entries = Array.isArray(value)
226
+ ? value
227
+ .filter((v) => !!v && typeof v === "object")
228
+ .map((v, i) => [String(v.name ?? i), v])
229
+ : value && typeof value === "object"
230
+ ? Object.entries(value)
231
+ : [];
232
+ return Object.fromEntries(entries.map(([key, raw]) => [
233
+ key,
234
+ raw && typeof raw === "object"
235
+ ? { ...raw, name: raw.name ?? key }
236
+ : raw,
237
+ ]));
238
+ }, z.record(z.object({
239
+ // Always present here: the preprocess above backfills it from the
240
+ // record key, so a stored entry that omits `name` (the common
241
+ // desktop case, which strips it) still validates.
179
242
  name: z.string(),
180
243
  command: z.string().optional(),
181
244
  args: z.array(z.string()).optional(),
@@ -183,10 +246,34 @@ export const SettingsSchema = z
183
246
  url: z.string().optional(),
184
247
  transport: z.enum(["stdio", "sse", "streamable-http", "inprocess"]).optional(),
185
248
  headers: z.record(z.string()).optional(),
249
+ // Codex-style env-secret handling: store env-var NAMES, read the
250
+ // secret from process.env at connect time (never plaintext here).
251
+ envVars: z.array(z.string()).optional(), // (stdio) forward these env vars
252
+ bearerTokenEnvVar: z.string().optional(), // (HTTP) → Authorization: Bearer <env value>
253
+ envHeaders: z.record(z.string()).optional(), // (HTTP) header-name → env-var-name
254
+ credentialRef: z.string().optional(), // (HTTP) id of a stored credential → Bearer, resolved at connect time
186
255
  // Codex-style on/off switch. Absent or true → connected; only
187
256
  // literal false disables. Filtered in MCPManager.connectAll.
188
257
  enabled: z.boolean().optional(),
189
- }))
258
+ })))
259
+ .default({}),
260
+ /**
261
+ * User supplements for PLUGIN-provided MCP servers, keyed by the server's
262
+ * `<plugin>:<server>` name. Layered onto the plugin config at merge time
263
+ * (mergePluginMcpServers). Only env/credential fields are accepted —
264
+ * command/args/url/transport are intentionally absent and `.strict()`
265
+ * rejects them, so a plugin update is never shadowed by a stale copy.
266
+ */
267
+ mcpServerOverrides: z
268
+ .record(z
269
+ .object({
270
+ env: z.record(z.string()).optional(),
271
+ envVars: z.array(z.string()).optional(),
272
+ credentialRef: z.string().optional(),
273
+ bearerTokenEnvVar: z.string().optional(),
274
+ envHeaders: z.record(z.string()).optional(),
275
+ })
276
+ .strict())
190
277
  .default({}),
191
278
  /**
192
279
  * Skill names hidden from the LLM. Names include the full
@@ -216,6 +303,32 @@ export const SettingsSchema = z
216
303
  * capability-assembly time. Optional — absence === everything inherits.
217
304
  */
218
305
  capabilityOverrides: CapabilityOverridesSchema,
306
+ /**
307
+ * Feature flags overlay: a map of flag name → boolean that overrides the
308
+ * compiled-in defaults (see settings/feature-flags.ts FEATURE_FLAGS).
309
+ * Project settings override user settings via the normal merge, so a flag
310
+ * can be flipped per-workspace. Unknown flag names are tolerated (kept as
311
+ * data) for forward-compat; consumers only read known flags via
312
+ * isFeatureEnabled(). Passthrough record — values coerced to boolean.
313
+ */
314
+ featureFlags: z.record(z.string(), z.boolean()).default({}),
315
+ /**
316
+ * Cross-session memory knobs. Optional — absence keeps the built-in
317
+ * defaults (see services/extract-memories.ts). `maxCount` caps memories
318
+ * accepted per extraction pass; `maxAge`/`extractionModel` are reserved
319
+ * for the consolidation/extraction pipeline.
320
+ */
321
+ memories: z
322
+ .object({
323
+ maxCount: z.number().int().positive().optional(),
324
+ maxAge: z.number().int().positive().optional(),
325
+ extractionModel: z.string().optional(),
326
+ /** Master switch for end-of-session automatic memory extraction.
327
+ * Absent/true = extract (current behavior); false = skip extraction
328
+ * while keeping session summaries and Dream untouched. */
329
+ autoExtract: z.boolean().optional(),
330
+ })
331
+ .optional(),
219
332
  instructions: z
220
333
  .object({
221
334
  fileName: z.string().default("CODESHELL.md"),
@@ -278,19 +391,22 @@ export const SettingsSchema = z
278
391
  .default({}),
279
392
  /**
280
393
  * Image attachment handling. Sub-fields:
281
- * - detail: OpenAI-style fidelity hint applied to every user-
282
- * attached image. "low" = 85 tokens/image fixed (cheap
283
- * thumbnail), "high" = ~768 px tiles (default), "original" =
284
- * keep client-side dimensions (most expensive). Anthropic
285
- * ignores this field today; that's fine — it just gets
286
- * dropped on the Claude path.
394
+ * - detail: provider-agnostic image clarity. Drives the
395
+ * renderer-side downscale (low→~1024 / standard→~1568 /
396
+ * high→~2576 px long edge) so BOTH providers save tokens
397
+ * before send. Legacy "original" is migrated to "high".
287
398
  * - mcpImageTokenBudget: per-turn cap on token cost of images
288
399
  * returned by MCP tools. Codex doesn't enforce this; CC uses
289
400
  * 25 000. Set to 0 to disable.
290
401
  */
291
402
  images: z
292
403
  .object({
293
- detail: z.enum(["low", "high", "original"]).optional(),
404
+ detail: z
405
+ .preprocess(
406
+ // Legacy migration: old settings stored "original"; map it to
407
+ // "high" so existing user.json doesn't fail validation on boot.
408
+ (v) => (v === "original" ? "high" : v), z.enum(["low", "standard", "high"]))
409
+ .optional(),
294
410
  mcpImageTokenBudget: z.number().int().nonnegative().optional(),
295
411
  })
296
412
  .optional(),
@@ -308,6 +424,21 @@ export const SettingsSchema = z
308
424
  network: z.enum(["allow", "deny"]).optional(),
309
425
  })
310
426
  .optional(),
427
+ /**
428
+ * Top-level environment variables injected into tool subprocesses (the
429
+ * Bash tool, background shells). Mirrors Claude Code's `env` field: a
430
+ * KEY=VALUE map that can be set globally (~/.code-shell/settings.json) and
431
+ * overridden per-project (.code-shell/settings.json). The canonical home
432
+ * for API keys (e.g. OPENAI_API_KEY) that a skill's script reads — configure
433
+ * once globally and every project's skills can use it.
434
+ *
435
+ * Precedence when merged into the spawn env (lowest → highest):
436
+ * project localEnvironment.env → global env → project env
437
+ * None of these is filtered through the deny regex (see mergeShellEnv):
438
+ * they are values the user typed deliberately, a different trust class from
439
+ * the host process.env passthrough the deny machinery guards against.
440
+ */
441
+ env: z.record(z.string()).optional(),
311
442
  /**
312
443
  * Project-local environment profile. Mirrors Codex's local-environment
313
444
  * shape at the settings layer: setup/cleanup scripts can be customized per
@@ -353,8 +484,48 @@ export const SettingsSchema = z
353
484
  matcher: z.string().optional(),
354
485
  timeout_ms: z.number().int().positive().optional(),
355
486
  cwd: z.string().optional(),
487
+ /** Soft off-switch: the entry stays in the file (and the UI) but
488
+ * registerSettingsHooks skips it. Absent = enabled. */
489
+ disabled: z.boolean().optional(),
356
490
  }))
357
491
  .optional(),
492
+ /**
493
+ * External coding-agent orchestration (Claude Code / Codex CLI).
494
+ * Used by the Mobile Web Remote to launch managed jobs. dangerousArgs
495
+ * is config-provided (not hardcoded) so it tracks CLI flag changes;
496
+ * project-default dangerous mode only applies inside trustedWorkspaces.
497
+ */
498
+ externalAgents: z
499
+ .object({
500
+ claudeCode: z
501
+ .object({
502
+ command: z.string().optional(),
503
+ defaultMode: z.enum(["safe", "dangerous"]).optional(),
504
+ dangerousArgs: z.array(z.string()).optional(),
505
+ trustedWorkspaces: z.array(z.string()).optional(),
506
+ autoStartInTrustedWorkspaces: z.boolean().optional(),
507
+ })
508
+ .optional(),
509
+ codex: z
510
+ .object({
511
+ command: z.string().optional(),
512
+ args: z.array(z.string()).optional(),
513
+ })
514
+ .optional(),
515
+ })
516
+ .optional(),
517
+ /**
518
+ * Credential-use gate (凭证模块第二期). Controls whether the AI's
519
+ * `UseCredential` tool prompts before handing a stored credential to a
520
+ * command. `autoApprove: true` skips the prompt entirely (默认关 — every
521
+ * use asks, or is remembered for the session). See
522
+ * docs/superpowers/specs/2026-06-16-credential-use-gate-design.md §5.
523
+ */
524
+ credentialUse: z
525
+ .object({
526
+ autoApprove: z.boolean().optional(),
527
+ })
528
+ .optional(),
358
529
  })
359
530
  .passthrough();
360
531
  export function validateSettings(raw) {
@@ -33,6 +33,15 @@ export interface SkillDefinition {
33
33
  export interface ScanSkillsOptions {
34
34
  disabledSkills?: string[];
35
35
  disabledPlugins?: string[];
36
+ /**
37
+ * Hard skill isolation for sub-agents. When set, ONLY skills whose name is
38
+ * in this list survive — every other skill is dropped from the result
39
+ * regardless of the disabled lists. Undefined → no allowlist filtering
40
+ * (parent inherits the full pool). An empty array → no skills at all.
41
+ * Applied after the disabled-list filters, so a skill must be both allowed
42
+ * AND not disabled to appear.
43
+ */
44
+ skillAllowlist?: string[];
36
45
  }
37
46
  export declare function scanSkills(cwd: string, opts?: ScanSkillsOptions): SkillDefinition[];
38
47
  export declare function invalidateSkillCache(): void;
@@ -157,18 +157,46 @@ function installedPluginsMtime() {
157
157
  return "0";
158
158
  }
159
159
  }
160
- const memoized = memoize(scanOnce, (cwd) => `${cwd}\0${userHome()}\0${installedPluginsMtime()}`);
160
+ /**
161
+ * mtime of each local skills base dir (project + user). A directory's mtime
162
+ * changes when a child entry is added/removed, so installing a new skill into
163
+ * `<cwd>/.code-shell/skills` or `~/.code-shell/skills` busts the cache on the
164
+ * next scan — the just-installed skill becomes visible to the running session
165
+ * without a restart. (Editing an existing skill's *contents* does not bump the
166
+ * dir mtime; install paths additionally call invalidateSkillCache() to cover
167
+ * that, so this is the passive half of a two-part guard.)
168
+ */
169
+ function skillsDirsMtime(cwd) {
170
+ return bases(cwd)
171
+ .map((b) => {
172
+ try {
173
+ return statSync(b.dir).mtimeMs.toString();
174
+ }
175
+ catch {
176
+ return "0";
177
+ }
178
+ })
179
+ .join("|");
180
+ }
181
+ const memoized = memoize(scanOnce, (cwd) => `${cwd}\0${userHome()}\0${installedPluginsMtime()}\0${skillsDirsMtime(cwd)}`);
161
182
  export function scanSkills(cwd, opts) {
162
183
  const all = memoized(cwd);
163
184
  const disabledSkills = opts?.disabledSkills;
164
185
  const disabledPlugins = opts?.disabledPlugins;
186
+ const skillAllowlist = opts?.skillAllowlist;
165
187
  const hasSkillFilter = disabledSkills && disabledSkills.length > 0;
166
188
  const hasPluginFilter = disabledPlugins && disabledPlugins.length > 0;
167
- if (!hasSkillFilter && !hasPluginFilter)
189
+ // An allowlist of [] is meaningful (no skills at all), so check for
190
+ // presence with !== undefined, not truthiness/length.
191
+ const hasAllowlist = skillAllowlist !== undefined;
192
+ if (!hasSkillFilter && !hasPluginFilter && !hasAllowlist)
168
193
  return all;
169
194
  const skillSet = hasSkillFilter ? new Set(disabledSkills) : null;
170
195
  const pluginSet = hasPluginFilter ? new Set(disabledPlugins) : null;
196
+ const allowSet = hasAllowlist ? new Set(skillAllowlist) : null;
171
197
  return all.filter((s) => {
198
+ if (allowSet && !allowSet.has(s.name))
199
+ return false;
172
200
  if (skillSet && skillSet.has(s.name))
173
201
  return false;
174
202
  if (pluginSet) {
@@ -0,0 +1,31 @@
1
+ import type { TranscribeCreds } from "./transcribe.js";
2
+ export interface ResolvedTranscribeProvider {
3
+ creds: TranscribeCreds;
4
+ /** Model id to transcribe with (e.g. gpt-4o-transcribe). */
5
+ model: string;
6
+ }
7
+ export declare function resolveTranscribeProvider(cwd: string, prefer?: string): ResolvedTranscribeProvider | null;
8
+ /** Tool/UI-visibility guard: is voice input usable (some transcribe provider
9
+ * resolvable)? Lets the desktop disable/enable the mic button. */
10
+ export declare function isTranscribeAvailable(cwd: string): boolean;
11
+ /**
12
+ * A renderer-safe description of what voice input will ACTUALLY use right now —
13
+ * so the UI can show "currently using gpt-4o-transcribe, reusing your OpenAI key
14
+ * sk-…1234" instead of looking unconfigured when the fallback is silently in
15
+ * effect. The key is MASKED (never ship the full secret to the renderer for
16
+ * display). `source`:
17
+ * - "connection": an explicit audio modelConnection is configured
18
+ * - "fallback": no audio connection; reusing an OpenAI-family credential
19
+ * - "none": nothing usable — voice input unavailable
20
+ */
21
+ export interface TranscribeDescription {
22
+ source: "connection" | "fallback" | "none";
23
+ model?: string;
24
+ baseUrl?: string;
25
+ /** Masked key for display (e.g. "sk-123...cdef"). */
26
+ maskedKey?: string;
27
+ /** For "fallback": the credential id/catalog whose key is being reused. */
28
+ reusedCredentialId?: string;
29
+ reusedCredentialCatalogId?: string;
30
+ }
31
+ export declare function describeTranscribe(cwd: string): TranscribeDescription;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Resolve which transcription (speech-to-text) provider the desktop voice-input
3
+ * should use, from settings. Mirrors generate-image.ts's resolveImageProvider:
4
+ *
5
+ * 0. Unified store — modelConnections (tag=audio) + credentials, via
6
+ * genInstancesFromConnections. Honors `defaults.audio` / an explicit
7
+ * `prefer` id, else the first usable.
8
+ * 1. Fallback — no audio connection configured: reuse any OpenAI-family
9
+ * credential's key (so a user who only set up OpenAI text/images can
10
+ * dictate immediately with zero extra config). Targets the official
11
+ * OpenAI endpoint + gpt-4o-transcribe.
12
+ *
13
+ * Returns null when nothing usable is configured (or an explicit `prefer` isn't
14
+ * usable — no silent fallback in that case, matching the image resolver).
15
+ */
16
+ import { SettingsManager } from "../settings/manager.js";
17
+ import { getMergedCatalog } from "../model-catalog/index.js";
18
+ import { genInstancesFromConnections } from "../model-catalog/gen-connections.js";
19
+ import { maskKey } from "../onboarding.js";
20
+ /** Catalog ids whose credentials are OpenAI-compatible and carry an OpenAI key
21
+ * reusable for /audio/transcriptions on the official endpoint. */
22
+ const OPENAI_CRED_CATALOG_IDS = new Set(["openai", "openai-images", "openai-transcribe"]);
23
+ const OPENAI_AUDIO_BASE_URL = "https://api.openai.com/v1";
24
+ const OPENAI_DEFAULT_TRANSCRIBE_MODEL = "gpt-4o-transcribe";
25
+ export function resolveTranscribeProvider(cwd, prefer) {
26
+ const settings = new SettingsManager(cwd, "full").get();
27
+ const conns = settings.modelConnections;
28
+ const creds = settings.credentials;
29
+ // 0. Unified store: audio connections.
30
+ if (Array.isArray(conns) && conns.some((c) => c.tag === "audio")) {
31
+ const list = genInstancesFromConnections(conns, (Array.isArray(creds) ? creds : []), getMergedCatalog(), "audio");
32
+ const usable = list.filter((p) => !!p.apiKey && !!p.baseUrl);
33
+ const def = settings.defaults?.audio;
34
+ if (prefer) {
35
+ const chosen = usable.find((p) => p.id === prefer);
36
+ // Explicit request not usable → don't silently fall back.
37
+ if (chosen) {
38
+ return {
39
+ creds: { baseUrl: chosen.baseUrl, apiKey: chosen.apiKey },
40
+ model: chosen.defaultModel || OPENAI_DEFAULT_TRANSCRIBE_MODEL,
41
+ };
42
+ }
43
+ return null;
44
+ }
45
+ const preferred = def ? usable.find((p) => p.id === def) : undefined;
46
+ const chosen = preferred ?? usable[0];
47
+ if (chosen) {
48
+ return {
49
+ creds: { baseUrl: chosen.baseUrl, apiKey: chosen.apiKey },
50
+ model: chosen.defaultModel || OPENAI_DEFAULT_TRANSCRIBE_MODEL,
51
+ };
52
+ }
53
+ // audio connections exist but none usable; if explicit prefer was handled
54
+ // above. Fall through to the credential fallback for the implicit case.
55
+ }
56
+ // 1. Fallback: reuse an OpenAI-family credential key (no audio connection set
57
+ // up yet). Only for the implicit path — an explicit `prefer` that didn't
58
+ // resolve above already returned null.
59
+ if (prefer)
60
+ return null;
61
+ if (Array.isArray(creds)) {
62
+ const openaiCred = creds.find((c) => typeof c.apiKey === "string" && c.apiKey && OPENAI_CRED_CATALOG_IDS.has(c.catalogId ?? ""));
63
+ if (openaiCred?.apiKey) {
64
+ return {
65
+ creds: { baseUrl: OPENAI_AUDIO_BASE_URL, apiKey: openaiCred.apiKey },
66
+ model: OPENAI_DEFAULT_TRANSCRIBE_MODEL,
67
+ };
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ /** Tool/UI-visibility guard: is voice input usable (some transcribe provider
73
+ * resolvable)? Lets the desktop disable/enable the mic button. */
74
+ export function isTranscribeAvailable(cwd) {
75
+ return resolveTranscribeProvider(cwd) !== null;
76
+ }
77
+ export function describeTranscribe(cwd) {
78
+ const settings = new SettingsManager(cwd, "full").get();
79
+ const conns = settings.modelConnections;
80
+ const creds = settings.credentials;
81
+ // A configured audio connection wins (mirror resolveTranscribeProvider's order).
82
+ if (Array.isArray(conns) && conns.some((c) => c.tag === "audio")) {
83
+ const resolved = resolveTranscribeProvider(cwd);
84
+ if (resolved) {
85
+ return {
86
+ source: "connection",
87
+ model: resolved.model,
88
+ baseUrl: resolved.creds.baseUrl,
89
+ maskedKey: maskKey(resolved.creds.apiKey),
90
+ };
91
+ }
92
+ }
93
+ // Fallback: reused OpenAI-family credential.
94
+ if (Array.isArray(creds)) {
95
+ const openaiCred = creds.find((c) => typeof c.apiKey === "string" && c.apiKey && OPENAI_CRED_CATALOG_IDS.has(c.catalogId ?? ""));
96
+ if (openaiCred?.apiKey) {
97
+ return {
98
+ source: "fallback",
99
+ model: OPENAI_DEFAULT_TRANSCRIBE_MODEL,
100
+ baseUrl: OPENAI_AUDIO_BASE_URL,
101
+ maskedKey: maskKey(openaiCred.apiKey),
102
+ reusedCredentialId: openaiCred.id,
103
+ reusedCredentialCatalogId: openaiCred.catalogId,
104
+ };
105
+ }
106
+ }
107
+ return { source: "none" };
108
+ }