@cjhyy/code-shell-core 0.5.0-rc.1 → 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 (528) hide show
  1. package/README.md +13 -10
  2. package/dist/agent/agent-definition-registry.d.ts +21 -3
  3. package/dist/agent/agent-definition-registry.js +49 -18
  4. package/dist/agent/agent-definition.d.ts +32 -0
  5. package/dist/agent/agent-definition.js +49 -4
  6. package/dist/arena/arena.js +11 -12
  7. package/dist/arena/context/context-tools.js +47 -6
  8. package/dist/arena/context/within-root.d.ts +7 -0
  9. package/dist/arena/context/within-root.js +15 -0
  10. package/dist/arena/iterate/phases/argue.js +8 -2
  11. package/dist/arena/iterate/phases/revise.js +1 -1
  12. package/dist/arena/iterate/phases/tournament.js +3 -3
  13. package/dist/arena/ledger.js +9 -1
  14. package/dist/arena/phases/adjudication.js +1 -4
  15. package/dist/arena/phases/build-consensus.js +1 -4
  16. package/dist/arena/phases/cross-review.js +2 -8
  17. package/dist/arena/phases/debate-rounds.js +1 -4
  18. package/dist/arena/phases/participant-research.js +1 -4
  19. package/dist/arena/phases/planning-detail-expansion.js +8 -10
  20. package/dist/arena/planner.js +0 -1
  21. package/dist/arena/providers/docs.d.ts +1 -0
  22. package/dist/arena/providers/docs.js +5 -2
  23. package/dist/arena/providers/repo.d.ts +1 -0
  24. package/dist/arena/providers/repo.js +5 -2
  25. package/dist/arena/strategies/utils.d.ts +1 -4
  26. package/dist/arena/strategies/utils.js +7 -51
  27. package/dist/arena/transitions.d.ts +7 -2
  28. package/dist/arena/transitions.js +9 -4
  29. package/dist/arena/types.d.ts +8 -2
  30. package/dist/automation/cron-expr.d.ts +41 -0
  31. package/dist/automation/cron-expr.js +169 -0
  32. package/dist/automation/index.d.ts +41 -0
  33. package/dist/automation/index.js +39 -0
  34. package/dist/automation/runner.d.ts +84 -0
  35. package/dist/automation/runner.js +92 -0
  36. package/dist/automation/scheduler.d.ts +194 -0
  37. package/dist/automation/scheduler.js +623 -0
  38. package/dist/automation/store.d.ts +39 -0
  39. package/dist/automation/store.js +122 -0
  40. package/dist/automation/write-policy.d.ts +34 -0
  41. package/dist/automation/write-policy.js +113 -0
  42. package/dist/automation/write-run.d.ts +51 -0
  43. package/dist/automation/write-run.js +38 -0
  44. package/dist/capability-control/disabled-lists.d.ts +25 -0
  45. package/dist/capability-control/disabled-lists.js +57 -0
  46. package/dist/capability-control/index.d.ts +5 -0
  47. package/dist/capability-control/index.js +3 -0
  48. package/dist/capability-control/overlay.d.ts +64 -0
  49. package/dist/capability-control/overlay.js +116 -0
  50. package/dist/capability-control/project.d.ts +65 -0
  51. package/dist/capability-control/project.js +147 -0
  52. package/dist/capability-control/service.d.ts +70 -0
  53. package/dist/capability-control/service.js +147 -0
  54. package/dist/capability-control/types.d.ts +62 -0
  55. package/dist/capability-control/types.js +17 -0
  56. package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
  57. package/dist/cc-orchestrator/agent-adapter.js +133 -0
  58. package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
  59. package/dist/cc-orchestrator/cc-capability.js +53 -0
  60. package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
  61. package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
  62. package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
  63. package/dist/cc-orchestrator/codex-session-history.js +187 -0
  64. package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
  65. package/dist/cc-orchestrator/external-agent-changes.js +214 -0
  66. package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
  67. package/dist/cc-orchestrator/external-agent-driver.js +69 -0
  68. package/dist/cc-orchestrator/index.d.ts +8 -0
  69. package/dist/cc-orchestrator/index.js +8 -0
  70. package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
  71. package/dist/cc-orchestrator/relevance-judge.js +29 -0
  72. package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
  73. package/dist/cc-orchestrator/session-discovery.js +125 -0
  74. package/dist/cc-orchestrator/session-history.d.ts +19 -0
  75. package/dist/cc-orchestrator/session-history.js +67 -0
  76. package/dist/cli/agent-server-stdio.d.ts +26 -1
  77. package/dist/cli/agent-server-stdio.js +221 -28
  78. package/dist/cli/agent-server-tcp.d.ts +20 -0
  79. package/dist/cli/agent-server-tcp.js +134 -0
  80. package/dist/cli/graceful-shutdown.d.ts +27 -0
  81. package/dist/cli/graceful-shutdown.js +30 -0
  82. package/dist/context/compaction.d.ts +56 -0
  83. package/dist/context/compaction.js +209 -15
  84. package/dist/context/manager.d.ts +0 -20
  85. package/dist/context/manager.js +25 -41
  86. package/dist/cost-tracker.js +5 -61
  87. package/dist/credentials/cipher.d.ts +49 -0
  88. package/dist/credentials/cipher.js +45 -0
  89. package/dist/credentials/cookie-jar.d.ts +24 -0
  90. package/dist/credentials/cookie-jar.js +40 -0
  91. package/dist/credentials/index.d.ts +7 -0
  92. package/dist/credentials/index.js +5 -0
  93. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  94. package/dist/credentials/inject-credential-tool.js +130 -0
  95. package/dist/credentials/store.d.ts +72 -0
  96. package/dist/credentials/store.js +184 -0
  97. package/dist/credentials/types.d.ts +56 -0
  98. package/dist/credentials/use-credential-tool.d.ts +29 -0
  99. package/dist/credentials/use-credential-tool.js +205 -0
  100. package/dist/credentials/use-gate.d.ts +56 -0
  101. package/dist/credentials/use-gate.js +52 -0
  102. package/dist/cron/cron-runtime.d.ts +2 -0
  103. package/dist/cron/cron-runtime.js +2 -0
  104. package/dist/cron/cron-store.d.ts +2 -0
  105. package/dist/cron/cron-store.js +2 -0
  106. package/dist/cron/scheduler.d.ts +5 -32
  107. package/dist/cron/scheduler.js +5 -113
  108. package/dist/data/model-metadata.d.ts +77 -0
  109. package/dist/data/model-metadata.js +56 -0
  110. package/dist/data/model-metadata.json +216 -0
  111. package/dist/data/openrouter-models.d.ts +18 -7
  112. package/dist/data/openrouter-models.js +35 -8
  113. package/dist/data/openrouter-sync.js +1 -1
  114. package/dist/engine/aux-key.d.ts +10 -0
  115. package/dist/engine/aux-key.js +11 -0
  116. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  117. package/dist/engine/dynamic-tool-defs.js +36 -0
  118. package/dist/engine/engine.d.ts +431 -108
  119. package/dist/engine/engine.js +1630 -279
  120. package/dist/engine/friendly-error.d.ts +18 -0
  121. package/dist/engine/friendly-error.js +63 -0
  122. package/dist/engine/goal.d.ts +187 -0
  123. package/dist/engine/goal.js +196 -0
  124. package/dist/engine/image-compression.d.ts +81 -0
  125. package/dist/engine/image-compression.js +186 -0
  126. package/dist/engine/image-policy.d.ts +165 -0
  127. package/dist/engine/image-policy.js +189 -0
  128. package/dist/engine/model-connections-pool.d.ts +17 -0
  129. package/dist/engine/model-connections-pool.js +66 -0
  130. package/dist/engine/model-facade.d.ts +10 -0
  131. package/dist/engine/model-facade.js +25 -0
  132. package/dist/engine/patch-orphaned-tools.js +3 -0
  133. package/dist/engine/reactive-threshold.d.ts +13 -0
  134. package/dist/engine/reactive-threshold.js +17 -0
  135. package/dist/engine/resolve-llm-config.d.ts +16 -0
  136. package/dist/engine/resolve-llm-config.js +44 -0
  137. package/dist/engine/runtime.js +9 -1
  138. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  139. package/dist/engine/sandbox-cache-key.js +9 -0
  140. package/dist/engine/sandbox-config.d.ts +31 -0
  141. package/dist/engine/sandbox-config.js +38 -0
  142. package/dist/engine/session-title.d.ts +13 -0
  143. package/dist/engine/session-title.js +34 -0
  144. package/dist/engine/session-usage.d.ts +19 -0
  145. package/dist/engine/session-usage.js +25 -0
  146. package/dist/engine/steer-queue.d.ts +32 -0
  147. package/dist/engine/steer-queue.js +26 -0
  148. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  149. package/dist/engine/streaming-tool-queue.js +50 -10
  150. package/dist/engine/turn-loop.d.ts +94 -9
  151. package/dist/engine/turn-loop.js +775 -342
  152. package/dist/engine/types.d.ts +175 -0
  153. package/dist/engine/types.js +13 -0
  154. package/dist/external-agents/config.d.ts +2 -0
  155. package/dist/external-agents/config.js +15 -0
  156. package/dist/external-agents/types.d.ts +31 -0
  157. package/dist/external-agents/types.js +1 -0
  158. package/dist/git/parse-log.d.ts +13 -0
  159. package/dist/git/parse-log.js +21 -0
  160. package/dist/git/utils.d.ts +8 -6
  161. package/dist/git/utils.js +62 -26
  162. package/dist/git/worktree.d.ts +48 -0
  163. package/dist/git/worktree.js +111 -20
  164. package/dist/hooks/events.d.ts +23 -1
  165. package/dist/hooks/goal-stop-hook.d.ts +58 -0
  166. package/dist/hooks/goal-stop-hook.js +279 -0
  167. package/dist/hooks/hook-output.d.ts +33 -0
  168. package/dist/hooks/hook-output.js +79 -0
  169. package/dist/hooks/registry.d.ts +15 -0
  170. package/dist/hooks/registry.js +57 -1
  171. package/dist/hooks/shell-runner.d.ts +2 -0
  172. package/dist/hooks/shell-runner.js +48 -18
  173. package/dist/index.d.ts +79 -11
  174. package/dist/index.js +89 -6
  175. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  176. package/dist/llm/capabilities/param-specs.js +62 -0
  177. package/dist/llm/capabilities/reasoning-control.d.ts +24 -0
  178. package/dist/llm/capabilities/reasoning-control.js +38 -0
  179. package/dist/llm/capabilities/rules.js +37 -3
  180. package/dist/llm/capabilities/types.d.ts +32 -2
  181. package/dist/llm/clamp-max-tokens.d.ts +11 -0
  182. package/dist/llm/clamp-max-tokens.js +17 -0
  183. package/dist/llm/client-base.d.ts +69 -5
  184. package/dist/llm/client-base.js +185 -25
  185. package/dist/llm/client-factory.d.ts +3 -3
  186. package/dist/llm/client-factory.js +2 -2
  187. package/dist/llm/model-cache.js +4 -2
  188. package/dist/llm/model-pool.d.ts +29 -11
  189. package/dist/llm/model-pool.js +36 -20
  190. package/dist/llm/provider-auth.d.ts +41 -0
  191. package/dist/llm/provider-auth.js +76 -0
  192. package/dist/llm/provider-catalog.d.ts +6 -2
  193. package/dist/llm/providers/anthropic.d.ts +32 -2
  194. package/dist/llm/providers/anthropic.js +207 -18
  195. package/dist/llm/providers/openai.d.ts +47 -2
  196. package/dist/llm/providers/openai.js +478 -71
  197. package/dist/llm/reasoning-setting.d.ts +51 -0
  198. package/dist/llm/reasoning-setting.js +40 -0
  199. package/dist/llm/stop-reason.d.ts +13 -0
  200. package/dist/llm/stop-reason.js +21 -0
  201. package/dist/llm/stream-watchdog.js +5 -1
  202. package/dist/llm/strip-vision.d.ts +32 -0
  203. package/dist/llm/strip-vision.js +94 -0
  204. package/dist/llm/token-counter.js +9 -2
  205. package/dist/llm/types.d.ts +9 -6
  206. package/dist/logging/logger.js +18 -4
  207. package/dist/logging/sanitize-messages.d.ts +10 -0
  208. package/dist/logging/sanitize-messages.js +112 -0
  209. package/dist/lsp/client.js +28 -8
  210. package/dist/lsp/manager.d.ts +1 -1
  211. package/dist/lsp/manager.js +42 -11
  212. package/dist/lsp/root-path.d.ts +9 -0
  213. package/dist/lsp/root-path.js +12 -0
  214. package/dist/model-catalog/builtin.d.ts +12 -0
  215. package/dist/model-catalog/builtin.js +407 -0
  216. package/dist/model-catalog/gen-connections.d.ts +20 -0
  217. package/dist/model-catalog/gen-connections.js +28 -0
  218. package/dist/model-catalog/index.d.ts +41 -0
  219. package/dist/model-catalog/index.js +90 -0
  220. package/dist/model-catalog/params.d.ts +20 -0
  221. package/dist/model-catalog/params.js +45 -0
  222. package/dist/model-catalog/resolve.d.ts +48 -0
  223. package/dist/model-catalog/resolve.js +33 -0
  224. package/dist/model-catalog/save-entry.d.ts +32 -0
  225. package/dist/model-catalog/save-entry.js +104 -0
  226. package/dist/model-catalog/types.d.ts +561 -0
  227. package/dist/model-catalog/types.js +93 -0
  228. package/dist/model-catalog/upsert.d.ts +9 -0
  229. package/dist/model-catalog/upsert.js +8 -0
  230. package/dist/onboarding.d.ts +12 -82
  231. package/dist/onboarding.js +75 -333
  232. package/dist/plugins/gitOps.d.ts +53 -0
  233. package/dist/plugins/gitOps.js +130 -5
  234. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  235. package/dist/plugins/installer/checkUpdate.js +32 -0
  236. package/dist/plugins/installer/codex/convertAgents.d.ts +7 -0
  237. package/dist/plugins/installer/codex/convertAgents.js +55 -0
  238. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  239. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  240. package/dist/plugins/installer/codex/convertMcp.d.ts +11 -0
  241. package/dist/plugins/installer/codex/convertMcp.js +85 -0
  242. package/dist/plugins/installer/codex/convertSkills.d.ts +12 -0
  243. package/dist/plugins/installer/codex/convertSkills.js +33 -0
  244. package/dist/plugins/installer/detectFormat.d.ts +2 -0
  245. package/dist/plugins/installer/detectFormat.js +6 -0
  246. package/dist/plugins/installer/install.d.ts +7 -0
  247. package/dist/plugins/installer/install.js +123 -0
  248. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  249. package/dist/plugins/installer/installFromArchive.js +134 -0
  250. package/dist/plugins/installer/installFromSource.d.ts +13 -0
  251. package/dist/plugins/installer/installFromSource.js +51 -0
  252. package/dist/plugins/installer/list.d.ts +9 -0
  253. package/dist/plugins/installer/list.js +30 -0
  254. package/dist/plugins/installer/loadPluginAgents.d.ts +3 -0
  255. package/dist/plugins/installer/loadPluginAgents.js +27 -0
  256. package/dist/plugins/installer/loadPluginMcp.d.ts +14 -0
  257. package/dist/plugins/installer/loadPluginMcp.js +107 -0
  258. package/dist/plugins/installer/parseSource.d.ts +20 -0
  259. package/dist/plugins/installer/parseSource.js +74 -0
  260. package/dist/plugins/installer/paths.d.ts +5 -0
  261. package/dist/plugins/installer/paths.js +25 -0
  262. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  263. package/dist/plugins/installer/pruneDisabled.js +73 -0
  264. package/dist/plugins/installer/types.d.ts +52 -0
  265. package/dist/plugins/installer/types.js +28 -0
  266. package/dist/plugins/installer/uninstall.d.ts +2 -0
  267. package/dist/plugins/installer/uninstall.js +18 -0
  268. package/dist/plugins/installer/unzip.d.ts +14 -0
  269. package/dist/plugins/installer/unzip.js +82 -0
  270. package/dist/plugins/installer/update.d.ts +28 -0
  271. package/dist/plugins/installer/update.js +97 -0
  272. package/dist/plugins/loadPluginHooks.d.ts +54 -1
  273. package/dist/plugins/loadPluginHooks.js +83 -1
  274. package/dist/plugins/marketplaceManager.d.ts +15 -1
  275. package/dist/plugins/marketplaceManager.js +58 -4
  276. package/dist/plugins/pluginCommandHook.js +34 -14
  277. package/dist/plugins/pluginContent.d.ts +30 -0
  278. package/dist/plugins/pluginContent.js +83 -0
  279. package/dist/plugins/pluginInstaller.d.ts +34 -0
  280. package/dist/plugins/pluginInstaller.js +168 -35
  281. package/dist/plugins/schemas.js +41 -6
  282. package/dist/plugins/types.d.ts +10 -0
  283. package/dist/preset/index.d.ts +7 -1
  284. package/dist/preset/index.js +112 -6
  285. package/dist/product/types.d.ts +1 -1
  286. package/dist/prompt/composer.d.ts +31 -0
  287. package/dist/prompt/composer.js +95 -25
  288. package/dist/prompt/instruction-scanner.js +5 -3
  289. package/dist/prompt/section-loader.js +1 -0
  290. package/dist/prompt/sections/base.md +1 -0
  291. package/dist/prompt/sections/browser.md +10 -0
  292. package/dist/prompt/sections/coding.md +4 -0
  293. package/dist/prompt/sections/orchestration.md +8 -0
  294. package/dist/protocol/chat-session-manager.d.ts +15 -2
  295. package/dist/protocol/chat-session-manager.js +46 -0
  296. package/dist/protocol/chat-session.d.ts +82 -0
  297. package/dist/protocol/chat-session.js +121 -1
  298. package/dist/protocol/client.d.ts +27 -0
  299. package/dist/protocol/client.js +38 -0
  300. package/dist/protocol/redact.d.ts +50 -0
  301. package/dist/protocol/redact.js +71 -0
  302. package/dist/protocol/server.d.ts +153 -2
  303. package/dist/protocol/server.js +807 -39
  304. package/dist/protocol/tcp-transport.d.ts +45 -0
  305. package/dist/protocol/tcp-transport.js +74 -0
  306. package/dist/protocol/transport.js +3 -2
  307. package/dist/protocol/types.d.ts +69 -0
  308. package/dist/protocol/types.js +22 -0
  309. package/dist/quota/credentials.d.ts +3 -0
  310. package/dist/quota/credentials.js +80 -0
  311. package/dist/quota/index.d.ts +36 -0
  312. package/dist/quota/index.js +155 -0
  313. package/dist/quota/types.d.ts +48 -0
  314. package/dist/quota/types.js +13 -0
  315. package/dist/remote/bridge.d.ts +11 -2
  316. package/dist/remote/bridge.js +61 -33
  317. package/dist/review/review-prompt.d.ts +28 -0
  318. package/dist/review/review-prompt.js +81 -0
  319. package/dist/run/ArtifactTracker.js +5 -4
  320. package/dist/run/EngineRunner.d.ts +27 -1
  321. package/dist/run/EngineRunner.js +46 -8
  322. package/dist/run/FileRunStore.js +40 -11
  323. package/dist/run/RunApprovalBackend.js +25 -5
  324. package/dist/run/RunLock.d.ts +28 -2
  325. package/dist/run/RunLock.js +49 -7
  326. package/dist/run/RunManager.d.ts +12 -0
  327. package/dist/run/RunManager.js +86 -3
  328. package/dist/run/RunQueue.d.ts +1 -0
  329. package/dist/run/RunQueue.js +8 -2
  330. package/dist/run/factory.d.ts +8 -1
  331. package/dist/run/factory.js +1 -0
  332. package/dist/run/index.d.ts +2 -2
  333. package/dist/run/index.js +1 -1
  334. package/dist/run/redirect-target.d.ts +7 -0
  335. package/dist/run/redirect-target.js +13 -0
  336. package/dist/run/types.js +1 -1
  337. package/dist/runtime/background-shell.d.ts +139 -0
  338. package/dist/runtime/background-shell.js +495 -0
  339. package/dist/runtime/output-clean.d.ts +24 -0
  340. package/dist/runtime/output-clean.js +41 -0
  341. package/dist/runtime/ring-file.d.ts +64 -0
  342. package/dist/runtime/ring-file.js +174 -0
  343. package/dist/runtime/safe-spawn.js +15 -34
  344. package/dist/runtime/spawn-common.d.ts +148 -0
  345. package/dist/runtime/spawn-common.js +303 -0
  346. package/dist/runtime/truncate-output.d.ts +22 -0
  347. package/dist/runtime/truncate-output.js +49 -0
  348. package/dist/runtime/utf8-cut.d.ts +11 -0
  349. package/dist/runtime/utf8-cut.js +23 -0
  350. package/dist/services/auto-dream.d.ts +4 -0
  351. package/dist/services/auto-dream.js +26 -26
  352. package/dist/services/browser-open.d.ts +13 -0
  353. package/dist/services/browser-open.js +16 -0
  354. package/dist/services/diagnostics.d.ts +1 -2
  355. package/dist/services/diagnostics.js +12 -7
  356. package/dist/services/dream-consolidation.d.ts +57 -0
  357. package/dist/services/dream-consolidation.js +151 -0
  358. package/dist/services/extract-memories.d.ts +14 -1
  359. package/dist/services/extract-memories.js +45 -6
  360. package/dist/services/memory-orchestrator.d.ts +21 -0
  361. package/dist/services/memory-orchestrator.js +125 -32
  362. package/dist/services/notifier.d.ts +8 -0
  363. package/dist/services/notifier.js +39 -25
  364. package/dist/services/oauth.js +5 -7
  365. package/dist/services/session-memory-sort.d.ts +8 -0
  366. package/dist/services/session-memory-sort.js +9 -0
  367. package/dist/services/session-memory.js +30 -19
  368. package/dist/session/file-history.d.ts +124 -1
  369. package/dist/session/file-history.js +232 -9
  370. package/dist/session/memory.d.ts +116 -2
  371. package/dist/session/memory.js +250 -28
  372. package/dist/session/session-manager.d.ts +63 -1
  373. package/dist/session/session-manager.js +186 -5
  374. package/dist/session/simple-diff.d.ts +23 -0
  375. package/dist/session/simple-diff.js +84 -0
  376. package/dist/session/transcript.d.ts +25 -1
  377. package/dist/session/transcript.js +35 -2
  378. package/dist/session/undo-target.d.ts +67 -0
  379. package/dist/session/undo-target.js +144 -0
  380. package/dist/settings/disk-defaults.d.ts +42 -0
  381. package/dist/settings/disk-defaults.js +33 -0
  382. package/dist/settings/feature-flags.d.ts +64 -0
  383. package/dist/settings/feature-flags.js +61 -0
  384. package/dist/settings/manager.d.ts +101 -1
  385. package/dist/settings/manager.js +345 -15
  386. package/dist/settings/migrate-config.d.ts +45 -0
  387. package/dist/settings/migrate-config.js +125 -0
  388. package/dist/settings/personalization.d.ts +19 -0
  389. package/dist/settings/personalization.js +7 -0
  390. package/dist/settings/schema-export.d.ts +25 -0
  391. package/dist/settings/schema-export.js +38 -0
  392. package/dist/settings/schema.d.ts +1827 -396
  393. package/dist/settings/schema.js +361 -81
  394. package/dist/skills/scanner.d.ts +9 -0
  395. package/dist/skills/scanner.js +30 -2
  396. package/dist/stt/resolve-transcribe.d.ts +31 -0
  397. package/dist/stt/resolve-transcribe.js +108 -0
  398. package/dist/stt/transcribe.d.ts +51 -0
  399. package/dist/stt/transcribe.js +65 -0
  400. package/dist/tool-system/browser-bridge.d.ts +226 -0
  401. package/dist/tool-system/browser-bridge.js +163 -0
  402. package/dist/tool-system/builtin/add-marketplace.d.ts +12 -0
  403. package/dist/tool-system/builtin/add-marketplace.js +76 -0
  404. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  405. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  406. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  407. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  408. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  409. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  410. package/dist/tool-system/builtin/agent-registry.d.ts +23 -0
  411. package/dist/tool-system/builtin/agent-registry.js +16 -4
  412. package/dist/tool-system/builtin/agent.d.ts +50 -11
  413. package/dist/tool-system/builtin/agent.js +576 -73
  414. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  415. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  416. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  417. package/dist/tool-system/builtin/apply-patch/index.js +7 -3
  418. package/dist/tool-system/builtin/arena.js +6 -7
  419. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  420. package/dist/tool-system/builtin/background-jobs.js +124 -0
  421. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  422. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  423. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  424. package/dist/tool-system/builtin/background-work.js +86 -0
  425. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  426. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  427. package/dist/tool-system/builtin/bash.d.ts +5 -2
  428. package/dist/tool-system/builtin/bash.js +98 -62
  429. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  430. package/dist/tool-system/builtin/browser-tools.js +312 -0
  431. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  432. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  433. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  434. package/dist/tool-system/builtin/check-quota.js +34 -0
  435. package/dist/tool-system/builtin/complete-goal.d.ts +25 -0
  436. package/dist/tool-system/builtin/complete-goal.js +45 -0
  437. package/dist/tool-system/builtin/config.js +7 -0
  438. package/dist/tool-system/builtin/cron.d.ts +7 -0
  439. package/dist/tool-system/builtin/cron.js +105 -9
  440. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  441. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  442. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  443. package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
  444. package/dist/tool-system/builtin/edit.d.ts +2 -1
  445. package/dist/tool-system/builtin/edit.js +21 -12
  446. package/dist/tool-system/builtin/eol.d.ts +29 -0
  447. package/dist/tool-system/builtin/eol.js +37 -0
  448. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  449. package/dist/tool-system/builtin/file-cache.js +8 -0
  450. package/dist/tool-system/builtin/generate-image.d.ts +60 -0
  451. package/dist/tool-system/builtin/generate-image.js +374 -0
  452. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  453. package/dist/tool-system/builtin/generate-video.js +361 -0
  454. package/dist/tool-system/builtin/grep.js +6 -2
  455. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  456. package/dist/tool-system/builtin/image-providers.js +190 -0
  457. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  458. package/dist/tool-system/builtin/image-uploader.js +74 -0
  459. package/dist/tool-system/builtin/index.d.ts +24 -1
  460. package/dist/tool-system/builtin/index.js +310 -25
  461. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  462. package/dist/tool-system/builtin/memory.js +45 -7
  463. package/dist/tool-system/builtin/notebook-edit.d.ts +2 -1
  464. package/dist/tool-system/builtin/notebook-edit.js +1 -1
  465. package/dist/tool-system/builtin/powershell.js +4 -1
  466. package/dist/tool-system/builtin/read.d.ts +2 -1
  467. package/dist/tool-system/builtin/read.js +11 -3
  468. package/dist/tool-system/builtin/repl.js +4 -1
  469. package/dist/tool-system/builtin/skill.js +9 -0
  470. package/dist/tool-system/builtin/sleep.js +12 -5
  471. package/dist/tool-system/builtin/task.js +4 -1
  472. package/dist/tool-system/builtin/tool-search.js +25 -7
  473. package/dist/tool-system/builtin/update-automation-memory.d.ts +24 -0
  474. package/dist/tool-system/builtin/update-automation-memory.js +60 -0
  475. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  476. package/dist/tool-system/builtin/video-providers.js +235 -0
  477. package/dist/tool-system/builtin/view-image.d.ts +18 -0
  478. package/dist/tool-system/builtin/view-image.js +96 -0
  479. package/dist/tool-system/builtin/web-fetch.js +12 -2
  480. package/dist/tool-system/builtin/web-search.d.ts +4 -1
  481. package/dist/tool-system/builtin/web-search.js +57 -10
  482. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  483. package/dist/tool-system/builtin/worktree.js +31 -4
  484. package/dist/tool-system/builtin/write.d.ts +2 -1
  485. package/dist/tool-system/builtin/write.js +1 -1
  486. package/dist/tool-system/context.d.ts +166 -6
  487. package/dist/tool-system/executor.d.ts +3 -2
  488. package/dist/tool-system/executor.js +197 -119
  489. package/dist/tool-system/investigation-guard.d.ts +4 -1
  490. package/dist/tool-system/investigation-guard.js +20 -4
  491. package/dist/tool-system/mcp-manager.d.ts +78 -16
  492. package/dist/tool-system/mcp-manager.js +357 -28
  493. package/dist/tool-system/path-policy.d.ts +99 -0
  494. package/dist/tool-system/path-policy.js +578 -0
  495. package/dist/tool-system/permission.d.ts +36 -1
  496. package/dist/tool-system/permission.js +322 -117
  497. package/dist/tool-system/plan-mode-allowlist.d.ts +32 -0
  498. package/dist/tool-system/plan-mode-allowlist.js +65 -0
  499. package/dist/tool-system/registry.d.ts +1 -0
  500. package/dist/tool-system/registry.js +26 -1
  501. package/dist/tool-system/sandbox/index.d.ts +8 -0
  502. package/dist/tool-system/sandbox/index.js +7 -2
  503. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  504. package/dist/tool-system/validate-tool-metadata.js +63 -0
  505. package/dist/tool-system/validation.d.ts +10 -0
  506. package/dist/tool-system/validation.js +16 -3
  507. package/dist/types.d.ts +301 -15
  508. package/dist/updater.js +20 -9
  509. package/dist/utils/envUtils.d.ts +0 -9
  510. package/dist/utils/envUtils.js +3 -28
  511. package/dist/utils/exec.d.ts +40 -0
  512. package/dist/utils/exec.js +144 -0
  513. package/dist/utils/format.js +4 -2
  514. package/dist/utils/json.d.ts +12 -0
  515. package/dist/utils/json.js +92 -0
  516. package/dist/utils/lockfile.js +9 -2
  517. package/dist/utils/theme.d.ts +7 -1
  518. package/dist/utils/theme.js +5 -3
  519. package/dist/utils/toolDisplay.js +0 -1
  520. package/package.json +14 -7
  521. package/dist/agent/coordinator.d.ts +0 -49
  522. package/dist/agent/coordinator.js +0 -77
  523. package/dist/settings/manager.test.js +0 -73
  524. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  525. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  526. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  527. package/dist/tool-system/builtin/send-message.js +0 -47
  528. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -0,0 +1,25 @@
1
+ import { homedir } from "node:os";
2
+ import { join } from "node:path";
3
+ import { PluginInstallError } from "./types.js";
4
+ function userHome() {
5
+ return process.env.HOME ?? homedir();
6
+ }
7
+ /** A plugin name must be a single safe path segment — no separators, no traversal. */
8
+ export function assertSafePluginName(name) {
9
+ if (!name || name === "." || name === "..") {
10
+ throw new PluginInstallError(`invalid plugin name: ${JSON.stringify(name)}`);
11
+ }
12
+ if (name.includes("/") || name.includes("\\") || name.includes("\0")) {
13
+ throw new PluginInstallError(`plugin name must be a single path segment: ${JSON.stringify(name)}`);
14
+ }
15
+ }
16
+ export function pluginsRoot() {
17
+ return join(userHome(), ".code-shell", "plugins");
18
+ }
19
+ export function pluginInstallDir(name) {
20
+ assertSafePluginName(name);
21
+ return join(pluginsRoot(), name);
22
+ }
23
+ export function pluginMetaPath(name) {
24
+ return join(pluginInstallDir(name), ".cs-meta.json");
25
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Prune a plugin's orphaned entries from a settings object's `disabledSkills`
3
+ * (entries shaped `name:skill`) and `disabledPlugins` (bare `name`). Called on
4
+ * uninstall so a removed plugin leaves no dangling disable flags behind.
5
+ *
6
+ * Pure + immutable: returns a NEW object (shallow clone) with the two arrays
7
+ * replaced by filtered copies. Settings lacking these fields pass through
8
+ * unchanged. A plugin name that is a prefix of another (`mimi-video` vs
9
+ * `mimi-video-pro`) only matches its own exact name / `name:` prefix.
10
+ */
11
+ export interface PrunableSettings {
12
+ disabledSkills?: string[];
13
+ disabledPlugins?: string[];
14
+ [key: string]: unknown;
15
+ }
16
+ export declare function pruneDisabledEntriesForPlugin<T extends PrunableSettings>(settings: T, pluginName: string): T;
17
+ /**
18
+ * Read the user settings.json (under {@link userHome}, so HOME-isolated tests
19
+ * are honored), prune the plugin's orphaned disable entries, and write back —
20
+ * only when something actually changed. Never throws: a missing/corrupt file or
21
+ * any IO error is swallowed (uninstall already succeeded; settings cleanup is
22
+ * best-effort). Atomic write via .tmp + rename mirrors SettingsManager.
23
+ */
24
+ export declare function pruneDisabledSettingsForPlugin(pluginName: string): void;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Prune a plugin's orphaned entries from a settings object's `disabledSkills`
3
+ * (entries shaped `name:skill`) and `disabledPlugins` (bare `name`). Called on
4
+ * uninstall so a removed plugin leaves no dangling disable flags behind.
5
+ *
6
+ * Pure + immutable: returns a NEW object (shallow clone) with the two arrays
7
+ * replaced by filtered copies. Settings lacking these fields pass through
8
+ * unchanged. A plugin name that is a prefix of another (`mimi-video` vs
9
+ * `mimi-video-pro`) only matches its own exact name / `name:` prefix.
10
+ */
11
+ import { writeFileSync, mkdirSync, existsSync, readFileSync, renameSync } from "node:fs";
12
+ import { join, dirname } from "node:path";
13
+ import { homedir } from "node:os";
14
+ /**
15
+ * Resolve the user's home dir, preferring `process.env.HOME` so HOME-isolated
16
+ * tests (and runtime overrides) take effect — same contract as
17
+ * SettingsManager.userHome and installer/paths.ts, without dragging in the
18
+ * settings module's heavier transitive deps.
19
+ */
20
+ function userHome() {
21
+ return process.env.HOME ?? homedir();
22
+ }
23
+ export function pruneDisabledEntriesForPlugin(settings, pluginName) {
24
+ const skillPrefix = `${pluginName}:`;
25
+ const out = { ...settings };
26
+ if (Array.isArray(settings.disabledSkills)) {
27
+ out.disabledSkills = settings.disabledSkills.filter((s) => !s.startsWith(skillPrefix));
28
+ }
29
+ if (Array.isArray(settings.disabledPlugins)) {
30
+ out.disabledPlugins = settings.disabledPlugins.filter((p) => p !== pluginName);
31
+ }
32
+ return out;
33
+ }
34
+ /**
35
+ * Read the user settings.json (under {@link userHome}, so HOME-isolated tests
36
+ * are honored), prune the plugin's orphaned disable entries, and write back —
37
+ * only when something actually changed. Never throws: a missing/corrupt file or
38
+ * any IO error is swallowed (uninstall already succeeded; settings cleanup is
39
+ * best-effort). Atomic write via .tmp + rename mirrors SettingsManager.
40
+ */
41
+ export function pruneDisabledSettingsForPlugin(pluginName) {
42
+ try {
43
+ const path = join(userHome(), ".code-shell", "settings.json");
44
+ if (!existsSync(path))
45
+ return;
46
+ let current;
47
+ try {
48
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
49
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
50
+ return;
51
+ current = parsed;
52
+ }
53
+ catch {
54
+ return; // corrupt file — leave it alone
55
+ }
56
+ const pruned = pruneDisabledEntriesForPlugin(current, pluginName);
57
+ const changed = JSON.stringify(pruned.disabledSkills) !== JSON.stringify(current.disabledSkills) ||
58
+ JSON.stringify(pruned.disabledPlugins) !== JSON.stringify(current.disabledPlugins);
59
+ if (!changed)
60
+ return;
61
+ mkdirSync(dirname(path), { recursive: true });
62
+ const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
63
+ // mode 0o600 — settings.json can hold plaintext API keys, so the pruned
64
+ // rewrite must stay owner-only (matching settings/manager.ts), not fall back
65
+ // to the umask default 0o644 (world-readable). The tmp IS the final file
66
+ // after renameSync, so the mode must be set at create time, not via chmod.
67
+ writeFileSync(tmp, JSON.stringify(pruned, null, 2), { encoding: "utf-8", mode: 0o600 });
68
+ renameSync(tmp, path);
69
+ }
70
+ catch {
71
+ // best-effort cleanup — never fail the uninstall over settings IO
72
+ }
73
+ }
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+ /** Codex `.codex-plugin/plugin.json`. v1 reads required fields; unknowns pass through. */
3
+ export declare const CodexPluginManifest: z.ZodObject<{
4
+ name: z.ZodString;
5
+ version: z.ZodString;
6
+ description: z.ZodOptional<z.ZodString>;
7
+ mcpServers: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
8
+ skills: z.ZodOptional<z.ZodString>;
9
+ agents: z.ZodOptional<z.ZodString>;
10
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
11
+ name: z.ZodString;
12
+ version: z.ZodString;
13
+ description: z.ZodOptional<z.ZodString>;
14
+ mcpServers: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
15
+ skills: z.ZodOptional<z.ZodString>;
16
+ agents: z.ZodOptional<z.ZodString>;
17
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
18
+ name: z.ZodString;
19
+ version: z.ZodString;
20
+ description: z.ZodOptional<z.ZodString>;
21
+ mcpServers: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
22
+ skills: z.ZodOptional<z.ZodString>;
23
+ agents: z.ZodOptional<z.ZodString>;
24
+ }, z.ZodTypeAny, "passthrough">>;
25
+ export type CodexPluginManifest = z.infer<typeof CodexPluginManifest>;
26
+ /** `.cs-meta.json` written into every installed plugin dir. */
27
+ export declare const CSMeta: z.ZodObject<{
28
+ name: z.ZodString;
29
+ format: z.ZodEnum<["cc", "codex"]>;
30
+ version: z.ZodOptional<z.ZodString>;
31
+ source: z.ZodString;
32
+ installedAt: z.ZodString;
33
+ commit: z.ZodOptional<z.ZodString>;
34
+ }, "strip", z.ZodTypeAny, {
35
+ source: string;
36
+ name: string;
37
+ format: "cc" | "codex";
38
+ installedAt: string;
39
+ version?: string | undefined;
40
+ commit?: string | undefined;
41
+ }, {
42
+ source: string;
43
+ name: string;
44
+ format: "cc" | "codex";
45
+ installedAt: string;
46
+ version?: string | undefined;
47
+ commit?: string | undefined;
48
+ }>;
49
+ export type CSMeta = z.infer<typeof CSMeta>;
50
+ export declare class PluginInstallError extends Error {
51
+ constructor(message: string);
52
+ }
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ /** Codex `.codex-plugin/plugin.json`. v1 reads required fields; unknowns pass through. */
3
+ export const CodexPluginManifest = z
4
+ .object({
5
+ name: z.string(),
6
+ version: z.string(),
7
+ description: z.string().optional(),
8
+ // string → relative path to a .mcp.json; object → inline mcpServers map
9
+ mcpServers: z.union([z.string(), z.record(z.any())]).optional(),
10
+ skills: z.string().optional(),
11
+ agents: z.string().optional(),
12
+ })
13
+ .passthrough();
14
+ /** `.cs-meta.json` written into every installed plugin dir. */
15
+ export const CSMeta = z.object({
16
+ name: z.string(),
17
+ format: z.enum(["cc", "codex"]),
18
+ version: z.string().optional(),
19
+ source: z.string(),
20
+ installedAt: z.string(),
21
+ commit: z.string().optional(), // remote (git) source: the HEAD SHA we installed
22
+ });
23
+ export class PluginInstallError extends Error {
24
+ constructor(message) {
25
+ super(message);
26
+ this.name = "PluginInstallError";
27
+ }
28
+ }
@@ -0,0 +1,2 @@
1
+ /** Remove a locally-installed plugin dir + its installed_plugins.json entry. */
2
+ export declare function uninstallPluginByName(name: string): void;
@@ -0,0 +1,18 @@
1
+ import { existsSync, rmSync } from "node:fs";
2
+ import { pluginInstallDir, assertSafePluginName } from "./paths.js";
3
+ import { removeInstallEntries, pluginInstallKey } from "../installedPlugins.js";
4
+ import { PluginInstallError } from "./types.js";
5
+ import { pruneDisabledSettingsForPlugin } from "./pruneDisabled.js";
6
+ /** Remove a locally-installed plugin dir + its installed_plugins.json entry. */
7
+ export function uninstallPluginByName(name) {
8
+ assertSafePluginName(name);
9
+ const dir = pluginInstallDir(name);
10
+ if (!existsSync(dir)) {
11
+ throw new PluginInstallError(`no plugin named '${name}'`);
12
+ }
13
+ rmSync(dir, { recursive: true, force: true });
14
+ removeInstallEntries(pluginInstallKey(name, "local"));
15
+ // Clear orphaned disable flags (disabledSkills "name:skill" /
16
+ // disabledPlugins "name") so a removed plugin leaves no dangling entries.
17
+ pruneDisabledSettingsForPlugin(name);
18
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Reject path traversal ("zip slip"): a malicious archive can carry entries
3
+ * like `../../etc/foo` that escape the extraction root. We normalize and
4
+ * require the resolved path to stay within `destDir`.
5
+ */
6
+ export declare function safeJoin(destDir: string, entryName: string): string;
7
+ /**
8
+ * Extract a .zip into destDir (must already exist). Streams each entry to disk
9
+ * so a large archive doesn't buffer in memory. Directory entries (trailing
10
+ * "/") just create the dir; symlinks and other special entries are skipped —
11
+ * we only materialize regular files and directories, which is all a plugin
12
+ * needs and keeps the surface safe.
13
+ */
14
+ export declare function extractZip(zipPath: string, destDir: string): Promise<void>;
@@ -0,0 +1,82 @@
1
+ import { createRequire } from "node:module";
2
+ import { createWriteStream } from "node:fs";
3
+ import { mkdir } from "node:fs/promises";
4
+ import { dirname, join, normalize, sep } from "node:path";
5
+ import { pipeline } from "node:stream/promises";
6
+ import { PluginInstallError } from "./types.js";
7
+ let _yauzl;
8
+ function yauzl() {
9
+ if (!_yauzl) {
10
+ _yauzl = createRequire(import.meta.url ?? __filename)("yauzl");
11
+ }
12
+ return _yauzl;
13
+ }
14
+ /**
15
+ * Reject path traversal ("zip slip"): a malicious archive can carry entries
16
+ * like `../../etc/foo` that escape the extraction root. We normalize and
17
+ * require the resolved path to stay within `destDir`.
18
+ */
19
+ export function safeJoin(destDir, entryName) {
20
+ // Zip entries always use forward slashes; normalize to the host separator.
21
+ const target = normalize(join(destDir, entryName));
22
+ const root = normalize(destDir.endsWith(sep) ? destDir : destDir + sep);
23
+ if (target !== normalize(destDir) && !target.startsWith(root)) {
24
+ throw new PluginInstallError(`refusing zip entry that escapes target: ${entryName}`);
25
+ }
26
+ return target;
27
+ }
28
+ /**
29
+ * Extract a .zip into destDir (must already exist). Streams each entry to disk
30
+ * so a large archive doesn't buffer in memory. Directory entries (trailing
31
+ * "/") just create the dir; symlinks and other special entries are skipped —
32
+ * we only materialize regular files and directories, which is all a plugin
33
+ * needs and keeps the surface safe.
34
+ */
35
+ export async function extractZip(zipPath, destDir) {
36
+ const zip = await openZip(zipPath);
37
+ try {
38
+ await drainEntries(zip, destDir);
39
+ }
40
+ finally {
41
+ zip.close();
42
+ }
43
+ }
44
+ function openZip(zipPath) {
45
+ return new Promise((resolve, reject) => {
46
+ yauzl().open(zipPath, { lazyEntries: true }, (err, z) => {
47
+ if (err || !z) {
48
+ reject(new PluginInstallError(`cannot open zip: ${err?.message ?? "unknown"}`));
49
+ return;
50
+ }
51
+ resolve(z);
52
+ });
53
+ });
54
+ }
55
+ function drainEntries(zip, destDir) {
56
+ return new Promise((resolve, reject) => {
57
+ zip.on("error", (e) => reject(e));
58
+ zip.on("end", () => resolve());
59
+ zip.on("entry", (entry) => {
60
+ const onErr = (e) => reject(e);
61
+ // Directory entry — yauzl signals these with a trailing slash.
62
+ if (/\/$/.test(entry.fileName)) {
63
+ mkdir(safeJoin(destDir, entry.fileName), { recursive: true })
64
+ .then(() => zip.readEntry())
65
+ .catch(onErr);
66
+ return;
67
+ }
68
+ const outPath = safeJoin(destDir, entry.fileName);
69
+ zip.openReadStream(entry, (err, stream) => {
70
+ if (err || !stream) {
71
+ onErr(new PluginInstallError(`cannot read zip entry ${entry.fileName}: ${err?.message ?? "unknown"}`));
72
+ return;
73
+ }
74
+ mkdir(dirname(outPath), { recursive: true })
75
+ .then(() => pipeline(stream, createWriteStream(outPath)))
76
+ .then(() => zip.readEntry())
77
+ .catch(onErr);
78
+ });
79
+ });
80
+ zip.readEntry();
81
+ });
82
+ }
@@ -0,0 +1,28 @@
1
+ export interface UpdateResult {
2
+ updated: boolean;
3
+ reason: string;
4
+ }
5
+ /**
6
+ * Reinstall a plugin atomically: a failed update leaves the OLD plugin intact.
7
+ *
8
+ * The installers (installPluginFromPath / installPluginFromSource) build into a
9
+ * temp dir then rename into pluginInstallDir(name), and THROW if the final dir
10
+ * already exists. So we must free the final dir *before* installing — we do that
11
+ * by renaming the live dir to a sibling backup. On success we drop the backup;
12
+ * on failure we delete any partial install and rename the backup back.
13
+ *
14
+ * Async fs only — this runs in the Electron main process, so we never block the
15
+ * event loop with sync fs. process.pid (not Date.now(), unavailable here) makes
16
+ * the backup name unique.
17
+ */
18
+ export declare function reinstallAtomic(name: string, source: string, doInstall: () => Promise<unknown>): Promise<void>;
19
+ /**
20
+ * Reinstall a plugin from its recorded source.
21
+ *
22
+ * - Local source: reinstall when the source version changed, or when `force`.
23
+ * CC plugins have no version → only `force` updates them.
24
+ * - Remote (git) source: re-clone and reinstall every time — git sources carry
25
+ * no local version file to compare, so update is always a fresh pull
26
+ * (equivalent to `--force`; cheap and reliable). See spec §9.
27
+ */
28
+ export declare function updatePluginByName(name: string, installedAt: string, force: boolean): Promise<UpdateResult>;
@@ -0,0 +1,97 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { rename, rm } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { detectPluginFormat } from "./detectFormat.js";
5
+ import { pluginInstallDir } from "./paths.js";
6
+ import { installPluginFromPath } from "./install.js";
7
+ import { installPluginFromSource } from "./installFromSource.js";
8
+ import { parseSource } from "./parseSource.js";
9
+ import { pluginInstallKey, readInstalledPlugins, removeInstallEntries, writeInstalledPlugins } from "../installedPlugins.js";
10
+ import { CodexPluginManifest, CSMeta, PluginInstallError } from "./types.js";
11
+ /**
12
+ * Reinstall a plugin atomically: a failed update leaves the OLD plugin intact.
13
+ *
14
+ * The installers (installPluginFromPath / installPluginFromSource) build into a
15
+ * temp dir then rename into pluginInstallDir(name), and THROW if the final dir
16
+ * already exists. So we must free the final dir *before* installing — we do that
17
+ * by renaming the live dir to a sibling backup. On success we drop the backup;
18
+ * on failure we delete any partial install and rename the backup back.
19
+ *
20
+ * Async fs only — this runs in the Electron main process, so we never block the
21
+ * event loop with sync fs. process.pid (not Date.now(), unavailable here) makes
22
+ * the backup name unique.
23
+ */
24
+ export async function reinstallAtomic(name, source, doInstall) {
25
+ const dir = pluginInstallDir(name);
26
+ const backup = `${dir}.bak-${process.pid}`;
27
+ // Capture the existing install_plugins.json entries so a failed reinstall can
28
+ // restore them (uninstall-then-install used to drop them on failure; here the
29
+ // old plugin survives, so its registration must survive too).
30
+ const key = pluginInstallKey(name, "local");
31
+ const savedEntries = readInstalledPlugins().plugins[key];
32
+ await rm(backup, { recursive: true, force: true });
33
+ await rename(dir, backup);
34
+ // The installer re-adds the entry on success; remove the stale one first so a
35
+ // successful reinstall doesn't accumulate a duplicate.
36
+ removeInstallEntries(key);
37
+ try {
38
+ await doInstall();
39
+ }
40
+ catch (err) {
41
+ // Roll back: drop any partial install, restore the old dir + its entries.
42
+ await rm(dir, { recursive: true, force: true });
43
+ await rename(backup, dir);
44
+ if (savedEntries) {
45
+ // Restore in a single read-modify-write rather than one append per entry,
46
+ // which both narrows the race window against any concurrent writer and
47
+ // avoids re-appending onto whatever partial state doInstall() may have
48
+ // left for this key.
49
+ const data = readInstalledPlugins();
50
+ data.plugins[key] = savedEntries;
51
+ writeInstalledPlugins(data);
52
+ }
53
+ throw new PluginInstallError(`update failed; the old version of '${name}' was kept: ` +
54
+ `${err instanceof Error ? err.message : String(err)}. Source: ${source}.`);
55
+ }
56
+ // Success — drop the backup (best-effort; a leftover backup is harmless but
57
+ // we clean it up so it never shows up in the plugins root).
58
+ await rm(backup, { recursive: true, force: true });
59
+ }
60
+ /**
61
+ * Reinstall a plugin from its recorded source.
62
+ *
63
+ * - Local source: reinstall when the source version changed, or when `force`.
64
+ * CC plugins have no version → only `force` updates them.
65
+ * - Remote (git) source: re-clone and reinstall every time — git sources carry
66
+ * no local version file to compare, so update is always a fresh pull
67
+ * (equivalent to `--force`; cheap and reliable). See spec §9.
68
+ */
69
+ export async function updatePluginByName(name, installedAt, force) {
70
+ const dir = pluginInstallDir(name);
71
+ const metaPath = join(dir, ".cs-meta.json");
72
+ if (!existsSync(metaPath))
73
+ throw new PluginInstallError(`no plugin named '${name}'`);
74
+ const meta = CSMeta.parse(JSON.parse(readFileSync(metaPath, "utf-8")));
75
+ const parsed = parseSource(meta.source);
76
+ if (parsed.kind === "remote") {
77
+ // No local version to diff against — always re-clone and reinstall.
78
+ await reinstallAtomic(name, meta.source, () => installPluginFromSource(parsed, name, installedAt));
79
+ return { updated: true, reason: "reinstalled from git source" };
80
+ }
81
+ if (!existsSync(meta.source)) {
82
+ throw new PluginInstallError(`source no longer exists: ${meta.source}`);
83
+ }
84
+ if (!force) {
85
+ if (detectPluginFormat(meta.source) === "codex") {
86
+ const manifest = CodexPluginManifest.parse(JSON.parse(readFileSync(join(meta.source, ".codex-plugin", "plugin.json"), "utf-8")));
87
+ if (manifest.version === meta.version) {
88
+ return { updated: false, reason: "already up to date" };
89
+ }
90
+ }
91
+ else {
92
+ return { updated: false, reason: "CC plugin needs --force to reinstall" };
93
+ }
94
+ }
95
+ await reinstallAtomic(name, meta.source, () => installPluginFromPath(meta.source, name, installedAt));
96
+ return { updated: true, reason: "reinstalled" };
97
+ }
@@ -42,11 +42,64 @@
42
42
  * Errors are swallowed per-plugin: a malformed hooks.json from one plugin
43
43
  * must not block other plugins from loading.
44
44
  */
45
+ import type { HookEventName } from "../hooks/events.js";
45
46
  import type { HookRegistry } from "../hooks/registry.js";
47
+ /**
48
+ * Stable identity for ONE plugin-provided hook, used as the record key in
49
+ * `capabilityOverrides.pluginHooks` (per-hook project off-switch). Derived
50
+ * from content (`plugin:RawEvent:command`) rather than scan order so it
51
+ * survives plugin reinstalls and hooks.json reordering. Two entries that
52
+ * differ only by matcher collide — acceptable: toggling one toggles both,
53
+ * and identical commands on the same event are in practice the same hook.
54
+ */
55
+ export declare function pluginHookKey(hook: {
56
+ plugin: string;
57
+ rawEvent: string;
58
+ command: string;
59
+ }): string;
46
60
  /**
47
61
  * Walk installed plugins and register their command hooks. Safe to call
48
62
  * multiple times — the caller is responsible for not double-registering
49
63
  * (HookRegistry has no de-dup; the engine constructor calls this exactly
50
64
  * once after creating the registry).
65
+ *
66
+ * `disabledPlugins` is the coarse "plugin total switch" — bare plugin names
67
+ * (no `@marketplace`, no `:` suffix), matching scanSkills' semantics. A
68
+ * disabled plugin contributes NO hooks, so e.g. disabling "superpowers"
69
+ * also suppresses its SessionStart injection — not just its Skill-tool
70
+ * entries. Without this, `disabledPlugins` only filtered the skill list and
71
+ * the plugin's hooks still fired regardless.
72
+ *
73
+ * `disabledPluginHooks` is the fine-grained per-hook switch — a list of
74
+ * {@link pluginHookKey} keys (folded from the project's
75
+ * `capabilityOverrides.pluginHooks` by readDisabledLists). A matching hook
76
+ * is skipped while the rest of the plugin keeps working.
77
+ */
78
+ export declare function loadPluginHooks(registry: HookRegistry, disabledPlugins?: string[], disabledPluginHooks?: string[]): void;
79
+ /** A single plugin-provided hook, surfaced read-only to the settings UI. */
80
+ export interface PluginHookEntry {
81
+ /** Source plugin name (bare, no @marketplace). */
82
+ plugin: string;
83
+ /** Mapped codeshell event name. */
84
+ event: HookEventName;
85
+ /** Original CC event name as written in hooks.json (for display). */
86
+ rawEvent: string;
87
+ /** The shell command the hook runs. */
88
+ command: string;
89
+ /** Optional matcher (regex) from the hooks.json group. */
90
+ matcher?: string;
91
+ /** Whether the owning plugin is currently disabled (its hooks don't fire). */
92
+ disabled: boolean;
93
+ /** Stable per-hook identity ({@link pluginHookKey}) — the record key the
94
+ * UI writes to `capabilityOverrides.pluginHooks` to toggle just this hook. */
95
+ key: string;
96
+ }
97
+ /**
98
+ * Read-only counterpart to {@link loadPluginHooks}: scan installed plugins and
99
+ * RETURN their command hooks (instead of registering them), so the settings
100
+ * "钩子" page can show plugin-provided hooks alongside the user's hand-written
101
+ * ones, labelled by owner plugin. `disabledPlugins` doesn't filter the list —
102
+ * disabled plugins are still listed but flagged `disabled:true` (so the UI can
103
+ * show "由 xxx 插件提供(已禁用)"); pass it so that flag is accurate.
51
104
  */
52
- export declare function loadPluginHooks(registry: HookRegistry): void;
105
+ export declare function listPluginHooks(disabledPlugins?: string[]): PluginHookEntry[];
@@ -109,15 +109,42 @@ function pluginNameFromKey(key) {
109
109
  const at = key.lastIndexOf("@");
110
110
  return at > 0 ? key.slice(0, at) : key;
111
111
  }
112
+ /**
113
+ * Stable identity for ONE plugin-provided hook, used as the record key in
114
+ * `capabilityOverrides.pluginHooks` (per-hook project off-switch). Derived
115
+ * from content (`plugin:RawEvent:command`) rather than scan order so it
116
+ * survives plugin reinstalls and hooks.json reordering. Two entries that
117
+ * differ only by matcher collide — acceptable: toggling one toggles both,
118
+ * and identical commands on the same event are in practice the same hook.
119
+ */
120
+ export function pluginHookKey(hook) {
121
+ return `${hook.plugin}:${hook.rawEvent}:${hook.command}`;
122
+ }
112
123
  /**
113
124
  * Walk installed plugins and register their command hooks. Safe to call
114
125
  * multiple times — the caller is responsible for not double-registering
115
126
  * (HookRegistry has no de-dup; the engine constructor calls this exactly
116
127
  * once after creating the registry).
128
+ *
129
+ * `disabledPlugins` is the coarse "plugin total switch" — bare plugin names
130
+ * (no `@marketplace`, no `:` suffix), matching scanSkills' semantics. A
131
+ * disabled plugin contributes NO hooks, so e.g. disabling "superpowers"
132
+ * also suppresses its SessionStart injection — not just its Skill-tool
133
+ * entries. Without this, `disabledPlugins` only filtered the skill list and
134
+ * the plugin's hooks still fired regardless.
135
+ *
136
+ * `disabledPluginHooks` is the fine-grained per-hook switch — a list of
137
+ * {@link pluginHookKey} keys (folded from the project's
138
+ * `capabilityOverrides.pluginHooks` by readDisabledLists). A matching hook
139
+ * is skipped while the rest of the plugin keeps working.
117
140
  */
118
- export function loadPluginHooks(registry) {
141
+ export function loadPluginHooks(registry, disabledPlugins = [], disabledPluginHooks = []) {
119
142
  const data = readInstalledPlugins();
143
+ const disabledSet = new Set(disabledPlugins);
144
+ const disabledHookSet = new Set(disabledPluginHooks);
120
145
  for (const [key, entries] of Object.entries(data.plugins)) {
146
+ if (disabledSet.has(pluginNameFromKey(key)))
147
+ continue;
121
148
  for (const entry of entries) {
122
149
  const installPath = entry.installPath;
123
150
  if (!installPath || !existsSync(installPath))
@@ -140,6 +167,13 @@ export function loadPluginHooks(registry) {
140
167
  if (cmd.type !== "command" || typeof cmd.command !== "string") {
141
168
  continue;
142
169
  }
170
+ if (disabledHookSet.has(pluginHookKey({
171
+ plugin: pluginNameFromKey(key),
172
+ rawEvent: eventNameRaw,
173
+ command: cmd.command,
174
+ }))) {
175
+ continue;
176
+ }
143
177
  const commandLine = cmd.command;
144
178
  const timeoutMs = cmd.timeout_ms;
145
179
  const matcher = group.matcher;
@@ -160,3 +194,51 @@ export function loadPluginHooks(registry) {
160
194
  }
161
195
  }
162
196
  }
197
+ /**
198
+ * Read-only counterpart to {@link loadPluginHooks}: scan installed plugins and
199
+ * RETURN their command hooks (instead of registering them), so the settings
200
+ * "钩子" page can show plugin-provided hooks alongside the user's hand-written
201
+ * ones, labelled by owner plugin. `disabledPlugins` doesn't filter the list —
202
+ * disabled plugins are still listed but flagged `disabled:true` (so the UI can
203
+ * show "由 xxx 插件提供(已禁用)"); pass it so that flag is accurate.
204
+ */
205
+ export function listPluginHooks(disabledPlugins = []) {
206
+ const data = readInstalledPlugins();
207
+ const disabledSet = new Set(disabledPlugins);
208
+ const out = [];
209
+ for (const [key, entries] of Object.entries(data.plugins)) {
210
+ const plugin = pluginNameFromKey(key);
211
+ const disabled = disabledSet.has(plugin);
212
+ for (const entry of entries) {
213
+ const installPath = entry.installPath;
214
+ if (!installPath || !existsSync(installPath))
215
+ continue;
216
+ const raw = readHooksJson(installPath);
217
+ if (!raw?.hooks)
218
+ continue;
219
+ for (const [eventNameRaw, groups] of Object.entries(raw.hooks)) {
220
+ const mapped = EVENT_NAME_MAP[eventNameRaw];
221
+ if (mapped === null || mapped === undefined)
222
+ continue;
223
+ if (!Array.isArray(groups))
224
+ continue;
225
+ for (const group of groups) {
226
+ for (const cmd of group.hooks ?? []) {
227
+ if (cmd.type !== "command" || typeof cmd.command !== "string")
228
+ continue;
229
+ out.push({
230
+ plugin,
231
+ event: mapped,
232
+ rawEvent: eventNameRaw,
233
+ command: cmd.command,
234
+ matcher: group.matcher,
235
+ disabled,
236
+ key: pluginHookKey({ plugin, rawEvent: eventNameRaw, command: cmd.command }),
237
+ });
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+ return out;
244
+ }