@cjhyy/code-shell-core 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (621) hide show
  1. package/README.md +36 -23
  2. package/dist/agent/agent-definition-registry.d.ts +2 -2
  3. package/dist/agent/agent-definition-registry.js +47 -10
  4. package/dist/agent/agent-definition.d.ts +5 -0
  5. package/dist/agent/agent-definition.js +14 -0
  6. package/dist/automation/index.d.ts +7 -4
  7. package/dist/automation/index.js +4 -2
  8. package/dist/automation/runner.js +3 -1
  9. package/dist/automation/scheduler.d.ts +57 -1
  10. package/dist/automation/scheduler.js +123 -23
  11. package/dist/automation/store.d.ts +6 -2
  12. package/dist/automation/store.js +7 -3
  13. package/dist/capabilities/index.d.ts +109 -0
  14. package/dist/capabilities/index.js +80 -0
  15. package/dist/capability-control/disabled-lists.d.ts +2 -1
  16. package/dist/capability-control/disabled-lists.js +3 -5
  17. package/dist/capability-control/overlay.d.ts +14 -1
  18. package/dist/capability-control/overlay.js +40 -0
  19. package/dist/capability-control/service.js +6 -4
  20. package/dist/cli/agent-server-stdio.d.ts +1 -1
  21. package/dist/cli/agent-server-stdio.js +66 -6
  22. package/dist/cli/agent-server-tcp.js +20 -5
  23. package/dist/context/compaction.d.ts +39 -3
  24. package/dist/context/compaction.js +151 -39
  25. package/dist/context/manager.d.ts +20 -4
  26. package/dist/context/manager.js +42 -7
  27. package/dist/context/token-counter.js +5 -3
  28. package/dist/context/tool-result-storage.d.ts +6 -0
  29. package/dist/context/tool-result-storage.js +25 -4
  30. package/dist/credentials/access.d.ts +13 -2
  31. package/dist/credentials/access.js +99 -4
  32. package/dist/credentials/index.d.ts +3 -2
  33. package/dist/credentials/index.js +2 -1
  34. package/dist/credentials/oauth.d.ts +9 -1
  35. package/dist/credentials/oauth.js +80 -1
  36. package/dist/credentials/store.d.ts +16 -2
  37. package/dist/credentials/store.js +33 -11
  38. package/dist/credentials/types.d.ts +62 -1
  39. package/dist/credentials/types.js +16 -1
  40. package/dist/credentials/use-credential-tool.js +15 -1
  41. package/dist/engine/auxiliary-pipeline.d.ts +40 -0
  42. package/dist/engine/auxiliary-pipeline.js +181 -0
  43. package/dist/{settings → engine}/disk-defaults.d.ts +2 -2
  44. package/dist/{settings → engine}/disk-defaults.js +5 -2
  45. package/dist/engine/dynamic-tool-defs.d.ts +4 -0
  46. package/dist/engine/dynamic-tool-defs.js +4 -0
  47. package/dist/engine/engine.d.ts +272 -184
  48. package/dist/engine/engine.js +1869 -1864
  49. package/dist/engine/file-history-hook.d.ts +11 -0
  50. package/dist/engine/file-history-hook.js +31 -0
  51. package/dist/engine/goal-judge-context.d.ts +9 -0
  52. package/dist/engine/goal-judge-context.js +234 -0
  53. package/dist/engine/injected-context-cache.d.ts +6 -0
  54. package/dist/engine/injected-context-cache.js +13 -0
  55. package/dist/engine/input-attachments.d.ts +1 -1
  56. package/dist/engine/model-facade.d.ts +3 -3
  57. package/dist/engine/model-facade.js +15 -14
  58. package/dist/engine/permission-controller.d.ts +55 -0
  59. package/dist/engine/permission-controller.js +148 -0
  60. package/dist/engine/prompt-cache-diagnostics.d.ts +58 -0
  61. package/dist/engine/prompt-cache-diagnostics.js +178 -0
  62. package/dist/engine/run-accounting.d.ts +41 -0
  63. package/dist/engine/run-accounting.js +126 -0
  64. package/dist/engine/run-context.d.ts +44 -0
  65. package/dist/engine/run-context.js +88 -0
  66. package/dist/engine/run-environment.d.ts +30 -0
  67. package/dist/engine/run-environment.js +77 -0
  68. package/dist/engine/run-finalize.d.ts +58 -0
  69. package/dist/engine/run-finalize.js +245 -0
  70. package/dist/engine/run-goal.d.ts +58 -0
  71. package/dist/engine/run-goal.js +188 -0
  72. package/dist/engine/run-image-input.d.ts +1 -1
  73. package/dist/engine/run-image-input.js +5 -3
  74. package/dist/engine/run-session-open.d.ts +41 -0
  75. package/dist/engine/run-session-open.js +186 -0
  76. package/dist/engine/run-setup.d.ts +42 -0
  77. package/dist/engine/run-setup.js +58 -0
  78. package/dist/engine/run-tooling.d.ts +125 -0
  79. package/dist/engine/run-tooling.js +283 -0
  80. package/dist/engine/run-types.d.ts +139 -0
  81. package/dist/engine/run-types.js +12 -0
  82. package/dist/engine/run-workspace.d.ts +50 -0
  83. package/dist/engine/run-workspace.js +114 -0
  84. package/dist/engine/session-title.d.ts +2 -1
  85. package/dist/engine/session-title.js +4 -1
  86. package/dist/engine/steer-queue.d.ts +1 -1
  87. package/dist/engine/subagent-spawner.d.ts +32 -0
  88. package/dist/engine/subagent-spawner.js +287 -0
  89. package/dist/engine/tool-summary.d.ts +2 -2
  90. package/dist/engine/tool-summary.js +2 -2
  91. package/dist/engine/turn-loop.d.ts +67 -10
  92. package/dist/engine/turn-loop.js +538 -97
  93. package/dist/engine/types.d.ts +35 -4
  94. package/dist/engine/types.js +1 -1
  95. package/dist/{engine/goal.d.ts → goal/lifecycle.d.ts} +80 -6
  96. package/dist/goal/lifecycle.js +482 -0
  97. package/dist/hooks/events.d.ts +26 -9
  98. package/dist/hooks/events.js +0 -3
  99. package/dist/hooks/goal-stop-hook.d.ts +28 -29
  100. package/dist/hooks/goal-stop-hook.js +344 -144
  101. package/dist/hooks/registry.js +4 -1
  102. package/dist/hooks/shell-runner.d.ts +12 -1
  103. package/dist/hooks/shell-runner.js +160 -9
  104. package/dist/index.d.ts +51 -110
  105. package/dist/index.extension.d.ts +51 -0
  106. package/dist/index.extension.js +39 -0
  107. package/dist/index.internal.d.ts +86 -0
  108. package/dist/index.internal.js +92 -0
  109. package/dist/index.js +37 -125
  110. package/dist/links/cli.d.ts +48 -0
  111. package/dist/links/cli.js +617 -0
  112. package/dist/links/http.d.ts +40 -0
  113. package/dist/links/http.js +166 -0
  114. package/dist/links/index.d.ts +4 -0
  115. package/dist/links/index.js +3 -0
  116. package/dist/links/link-action-tool.d.ts +5 -0
  117. package/dist/links/link-action-tool.js +241 -0
  118. package/dist/links/providers.d.ts +8 -0
  119. package/dist/links/providers.js +665 -0
  120. package/dist/links/types.d.ts +44 -0
  121. package/dist/llm/client-base.d.ts +7 -0
  122. package/dist/llm/client-base.js +72 -10
  123. package/dist/llm/model-pool.d.ts +1 -1
  124. package/dist/llm/model-pool.js +1 -1
  125. package/dist/llm/providers/anthropic.d.ts +1 -0
  126. package/dist/llm/providers/anthropic.js +9 -0
  127. package/dist/llm/providers/openai.d.ts +1 -0
  128. package/dist/llm/providers/openai.js +17 -0
  129. package/dist/llm/types.d.ts +12 -5
  130. package/dist/model-catalog/index.js +15 -2
  131. package/dist/model-catalog/resolve.d.ts +13 -1
  132. package/dist/model-catalog/resolve.js +37 -2
  133. package/dist/model-catalog/types.d.ts +74 -48
  134. package/dist/model-catalog/types.js +16 -5
  135. package/dist/model-catalog/upsert.d.ts +3 -1
  136. package/dist/model-catalog/upsert.js +9 -0
  137. package/dist/onboarding.d.ts +0 -1
  138. package/dist/onboarding.js +1 -22
  139. package/dist/panel-apps/bindings.d.ts +24 -0
  140. package/dist/panel-apps/bindings.js +69 -0
  141. package/dist/panel-apps/github-archive.d.ts +21 -0
  142. package/dist/panel-apps/github-archive.js +98 -0
  143. package/dist/panel-apps/index.d.ts +4 -0
  144. package/dist/panel-apps/index.js +4 -0
  145. package/dist/panel-apps/installer.d.ts +68 -0
  146. package/dist/panel-apps/installer.js +622 -0
  147. package/dist/panel-apps/manifest.d.ts +364 -0
  148. package/dist/panel-apps/manifest.js +189 -0
  149. package/dist/panel-apps/paths.d.ts +13 -0
  150. package/dist/panel-apps/paths.js +38 -0
  151. package/dist/panel-apps/registry.d.ts +51 -0
  152. package/dist/panel-apps/registry.js +99 -0
  153. package/dist/panel-apps/runtime.d.ts +80 -0
  154. package/dist/panel-apps/runtime.js +154 -0
  155. package/dist/plugins/gitOps.js +8 -1
  156. package/dist/plugins/installedPlugins.d.ts +2 -1
  157. package/dist/plugins/installedPlugins.js +146 -8
  158. package/dist/plugins/installer/codex/convertAgents.d.ts +4 -1
  159. package/dist/plugins/installer/codex/convertAgents.js +62 -8
  160. package/dist/plugins/installer/codex/convertCommands.d.ts +5 -5
  161. package/dist/plugins/installer/codex/convertCommands.js +35 -12
  162. package/dist/plugins/installer/codex/convertHooks.d.ts +10 -0
  163. package/dist/plugins/installer/codex/convertHooks.js +82 -0
  164. package/dist/plugins/installer/codex/convertSkills.js +41 -6
  165. package/dist/plugins/installer/install.d.ts +7 -1
  166. package/dist/plugins/installer/install.js +21 -87
  167. package/dist/plugins/installer/installFromArchive.d.ts +26 -4
  168. package/dist/plugins/installer/installFromArchive.js +44 -27
  169. package/dist/plugins/installer/installFromNpm.d.ts +31 -0
  170. package/dist/plugins/installer/installFromNpm.js +273 -0
  171. package/dist/plugins/installer/loadPluginAgents.js +17 -4
  172. package/dist/plugins/installer/loadPluginMcp.d.ts +14 -0
  173. package/dist/plugins/installer/loadPluginMcp.js +245 -35
  174. package/dist/plugins/installer/normalizeManifest.d.ts +13 -0
  175. package/dist/plugins/installer/normalizeManifest.js +306 -0
  176. package/dist/plugins/installer/npmTar.d.ts +13 -0
  177. package/dist/plugins/installer/npmTar.js +321 -0
  178. package/dist/plugins/installer/parseSource.d.ts +11 -0
  179. package/dist/plugins/installer/parseSource.js +48 -0
  180. package/dist/plugins/installer/preview.d.ts +101 -0
  181. package/dist/plugins/installer/preview.js +336 -0
  182. package/dist/plugins/installer/projectPluginSource.d.ts +14 -0
  183. package/dist/plugins/installer/projectPluginSource.js +140 -0
  184. package/dist/plugins/installer/types.d.ts +775 -0
  185. package/dist/plugins/installer/types.js +100 -0
  186. package/dist/plugins/installer/unzip.d.ts +11 -0
  187. package/dist/plugins/installer/unzip.js +123 -9
  188. package/dist/plugins/installer/update.d.ts +2 -2
  189. package/dist/plugins/installer/update.js +43 -4
  190. package/dist/plugins/loadPluginHooks.d.ts +19 -2
  191. package/dist/plugins/loadPluginHooks.js +97 -86
  192. package/dist/plugins/pluginAutomationTemplates.d.ts +18 -0
  193. package/dist/plugins/pluginAutomationTemplates.js +50 -0
  194. package/dist/plugins/pluginCatalog.d.ts +45 -0
  195. package/dist/plugins/pluginCatalog.js +87 -0
  196. package/dist/plugins/pluginCommandHook.d.ts +10 -4
  197. package/dist/plugins/pluginCommandHook.js +133 -18
  198. package/dist/plugins/pluginCommandsLoader.d.ts +19 -0
  199. package/dist/plugins/pluginCommandsLoader.js +181 -7
  200. package/dist/plugins/pluginContent.d.ts +10 -1
  201. package/dist/plugins/pluginContent.js +87 -30
  202. package/dist/plugins/pluginHookApproval.d.ts +30 -0
  203. package/dist/plugins/pluginHookApproval.js +160 -0
  204. package/dist/plugins/pluginHookIntegrity.d.ts +69 -0
  205. package/dist/plugins/pluginHookIntegrity.js +361 -0
  206. package/dist/plugins/pluginInstaller.js +71 -12
  207. package/dist/plugins/pluginMcpApproval.d.ts +19 -0
  208. package/dist/plugins/pluginMcpApproval.js +110 -0
  209. package/dist/plugins/pluginMcpIntegrity.d.ts +21 -0
  210. package/dist/plugins/pluginMcpIntegrity.js +74 -0
  211. package/dist/plugins/types.d.ts +30 -0
  212. package/dist/plugins/varRewrite.d.ts +9 -5
  213. package/dist/plugins/varRewrite.js +26 -17
  214. package/dist/preset/index.d.ts +11 -8
  215. package/dist/preset/index.js +62 -203
  216. package/dist/product/define.js +9 -3
  217. package/dist/product/types.d.ts +0 -2
  218. package/dist/profile/activation.d.ts +36 -0
  219. package/dist/profile/activation.js +57 -0
  220. package/dist/profile/catalog-store.d.ts +77 -0
  221. package/dist/profile/catalog-store.js +346 -0
  222. package/dist/profile/catalog.d.ts +54 -0
  223. package/dist/profile/catalog.js +152 -0
  224. package/dist/profile/index.d.ts +7 -0
  225. package/dist/profile/index.js +7 -0
  226. package/dist/profile/requirements.d.ts +76 -0
  227. package/dist/profile/requirements.js +117 -0
  228. package/dist/profile/resolve.d.ts +11 -0
  229. package/dist/profile/resolve.js +41 -0
  230. package/dist/profile/store.d.ts +17 -0
  231. package/dist/profile/store.js +167 -0
  232. package/dist/profile/types.d.ts +321 -0
  233. package/dist/profile/types.js +104 -0
  234. package/dist/prompt/composer.d.ts +46 -7
  235. package/dist/prompt/composer.js +78 -48
  236. package/dist/prompt/instruction-scanner.d.ts +6 -5
  237. package/dist/prompt/instruction-scanner.js +8 -23
  238. package/dist/prompt/section-loader.d.ts +2 -2
  239. package/dist/prompt/section-loader.js +7 -4
  240. package/dist/prompt/sections/browser.md +10 -9
  241. package/dist/prompt/sections/harness-base.md +9 -0
  242. package/dist/protocol/chat-session-manager.d.ts +77 -3
  243. package/dist/protocol/chat-session-manager.js +194 -18
  244. package/dist/protocol/chat-session.d.ts +72 -9
  245. package/dist/protocol/chat-session.js +151 -16
  246. package/dist/protocol/client.d.ts +37 -4
  247. package/dist/protocol/client.js +118 -6
  248. package/dist/protocol/index.d.ts +2 -2
  249. package/dist/protocol/index.js +2 -2
  250. package/dist/protocol/mobile-remote-types.d.ts +406 -0
  251. package/dist/protocol/mobile-remote-types.js +1 -0
  252. package/dist/protocol/server.d.ts +152 -14
  253. package/dist/protocol/server.js +1574 -229
  254. package/dist/protocol/types.d.ts +182 -32
  255. package/dist/protocol/types.js +18 -0
  256. package/dist/run/ArtifactTracker.d.ts +6 -1
  257. package/dist/run/ArtifactTracker.js +29 -21
  258. package/dist/run/EngineRunner.d.ts +2 -0
  259. package/dist/run/EngineRunner.js +1 -0
  260. package/dist/run/RunManager.d.ts +26 -0
  261. package/dist/run/RunManager.js +82 -11
  262. package/dist/run/factory.d.ts +3 -0
  263. package/dist/run/factory.js +2 -0
  264. package/dist/runtime/safe-spawn.d.ts +6 -0
  265. package/dist/runtime/safe-spawn.js +8 -13
  266. package/dist/services/auto-dream.d.ts +13 -1
  267. package/dist/services/auto-dream.js +56 -8
  268. package/dist/services/dream-consolidation.d.ts +3 -0
  269. package/dist/services/dream-consolidation.js +14 -2
  270. package/dist/services/index.d.ts +1 -1
  271. package/dist/services/index.js +1 -1
  272. package/dist/services/memory-orchestrator.js +6 -2
  273. package/dist/services/oauth.d.ts +34 -10
  274. package/dist/services/oauth.js +236 -98
  275. package/dist/services/session-memory.d.ts +4 -4
  276. package/dist/services/session-memory.js +13 -10
  277. package/dist/session/memory.d.ts +26 -7
  278. package/dist/session/memory.js +79 -21
  279. package/dist/session/session-manager.d.ts +208 -25
  280. package/dist/session/session-manager.js +1232 -116
  281. package/dist/session/session-message.d.ts +22 -0
  282. package/dist/session/session-message.js +1 -0
  283. package/dist/session/transcript.d.ts +76 -6
  284. package/dist/session/transcript.js +278 -7
  285. package/dist/settings/feature-flags.d.ts +40 -0
  286. package/dist/settings/feature-flags.js +40 -0
  287. package/dist/settings/manager.d.ts +39 -1
  288. package/dist/settings/manager.js +102 -41
  289. package/dist/settings/migrate-config.js +4 -2
  290. package/dist/settings/schema.d.ts +511 -177
  291. package/dist/settings/schema.js +98 -25
  292. package/dist/skills/scanner.d.ts +6 -2
  293. package/dist/skills/scanner.js +160 -9
  294. package/dist/sources/adapter.d.ts +14 -0
  295. package/dist/sources/adapter.js +7 -0
  296. package/dist/sources/adapters/local-files.d.ts +10 -0
  297. package/dist/sources/adapters/local-files.js +127 -0
  298. package/dist/sources/adapters/mcp-resource.d.ts +17 -0
  299. package/dist/sources/adapters/mcp-resource.js +41 -0
  300. package/dist/sources/adapters/mock.d.ts +3 -0
  301. package/dist/sources/adapters/mock.js +29 -0
  302. package/dist/sources/binding.d.ts +6 -0
  303. package/dist/sources/binding.js +24 -0
  304. package/dist/sources/catalog.d.ts +6 -0
  305. package/dist/sources/catalog.js +64 -0
  306. package/dist/sources/context-summary.d.ts +8 -0
  307. package/dist/sources/context-summary.js +13 -0
  308. package/dist/sources/credential-status.d.ts +2 -0
  309. package/dist/sources/credential-status.js +13 -0
  310. package/dist/sources/index.d.ts +10 -0
  311. package/dist/sources/index.js +10 -0
  312. package/dist/sources/resolve.d.ts +28 -0
  313. package/dist/sources/resolve.js +47 -0
  314. package/dist/sources/truncate-utf8.d.ts +7 -0
  315. package/dist/sources/truncate-utf8.js +18 -0
  316. package/dist/sources/types.d.ts +71 -0
  317. package/dist/sources/types.js +26 -0
  318. package/dist/testing/fetch-stub.d.ts +32 -0
  319. package/dist/testing/fetch-stub.js +24 -0
  320. package/dist/themes/image.d.ts +18 -0
  321. package/dist/themes/image.js +117 -0
  322. package/dist/themes/index.d.ts +4 -0
  323. package/dist/themes/index.js +4 -0
  324. package/dist/themes/installer.d.ts +50 -0
  325. package/dist/themes/installer.js +290 -0
  326. package/dist/themes/manifest.d.ts +102 -0
  327. package/dist/themes/manifest.js +86 -0
  328. package/dist/themes/paths.d.ts +14 -0
  329. package/dist/themes/paths.js +33 -0
  330. package/dist/tool-system/browser-bridge.d.ts +53 -11
  331. package/dist/tool-system/browser-bridge.js +8 -9
  332. package/dist/tool-system/builtin/agent-heartbeat.d.ts +2 -2
  333. package/dist/tool-system/builtin/agent-heartbeat.js +20 -6
  334. package/dist/tool-system/builtin/agent-notifications.d.ts +127 -72
  335. package/dist/tool-system/builtin/agent-notifications.js +291 -101
  336. package/dist/tool-system/builtin/agent-output-file.js +1 -3
  337. package/dist/tool-system/builtin/agent-progress.d.ts +6 -0
  338. package/dist/tool-system/builtin/agent-progress.js +83 -0
  339. package/dist/tool-system/builtin/agent-registry.d.ts +38 -2
  340. package/dist/tool-system/builtin/agent-registry.js +178 -9
  341. package/dist/tool-system/builtin/agent-transcript-translator.js +1 -1
  342. package/dist/tool-system/builtin/agent.d.ts +2 -0
  343. package/dist/tool-system/builtin/agent.js +279 -34
  344. package/dist/tool-system/builtin/background-jobs.d.ts +63 -7
  345. package/dist/tool-system/builtin/background-jobs.js +111 -15
  346. package/dist/tool-system/builtin/background-work.d.ts +12 -1
  347. package/dist/tool-system/builtin/background-work.js +12 -1
  348. package/dist/tool-system/builtin/bash.d.ts +3 -5
  349. package/dist/tool-system/builtin/bash.js +14 -6
  350. package/dist/tool-system/builtin/browser-tools.d.ts +8 -5
  351. package/dist/tool-system/builtin/browser-tools.js +89 -23
  352. package/dist/tool-system/builtin/edit-model-catalog.d.ts +6 -0
  353. package/dist/tool-system/builtin/edit-model-catalog.js +172 -12
  354. package/dist/tool-system/builtin/edit.d.ts +2 -1
  355. package/dist/tool-system/builtin/edit.js +14 -10
  356. package/dist/tool-system/builtin/file-cache.d.ts +2 -0
  357. package/dist/tool-system/builtin/file-cache.js +4 -0
  358. package/dist/tool-system/builtin/generate-image.js +17 -10
  359. package/dist/tool-system/builtin/generate-video.d.ts +4 -0
  360. package/dist/tool-system/builtin/generate-video.js +164 -28
  361. package/dist/tool-system/builtin/glob.d.ts +2 -1
  362. package/dist/tool-system/builtin/glob.js +28 -3
  363. package/dist/tool-system/builtin/grep.d.ts +1 -0
  364. package/dist/tool-system/builtin/grep.js +82 -17
  365. package/dist/tool-system/builtin/image-uploader.js +7 -1
  366. package/dist/tool-system/builtin/index.d.ts +57 -18
  367. package/dist/tool-system/builtin/index.js +280 -167
  368. package/dist/tool-system/builtin/memory.d.ts +6 -0
  369. package/dist/tool-system/builtin/memory.js +36 -15
  370. package/dist/tool-system/builtin/panel.d.ts +9 -0
  371. package/dist/tool-system/builtin/panel.js +314 -0
  372. package/dist/tool-system/builtin/read.js +5 -1
  373. package/dist/tool-system/builtin/send-message-to-session.d.ts +6 -0
  374. package/dist/tool-system/builtin/send-message-to-session.js +67 -0
  375. package/dist/tool-system/builtin/sources.d.ts +8 -0
  376. package/dist/tool-system/builtin/sources.js +137 -0
  377. package/dist/tool-system/builtin/tool-search.js +7 -2
  378. package/dist/tool-system/builtin/update-automation-memory.js +2 -0
  379. package/dist/tool-system/builtin/video-providers.d.ts +12 -15
  380. package/dist/tool-system/builtin/video-providers.js +1 -0
  381. package/dist/tool-system/builtin/view-image.d.ts +2 -2
  382. package/dist/tool-system/builtin/web-fetch.js +60 -15
  383. package/dist/tool-system/builtin/web-search.js +1 -3
  384. package/dist/tool-system/builtin/write.d.ts +2 -1
  385. package/dist/tool-system/builtin/write.js +14 -4
  386. package/dist/tool-system/capability-module.d.ts +93 -0
  387. package/dist/tool-system/capability-module.js +53 -0
  388. package/dist/tool-system/context.d.ts +94 -24
  389. package/dist/tool-system/executor.js +99 -58
  390. package/dist/tool-system/external-tool-exposure.d.ts +60 -0
  391. package/dist/tool-system/external-tool-exposure.js +304 -0
  392. package/dist/tool-system/mcp-manager.d.ts +17 -1
  393. package/dist/tool-system/mcp-manager.js +72 -7
  394. package/dist/tool-system/mcp-tool-policy.d.ts +9 -0
  395. package/dist/tool-system/mcp-tool-policy.js +34 -0
  396. package/dist/tool-system/panel-bridge.d.ts +53 -0
  397. package/dist/tool-system/panel-bridge.js +1 -0
  398. package/dist/tool-system/path-policy.d.ts +19 -0
  399. package/dist/tool-system/path-policy.js +62 -1
  400. package/dist/tool-system/permission.d.ts +69 -3
  401. package/dist/tool-system/permission.js +429 -30
  402. package/dist/tool-system/registry.d.ts +15 -3
  403. package/dist/tool-system/registry.js +82 -40
  404. package/dist/tool-system/sandbox/index.js +3 -8
  405. package/dist/tool-system/sandbox/seatbelt.js +2 -6
  406. package/dist/tool-system/session-tool-host.d.ts +139 -0
  407. package/dist/tool-system/session-tool-host.js +167 -0
  408. package/dist/tool-system/testing/tool-registry-harness.d.ts +31 -0
  409. package/dist/tool-system/testing/tool-registry-harness.js +51 -0
  410. package/dist/tool-system/validation.d.ts +14 -7
  411. package/dist/tool-system/validation.js +701 -7
  412. package/dist/types.d.ts +201 -20
  413. package/dist/{cc-orchestrator → utils}/cwd-normalize.d.ts +1 -0
  414. package/dist/{cc-orchestrator → utils}/cwd-normalize.js +1 -0
  415. package/dist/utils/file-mutex.d.ts +65 -0
  416. package/dist/utils/file-mutex.js +145 -0
  417. package/dist/utils/json.d.ts +2 -4
  418. package/dist/utils/json.js +2 -4
  419. package/dist/utils/lockfile.d.ts +30 -1
  420. package/dist/utils/lockfile.js +2 -2
  421. package/dist/utils/secret-scrubber.d.ts +8 -0
  422. package/dist/utils/secret-scrubber.js +227 -0
  423. package/dist/utils/toolDisplay.js +1 -1
  424. package/package.json +20 -5
  425. package/THIRD_PARTY_NOTICES.md +0 -206
  426. package/dist/arena/arena.d.ts +0 -43
  427. package/dist/arena/arena.js +0 -333
  428. package/dist/arena/context/context-tools.d.ts +0 -16
  429. package/dist/arena/context/context-tools.js +0 -272
  430. package/dist/arena/context/within-root.d.ts +0 -7
  431. package/dist/arena/context/within-root.js +0 -15
  432. package/dist/arena/detect-mode.d.ts +0 -20
  433. package/dist/arena/detect-mode.js +0 -78
  434. package/dist/arena/digest-builder.d.ts +0 -25
  435. package/dist/arena/digest-builder.js +0 -120
  436. package/dist/arena/index.d.ts +0 -29
  437. package/dist/arena/index.js +0 -29
  438. package/dist/arena/iterate/convergence.d.ts +0 -25
  439. package/dist/arena/iterate/convergence.js +0 -103
  440. package/dist/arena/iterate/formats/index.d.ts +0 -22
  441. package/dist/arena/iterate/formats/index.js +0 -283
  442. package/dist/arena/iterate/index.d.ts +0 -11
  443. package/dist/arena/iterate/index.js +0 -9
  444. package/dist/arena/iterate/iterative-arena.d.ts +0 -23
  445. package/dist/arena/iterate/iterative-arena.js +0 -237
  446. package/dist/arena/iterate/parse.d.ts +0 -42
  447. package/dist/arena/iterate/parse.js +0 -123
  448. package/dist/arena/iterate/phases/argue.d.ts +0 -22
  449. package/dist/arena/iterate/phases/argue.js +0 -165
  450. package/dist/arena/iterate/phases/revise.d.ts +0 -16
  451. package/dist/arena/iterate/phases/revise.js +0 -62
  452. package/dist/arena/iterate/phases/tournament.d.ts +0 -34
  453. package/dist/arena/iterate/phases/tournament.js +0 -113
  454. package/dist/arena/iterate/tools/web-tools.d.ts +0 -13
  455. package/dist/arena/iterate/tools/web-tools.js +0 -54
  456. package/dist/arena/iterate/types.d.ts +0 -152
  457. package/dist/arena/iterate/types.js +0 -8
  458. package/dist/arena/ledger.d.ts +0 -47
  459. package/dist/arena/ledger.js +0 -159
  460. package/dist/arena/lenses/architecture.d.ts +0 -5
  461. package/dist/arena/lenses/architecture.js +0 -22
  462. package/dist/arena/lenses/engineering.d.ts +0 -5
  463. package/dist/arena/lenses/engineering.js +0 -22
  464. package/dist/arena/lenses/general.d.ts +0 -5
  465. package/dist/arena/lenses/general.js +0 -20
  466. package/dist/arena/lenses/index.d.ts +0 -16
  467. package/dist/arena/lenses/index.js +0 -47
  468. package/dist/arena/lenses/product.d.ts +0 -5
  469. package/dist/arena/lenses/product.js +0 -22
  470. package/dist/arena/model-presets.d.ts +0 -23
  471. package/dist/arena/model-presets.js +0 -44
  472. package/dist/arena/phases/adjudication.d.ts +0 -24
  473. package/dist/arena/phases/adjudication.js +0 -141
  474. package/dist/arena/phases/build-consensus.d.ts +0 -29
  475. package/dist/arena/phases/build-consensus.js +0 -83
  476. package/dist/arena/phases/claim-registry.d.ts +0 -26
  477. package/dist/arena/phases/claim-registry.js +0 -60
  478. package/dist/arena/phases/cross-review.d.ts +0 -45
  479. package/dist/arena/phases/cross-review.js +0 -218
  480. package/dist/arena/phases/debate-rounds.d.ts +0 -27
  481. package/dist/arena/phases/debate-rounds.js +0 -159
  482. package/dist/arena/phases/participant-research.d.ts +0 -38
  483. package/dist/arena/phases/participant-research.js +0 -314
  484. package/dist/arena/phases/planning-detail-expansion.d.ts +0 -38
  485. package/dist/arena/phases/planning-detail-expansion.js +0 -119
  486. package/dist/arena/planner.d.ts +0 -27
  487. package/dist/arena/planner.js +0 -311
  488. package/dist/arena/providers/docs.d.ts +0 -7
  489. package/dist/arena/providers/docs.js +0 -111
  490. package/dist/arena/providers/git.d.ts +0 -8
  491. package/dist/arena/providers/git.js +0 -174
  492. package/dist/arena/providers/index.d.ts +0 -32
  493. package/dist/arena/providers/index.js +0 -132
  494. package/dist/arena/providers/none.d.ts +0 -7
  495. package/dist/arena/providers/none.js +0 -11
  496. package/dist/arena/providers/repo.d.ts +0 -7
  497. package/dist/arena/providers/repo.js +0 -258
  498. package/dist/arena/render/session.d.ts +0 -17
  499. package/dist/arena/render/session.js +0 -190
  500. package/dist/arena/render/terminal.d.ts +0 -34
  501. package/dist/arena/render/terminal.js +0 -286
  502. package/dist/arena/strategies/discussion.d.ts +0 -25
  503. package/dist/arena/strategies/discussion.js +0 -143
  504. package/dist/arena/strategies/index.d.ts +0 -15
  505. package/dist/arena/strategies/index.js +0 -28
  506. package/dist/arena/strategies/language-wrapper.d.ts +0 -17
  507. package/dist/arena/strategies/language-wrapper.js +0 -102
  508. package/dist/arena/strategies/lens-wrapper.d.ts +0 -16
  509. package/dist/arena/strategies/lens-wrapper.js +0 -236
  510. package/dist/arena/strategies/planning.d.ts +0 -30
  511. package/dist/arena/strategies/planning.js +0 -225
  512. package/dist/arena/strategies/review.d.ts +0 -26
  513. package/dist/arena/strategies/review.js +0 -168
  514. package/dist/arena/strategies/utils.d.ts +0 -36
  515. package/dist/arena/strategies/utils.js +0 -603
  516. package/dist/arena/tools/selector.d.ts +0 -17
  517. package/dist/arena/tools/selector.js +0 -61
  518. package/dist/arena/transitions.d.ts +0 -53
  519. package/dist/arena/transitions.js +0 -97
  520. package/dist/arena/types.d.ts +0 -514
  521. package/dist/arena/types.js +0 -27
  522. package/dist/cc-orchestrator/agent-adapter.d.ts +0 -54
  523. package/dist/cc-orchestrator/agent-adapter.js +0 -143
  524. package/dist/cc-orchestrator/cc-capability.d.ts +0 -19
  525. package/dist/cc-orchestrator/cc-capability.js +0 -53
  526. package/dist/cc-orchestrator/codex-session-discovery.d.ts +0 -24
  527. package/dist/cc-orchestrator/codex-session-discovery.js +0 -191
  528. package/dist/cc-orchestrator/codex-session-history.d.ts +0 -38
  529. package/dist/cc-orchestrator/codex-session-history.js +0 -247
  530. package/dist/cc-orchestrator/external-agent-bindings.d.ts +0 -27
  531. package/dist/cc-orchestrator/external-agent-bindings.js +0 -150
  532. package/dist/cc-orchestrator/external-agent-changes.d.ts +0 -19
  533. package/dist/cc-orchestrator/external-agent-changes.js +0 -231
  534. package/dist/cc-orchestrator/external-agent-driver.d.ts +0 -19
  535. package/dist/cc-orchestrator/external-agent-driver.js +0 -284
  536. package/dist/cc-orchestrator/external-agent-session-store.d.ts +0 -23
  537. package/dist/cc-orchestrator/external-agent-session-store.js +0 -146
  538. package/dist/cc-orchestrator/index.d.ts +0 -8
  539. package/dist/cc-orchestrator/index.js +0 -8
  540. package/dist/cc-orchestrator/relevance-judge.d.ts +0 -15
  541. package/dist/cc-orchestrator/relevance-judge.js +0 -29
  542. package/dist/cc-orchestrator/session-discovery.d.ts +0 -46
  543. package/dist/cc-orchestrator/session-discovery.js +0 -125
  544. package/dist/cc-orchestrator/session-history.d.ts +0 -54
  545. package/dist/cc-orchestrator/session-history.js +0 -150
  546. package/dist/cron/cron-runtime.d.ts +0 -2
  547. package/dist/cron/cron-runtime.js +0 -2
  548. package/dist/cron/cron-store.d.ts +0 -2
  549. package/dist/cron/cron-store.js +0 -2
  550. package/dist/cron/scheduler.d.ts +0 -7
  551. package/dist/cron/scheduler.js +0 -7
  552. package/dist/engine/goal.js +0 -206
  553. package/dist/external-agents/config.d.ts +0 -2
  554. package/dist/external-agents/config.js +0 -15
  555. package/dist/external-agents/types.d.ts +0 -31
  556. package/dist/git/parse-log.d.ts +0 -13
  557. package/dist/git/parse-log.js +0 -21
  558. package/dist/git/utils.d.ts +0 -49
  559. package/dist/git/utils.js +0 -161
  560. package/dist/git/worktree/crud.d.ts +0 -69
  561. package/dist/git/worktree/crud.js +0 -206
  562. package/dist/git/worktree/diff.d.ts +0 -14
  563. package/dist/git/worktree/diff.js +0 -82
  564. package/dist/git/worktree/git-exec.d.ts +0 -7
  565. package/dist/git/worktree/git-exec.js +0 -51
  566. package/dist/git/worktree/index.d.ts +0 -5
  567. package/dist/git/worktree/index.js +0 -5
  568. package/dist/git/worktree/query.d.ts +0 -42
  569. package/dist/git/worktree/query.js +0 -121
  570. package/dist/git/worktree/slug.d.ts +0 -11
  571. package/dist/git/worktree/slug.js +0 -58
  572. package/dist/git/worktree.d.ts +0 -1
  573. package/dist/git/worktree.js +0 -5
  574. package/dist/lsp/client.d.ts +0 -41
  575. package/dist/lsp/client.js +0 -186
  576. package/dist/lsp/manager.d.ts +0 -40
  577. package/dist/lsp/manager.js +0 -155
  578. package/dist/lsp/root-path.d.ts +0 -9
  579. package/dist/lsp/root-path.js +0 -12
  580. package/dist/lsp/servers.d.ts +0 -16
  581. package/dist/lsp/servers.js +0 -60
  582. package/dist/prompt/sections/coding.md +0 -35
  583. package/dist/quota/credentials.d.ts +0 -3
  584. package/dist/quota/credentials.js +0 -80
  585. package/dist/quota/index.d.ts +0 -36
  586. package/dist/quota/index.js +0 -155
  587. package/dist/quota/types.d.ts +0 -48
  588. package/dist/quota/types.js +0 -13
  589. package/dist/review/review-prompt.d.ts +0 -28
  590. package/dist/review/review-prompt.js +0 -81
  591. package/dist/state.d.ts +0 -160
  592. package/dist/state.js +0 -267
  593. package/dist/tool-system/builtin/apply-patch/applier.d.ts +0 -26
  594. package/dist/tool-system/builtin/apply-patch/applier.js +0 -308
  595. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +0 -10
  596. package/dist/tool-system/builtin/apply-patch/backup-targets.js +0 -30
  597. package/dist/tool-system/builtin/apply-patch/index.d.ts +0 -20
  598. package/dist/tool-system/builtin/apply-patch/index.js +0 -105
  599. package/dist/tool-system/builtin/apply-patch/parser.d.ts +0 -17
  600. package/dist/tool-system/builtin/apply-patch/parser.js +0 -212
  601. package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +0 -18
  602. package/dist/tool-system/builtin/apply-patch/seek-sequence.js +0 -123
  603. package/dist/tool-system/builtin/apply-patch/types.d.ts +0 -49
  604. package/dist/tool-system/builtin/apply-patch/types.js +0 -13
  605. package/dist/tool-system/builtin/arena.d.ts +0 -31
  606. package/dist/tool-system/builtin/arena.js +0 -415
  607. package/dist/tool-system/builtin/brief.d.ts +0 -6
  608. package/dist/tool-system/builtin/brief.js +0 -41
  609. package/dist/tool-system/builtin/check-quota.d.ts +0 -15
  610. package/dist/tool-system/builtin/check-quota.js +0 -34
  611. package/dist/tool-system/builtin/drive-claude-code.d.ts +0 -51
  612. package/dist/tool-system/builtin/drive-claude-code.js +0 -698
  613. package/dist/tool-system/builtin/lsp.d.ts +0 -7
  614. package/dist/tool-system/builtin/lsp.js +0 -144
  615. package/dist/tool-system/builtin/notebook-edit.d.ts +0 -7
  616. package/dist/tool-system/builtin/notebook-edit.js +0 -127
  617. package/dist/tool-system/builtin/worktree.d.ts +0 -11
  618. package/dist/tool-system/builtin/worktree.js +0 -345
  619. /package/dist/{external-agents → links}/types.js +0 -0
  620. /package/dist/{engine/session-usage.d.ts → session/usage.d.ts} +0 -0
  621. /package/dist/{engine/session-usage.js → session/usage.js} +0 -0
@@ -6,6 +6,96 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "
6
6
  import { randomUUID } from "node:crypto";
7
7
  import { logger as rootPermLogger } from "../logging/logger.js";
8
8
  import { READ_ONLY_TOOLS } from "./plan-mode-allowlist.js";
9
+ /**
10
+ * Process-local connection owner router. Handlers are connection-scoped while
11
+ * session ownership is an explicit binding with a monotonic generation.
12
+ */
13
+ export class ApprovalRouter {
14
+ handlers = new Map();
15
+ owners = new Map();
16
+ fallbackConnections = new Set();
17
+ nextGeneration = 1;
18
+ addConnection(connectionId, handler, options) {
19
+ if (!connectionId)
20
+ throw new Error("approval connectionId is required");
21
+ if (this.handlers.has(connectionId)) {
22
+ throw new Error(`approval connection already registered: ${connectionId}`);
23
+ }
24
+ this.handlers.set(connectionId, handler);
25
+ if (options?.claimUnownedSessions)
26
+ this.fallbackConnections.add(connectionId);
27
+ return () => this.deregister(connectionId);
28
+ }
29
+ register(sessionId, connectionId) {
30
+ if (!sessionId)
31
+ throw new Error("approval sessionId is required");
32
+ if (!this.handlers.has(connectionId)) {
33
+ throw new Error(`approval connection is not registered: ${connectionId}`);
34
+ }
35
+ const current = this.owners.get(sessionId);
36
+ if (current?.connectionId === connectionId)
37
+ return { ok: true, target: current };
38
+ if (current)
39
+ return { ok: false, conflict: current };
40
+ const target = { connectionId, sessionId, generation: this.nextGeneration++ };
41
+ this.owners.set(sessionId, target);
42
+ return { ok: true, target };
43
+ }
44
+ resolve(request) {
45
+ if (!request.sessionId)
46
+ return null;
47
+ let target = this.owners.get(request.sessionId);
48
+ if (!target && this.fallbackConnections.size === 1) {
49
+ const connectionId = this.fallbackConnections.values().next().value;
50
+ if (connectionId) {
51
+ const registration = this.register(request.sessionId, connectionId);
52
+ if (registration.ok)
53
+ target = registration.target;
54
+ }
55
+ }
56
+ if (!target)
57
+ return null;
58
+ const handler = this.handlers.get(target.connectionId);
59
+ if (!handler) {
60
+ this.owners.delete(request.sessionId);
61
+ return null;
62
+ }
63
+ return handler.requestApproval(request, target);
64
+ }
65
+ matches(target) {
66
+ const current = this.owners.get(target.sessionId);
67
+ return (current?.connectionId === target.connectionId && current.generation === target.generation);
68
+ }
69
+ current(sessionId) {
70
+ return this.owners.get(sessionId) ?? null;
71
+ }
72
+ release(sessionId, connectionId, reason = "approval session released") {
73
+ const current = this.owners.get(sessionId);
74
+ if (!current || current.connectionId !== connectionId)
75
+ return;
76
+ this.owners.delete(sessionId);
77
+ this.handlers.get(connectionId)?.ownershipLost?.([current], reason);
78
+ }
79
+ deregister(connectionId, reason = "approval connection disconnected") {
80
+ const handler = this.handlers.get(connectionId);
81
+ if (!handler)
82
+ return;
83
+ this.handlers.delete(connectionId);
84
+ this.fallbackConnections.delete(connectionId);
85
+ const lost = [];
86
+ for (const [sessionId, target] of this.owners) {
87
+ if (target.connectionId !== connectionId)
88
+ continue;
89
+ this.owners.delete(sessionId);
90
+ lost.push(target);
91
+ }
92
+ if (lost.length > 0)
93
+ handler.ownershipLost?.(lost, reason);
94
+ }
95
+ hasConnections() {
96
+ return this.handlers.size > 0;
97
+ }
98
+ }
9
99
  export class HeadlessApprovalBackend {
10
100
  mode;
11
101
  constructor(mode) {
@@ -117,6 +207,7 @@ export const CLOSED_SESSION_TOMBSTONE_LIMIT = 4096;
117
207
  * the next time the user opens the project.
118
208
  */
119
209
  export class InteractiveApprovalBackend {
210
+ approvalRouter;
120
211
  // Session-scoped grants are bucketed by ApprovalRequest.sessionId and then
121
212
  // keyed on the OPERATION (tool + narrowed argsPattern via buildProjectRule),
122
213
  // NOT just the tool name. Approving `git status` for one session must not
@@ -132,18 +223,25 @@ export class InteractiveApprovalBackend {
132
223
  savedProjectRules: [],
133
224
  onProjectRules: null,
134
225
  };
226
+ constructor(approvalRouter = new ApprovalRouter()) {
227
+ this.approvalRouter = approvalRouter;
228
+ }
135
229
  setPromptFn(fn) {
136
230
  this.promptFn = fn;
137
231
  }
232
+ clearPromptFn() {
233
+ this.promptFn = null;
234
+ }
138
235
  /**
139
236
  * Has someone installed a real prompt callback? Engine consults this
140
237
  * to decide whether to use the interactive backend (= talk to a UI)
141
238
  * or fall back to HeadlessApprovalBackend (= deny-all). Without it,
142
- * the agent-server-stdio entry which wires setInteractiveApprovalFn
143
- * during server boot would still fall through to deny-all because
239
+ * a protocol host registers its connection with ApprovalRouter during boot
240
+ * but before the first session is bound without this check Engine would
241
+ * still fall through to deny-all because
144
242
  * the engine couldn't tell the difference. */
145
243
  hasPromptFn() {
146
- return this.promptFn !== null;
244
+ return this.promptFn !== null || this.approvalRouter.hasConnections();
147
245
  }
148
246
  /** Inject the project root so persistence writes to the right settings file. */
149
247
  setCwd(cwd) {
@@ -220,7 +318,7 @@ export class InteractiveApprovalBackend {
220
318
  const cached = state ? this.checkSessionRules(req, state) : null;
221
319
  if (cached)
222
320
  return cached;
223
- if (!this.promptFn) {
321
+ if (!this.promptFn && !this.approvalRouter.hasConnections()) {
224
322
  return { approved: false, reason: "interactive approval backend has no prompt function" };
225
323
  }
226
324
  // Serialize prompts and re-check rules when our turn comes (see promptTurn
@@ -261,10 +359,27 @@ export class InteractiveApprovalBackend {
261
359
  }
262
360
  /** The actual interactive ask + rule recording (runs inside the prompt turn). */
263
361
  async promptAndRecord(req, state) {
264
- if (!this.promptFn) {
362
+ const hasOwner = !!req.sessionId && this.approvalRouter.current(req.sessionId) !== null;
363
+ const routed = hasOwner ? this.approvalRouter.resolve(req) : null;
364
+ let result;
365
+ if (routed) {
366
+ result = await routed;
367
+ }
368
+ else if (this.promptFn) {
369
+ result = await this.promptFn(req);
370
+ }
371
+ else if (req.sessionId && this.approvalRouter.hasConnections()) {
372
+ const fallback = this.approvalRouter.resolve(req);
373
+ result = fallback
374
+ ? await fallback
375
+ : {
376
+ approved: false,
377
+ reason: `no approval connection owns session ${req.sessionId}`,
378
+ };
379
+ }
380
+ else {
265
381
  return { approved: false, reason: "interactive approval backend has no prompt function" };
266
382
  }
267
- const result = await this.promptFn(req);
268
383
  const scope = result.scope ?? (result.always ? "session" : "once");
269
384
  const activeState = this.isActiveSessionState(req.sessionId, state) ? state : null;
270
385
  const context = activeState ?? (!req.sessionId ? this.legacyContext : null);
@@ -521,11 +636,15 @@ function persistProjectRule(cwd, rule) {
521
636
  writeFileSync(tmp, JSON.stringify(settings, null, 2) + "\n", "utf-8");
522
637
  renameSync(tmp, file);
523
638
  }
524
- // Singleton interactive backend for use by the UI
639
+ // Singleton interactive backend and its multi-connection owner router.
640
+ const _approvalRouter = new ApprovalRouter();
525
641
  let _interactiveBackend = null;
642
+ export function getApprovalRouter() {
643
+ return _approvalRouter;
644
+ }
526
645
  export function getInteractiveApprovalBackend() {
527
646
  if (!_interactiveBackend) {
528
- _interactiveBackend = new InteractiveApprovalBackend();
647
+ _interactiveBackend = new InteractiveApprovalBackend(_approvalRouter);
529
648
  }
530
649
  return _interactiveBackend;
531
650
  }
@@ -535,9 +654,6 @@ export function openInteractiveApprovalSession(sessionId) {
535
654
  export function clearInteractiveApprovalSession(sessionId) {
536
655
  getInteractiveApprovalBackend().clearSession(sessionId);
537
656
  }
538
- export function setInteractiveApprovalFn(fn) {
539
- getInteractiveApprovalBackend().setPromptFn(fn);
540
- }
541
657
  const DANGEROUS_PATTERNS = [
542
658
  /rm\s+-rf/,
543
659
  /rm\s+-r\s+\//,
@@ -570,9 +686,6 @@ const SAFE_READ_PATTERNS = [
570
686
  // are NOT classified safe-read. Plain predicates (-name, -type, -print) stay.
571
687
  /^find\s(?!.*\s-(delete|exec(dir)?|ok(dir)?|fprintf?|fls)\b)/,
572
688
  /^(grep|rg|ag|ack|fgrep|egrep)\s/,
573
- // Word-boundary the git read subcommands so `git difftool -x <cmd>` (which
574
- // runs an arbitrary external command) does NOT match on the `diff` branch.
575
- /^(git\s+(status|log|diff|branch|show|blame|remote|tag|stash\s+list|rev-parse|describe))\b/,
576
689
  /^(node|python|ruby|go|rustc|java|javac)\s+--version/,
577
690
  /^(npm|pnpm|yarn|cargo|pip|gem|brew)\s+(list|ls|info|show|view|outdated|audit)/,
578
691
  /^pwd$/,
@@ -583,6 +696,151 @@ const SAFE_READ_PATTERNS = [
583
696
  /^env$/,
584
697
  /^printenv/,
585
698
  ];
699
+ /** Split a command conservatively enough to validate git's argument shape. */
700
+ function splitShellWords(input) {
701
+ const words = [];
702
+ let word = "";
703
+ let quote = null;
704
+ let hasWord = false;
705
+ for (let i = 0; i < input.length; i++) {
706
+ const ch = input[i];
707
+ if (quote === null && /\s/.test(ch)) {
708
+ if (hasWord) {
709
+ words.push(word);
710
+ word = "";
711
+ hasWord = false;
712
+ }
713
+ continue;
714
+ }
715
+ if (ch === "\\" && quote !== "'") {
716
+ const next = input[++i];
717
+ if (next === undefined)
718
+ return null;
719
+ word += next;
720
+ hasWord = true;
721
+ continue;
722
+ }
723
+ // Single quotes make expansion syntax literal. Outside them, reject all
724
+ // parameter/command expansion rather than let expansion change a vetted
725
+ // git argument into an unsafe option or action at execution time.
726
+ if (quote !== "'" && (ch === "$" || ch === "`"))
727
+ return null;
728
+ if (ch === "'" || ch === '"') {
729
+ if (quote === null) {
730
+ quote = ch;
731
+ hasWord = true;
732
+ continue;
733
+ }
734
+ if (quote === ch) {
735
+ quote = null;
736
+ continue;
737
+ }
738
+ }
739
+ word += ch;
740
+ hasWord = true;
741
+ }
742
+ if (quote !== null)
743
+ return null;
744
+ if (hasWord)
745
+ words.push(word);
746
+ return words;
747
+ }
748
+ const GIT_LIST_STANDALONE_OPTIONS = new Set([
749
+ "--all",
750
+ "--color",
751
+ "--column",
752
+ "--ignore-case",
753
+ "--no-abbrev",
754
+ "--no-color",
755
+ "--no-column",
756
+ "--omit-empty",
757
+ "--remotes",
758
+ "--show-current",
759
+ "--verbose",
760
+ "-a",
761
+ "-r",
762
+ "-v",
763
+ "-vv",
764
+ ]);
765
+ const GIT_LIST_VALUE_OPTIONS = new Set([
766
+ "--contains",
767
+ "--format",
768
+ "--merged",
769
+ "--no-contains",
770
+ "--no-merged",
771
+ "--points-at",
772
+ "--sort",
773
+ ]);
774
+ const GIT_SAFE_GLOBAL_OPTIONS = new Set(["--no-pager", "--no-optional-locks"]);
775
+ function isSafeGitListArgs(args) {
776
+ let listMode = false;
777
+ let positionalOnly = false;
778
+ for (let i = 0; i < args.length; i++) {
779
+ const arg = args[i];
780
+ if (positionalOnly)
781
+ continue;
782
+ if (arg === "--") {
783
+ if (!listMode)
784
+ return false;
785
+ positionalOnly = true;
786
+ continue;
787
+ }
788
+ if (arg === "-l" || arg === "--list") {
789
+ listMode = true;
790
+ continue;
791
+ }
792
+ if (GIT_LIST_STANDALONE_OPTIONS.has(arg))
793
+ continue;
794
+ if ([...GIT_LIST_STANDALONE_OPTIONS, ...GIT_LIST_VALUE_OPTIONS].some((option) => arg.startsWith(`${option}=`))) {
795
+ continue;
796
+ }
797
+ if (GIT_LIST_VALUE_OPTIONS.has(arg)) {
798
+ if (++i >= args.length)
799
+ return false;
800
+ continue;
801
+ }
802
+ if (listMode && !arg.startsWith("-"))
803
+ continue;
804
+ return false;
805
+ }
806
+ return true;
807
+ }
808
+ /**
809
+ * Git is safe-read only for an explicit read subcommand and a read-only
810
+ * argument shape. In particular, branch/tag positional creation and all
811
+ * remote sub-actions fail closed instead of inheriting safety from the
812
+ * subcommand name.
813
+ */
814
+ function isSafeReadGitCommand(segment) {
815
+ const words = splitShellWords(segment.trim());
816
+ if (!words || words[0] !== "git")
817
+ return false;
818
+ let subcommandIndex = 1;
819
+ while (GIT_SAFE_GLOBAL_OPTIONS.has(words[subcommandIndex]))
820
+ subcommandIndex++;
821
+ const subcommand = words[subcommandIndex];
822
+ const args = words.slice(subcommandIndex + 1);
823
+ const hasWriteOrExecutionOption = (gitArgs) => gitArgs.some((arg) => arg === "--ext-diff" ||
824
+ arg === "--textconv" ||
825
+ arg === "--output" ||
826
+ arg.startsWith("--output="));
827
+ if (["status", "log", "diff", "show", "blame", "rev-parse", "describe"].includes(subcommand)) {
828
+ return !hasWriteOrExecutionOption(args);
829
+ }
830
+ if (subcommand === "stash") {
831
+ return args[0] === "list" && !hasWriteOrExecutionOption(args.slice(1));
832
+ }
833
+ if (subcommand === "branch" || subcommand === "tag")
834
+ return isSafeGitListArgs(args);
835
+ if (subcommand === "remote") {
836
+ return args.every((arg) => arg === "-v" || arg === "--verbose");
837
+ }
838
+ return false;
839
+ }
840
+ function matchesSafeReadPattern(segment, allowArgumentless = false) {
841
+ return (isSafeReadGitCommand(segment) ||
842
+ SAFE_READ_PATTERNS.some((pattern) => pattern.test(segment) || (allowArgumentless && pattern.test(`${segment} `))));
843
+ }
586
844
  // ─── Sensitive safe-read downgrade ────────────────────────────────
587
845
  //
588
846
  // `Read ~/.ssh/id_rsa` routes through path-policy (asks); the equivalent
@@ -643,17 +901,61 @@ const SAFE_WRITE_PATTERNS = [
643
901
  // - top-level `;`, `&&`, `||`, newline split the command into
644
902
  // segments. Every segment must independently classify as safe
645
903
  // for the whole command to be safe.
646
- // - unquoted command substitution (` ` ` or `$(` ), redirection
904
+ // - command substitution (` ` ` or `$(` ) outside single quotes, redirection
647
905
  // (`>` `>>` `<` `<<`), process substitution (`<(` `>(`), and
648
906
  // pipe-to-shell (`| sh`, `| bash`, ...) flag the command as
649
907
  // dangerous.
650
- // - quoted (`'…'`, `"…"`) and backslash-escaped characters are
651
- // ignored `echo "a; b"` is a single segment.
908
+ // - single quotes make command-substitution syntax literal; double quotes
909
+ // do not. Other quoted and backslash-escaped metacharacters are ignored —
910
+ // `echo "a; b"` is a single segment.
652
911
  //
653
912
  // This is intentionally detection-only, not a full shell parser. We
654
913
  // only need to find unquoted metacharacters and split safely.
655
- const PIPE_TO_SHELL_RE = /\|\s*(sh|bash|zsh|dash|ksh|fish|python|python3|node|nodejs|ruby|perl|php)\b/;
914
+ const PIPE_SHELL_COMMAND_RE = /^(sh|bash|zsh|dash|ksh|fish|python|python3|node|nodejs|ruby|perl|php)\b/;
915
+ /** Apply Bash line continuation before inspecting shell syntax. */
916
+ function normalizeShellLineContinuations(input) {
917
+ let normalized = "";
918
+ let quote = null;
919
+ for (let i = 0; i < input.length; i++) {
920
+ const ch = input[i];
921
+ const next = input[i + 1];
922
+ // Backslash-newline remains literal inside single quotes.
923
+ if (quote === "'") {
924
+ if (ch === quote)
925
+ quote = null;
926
+ normalized += ch;
927
+ continue;
928
+ }
929
+ if (ch === "\\") {
930
+ if (next === "\n") {
931
+ i++;
932
+ continue;
933
+ }
934
+ if (next === "\r" && input[i + 2] === "\n") {
935
+ i += 2;
936
+ continue;
937
+ }
938
+ // Preserve other escapes verbatim and do not treat an escaped quote as
939
+ // changing the quote state used by this normalization pass.
940
+ normalized += ch;
941
+ if (next !== undefined) {
942
+ normalized += next;
943
+ i++;
944
+ }
945
+ continue;
946
+ }
947
+ if (ch === "'" || ch === '"') {
948
+ if (quote === null)
949
+ quote = ch;
950
+ else if (quote === ch)
951
+ quote = null;
952
+ }
953
+ normalized += ch;
954
+ }
955
+ return normalized;
956
+ }
656
957
  function scanShellCommand(input) {
958
+ const normalizedInput = normalizeShellLineContinuations(input);
657
959
  const segments = [];
658
960
  let buf = "";
659
961
  let dangerous = false;
@@ -668,9 +970,9 @@ function scanShellCommand(input) {
668
970
  segments.push(s);
669
971
  buf = "";
670
972
  };
671
- while (i < input.length) {
672
- const ch = input[i];
673
- const next = input[i + 1];
973
+ while (i < normalizedInput.length) {
974
+ const ch = normalizedInput[i];
975
+ const next = normalizedInput[i + 1];
674
976
  if (quote === null) {
675
977
  // Escape: skip the next character
676
978
  if (ch === "\\" && next !== undefined) {
@@ -727,12 +1029,28 @@ function scanShellCommand(input) {
727
1029
  i++;
728
1030
  continue;
729
1031
  }
730
- // Inside a quote
1032
+ // Inside single quotes, every character other than the closing quote is
1033
+ // literal. In particular, `$(` and backticks do not execute.
1034
+ if (quote === "'") {
1035
+ if (ch === quote)
1036
+ quote = null;
1037
+ buf += ch;
1038
+ i++;
1039
+ continue;
1040
+ }
1041
+ // Inside double quotes, escapes still suppress substitution syntax, but
1042
+ // unescaped `$(` and backticks execute and must fail closed.
731
1043
  if (ch === "\\" && next !== undefined) {
732
1044
  buf += ch + next;
733
1045
  i += 2;
734
1046
  continue;
735
1047
  }
1048
+ if (ch === "`" || (ch === "$" && next === "(")) {
1049
+ dangerous = true;
1050
+ buf += ch;
1051
+ i++;
1052
+ continue;
1053
+ }
736
1054
  if (ch === quote) {
737
1055
  quote = null;
738
1056
  buf += ch;
@@ -751,6 +1069,37 @@ function scanShellCommand(input) {
751
1069
  dangerous = true;
752
1070
  return { segments, dangerous };
753
1071
  }
1072
+ /** Split only on real shell pipes, preserving pipes inside quotes or escapes. */
1073
+ function splitUnquotedPipes(input) {
1074
+ const parts = [];
1075
+ let buf = "";
1076
+ let quote = null;
1077
+ for (let i = 0; i < input.length; i++) {
1078
+ const ch = input[i];
1079
+ const next = input[i + 1];
1080
+ if (ch === "\\" && quote !== "'" && next !== undefined) {
1081
+ buf += ch + next;
1082
+ i++;
1083
+ continue;
1084
+ }
1085
+ if (ch === "'" || ch === '"') {
1086
+ if (quote === null)
1087
+ quote = ch;
1088
+ else if (quote === ch)
1089
+ quote = null;
1090
+ buf += ch;
1091
+ continue;
1092
+ }
1093
+ if (ch === "|" && quote === null) {
1094
+ parts.push(buf.trim());
1095
+ buf = "";
1096
+ continue;
1097
+ }
1098
+ buf += ch;
1099
+ }
1100
+ parts.push(buf.trim());
1101
+ return parts;
1102
+ }
754
1103
  function classifySegment(segment) {
755
1104
  if (DANGEROUS_PATTERNS.some((p) => p.test(segment)))
756
1105
  return "dangerous";
@@ -762,13 +1111,15 @@ function classifySegment(segment) {
762
1111
  // `| nc ...` exfil tail — declaring a piped-to-network command safe-read.
763
1112
  // We did not split on `|` in the scanner because pipes are not statement
764
1113
  // boundaries; they're per-segment data flow.
765
- if (segment.includes("|")) {
1114
+ const parts = splitUnquotedPipes(segment);
1115
+ if (parts.length > 1) {
766
1116
  // A pipe part may be an argument-less command (`ls`, `pwd`) whose trailing
767
1117
  // space was stripped along with the `|`. Test each part both as-is (for
768
1118
  // `$`-anchored patterns like /^pwd$/) and with a trailing space appended
769
1119
  // (for `\s`-delimited patterns like /^ls\s/), so neither form is missed.
770
- const parts = segment.split("|").map((p) => p.trim());
771
- const partIsSafeRead = (p) => SAFE_READ_PATTERNS.some((re) => re.test(p) || re.test(`${p} `));
1120
+ if (parts.slice(1).some((part) => PIPE_SHELL_COMMAND_RE.test(part)))
1121
+ return "dangerous";
1122
+ const partIsSafeRead = (p) => matchesSafeReadPattern(p, true);
772
1123
  if (parts.every(partIsSafeRead)) {
773
1124
  // A sensitive read anywhere in the pipe (`cat ~/.ssh/id_rsa | base64`,
774
1125
  // `env | grep KEY`) downgrades the whole pipe.
@@ -778,7 +1129,7 @@ function classifySegment(segment) {
778
1129
  }
779
1130
  return "unsafe";
780
1131
  }
781
- if (SAFE_READ_PATTERNS.some((p) => p.test(segment))) {
1132
+ if (matchesSafeReadPattern(segment)) {
782
1133
  return segmentIsSensitiveRead(segment) ? "unsafe" : "safe-read";
783
1134
  }
784
1135
  if (SAFE_WRITE_PATTERNS.some((p) => p.test(segment)))
@@ -803,8 +1154,6 @@ export function classifyBashCommand(command) {
803
1154
  // separators we would split on.
804
1155
  if (DANGEROUS_PATTERNS.some((p) => p.test(trimmed)))
805
1156
  return "dangerous";
806
- if (PIPE_TO_SHELL_RE.test(trimmed))
807
- return "dangerous";
808
1157
  const scan = scanShellCommand(trimmed);
809
1158
  if (scan.dangerous)
810
1159
  return "dangerous";
@@ -888,6 +1237,9 @@ export class PermissionClassifier {
888
1237
  * tests and ad-hoc usages still write log lines.
889
1238
  */
890
1239
  log = rootPermLogger;
1240
+ approvalStateListener;
1241
+ approvalEventListener;
1242
+ activeApprovalCount = 0;
891
1243
  constructor(rules, defaultMode = "default", approvalBackend = new HeadlessApprovalBackend("deny-all")) {
892
1244
  this.rules = rules;
893
1245
  this.defaultMode = defaultMode;
@@ -896,6 +1248,27 @@ export class PermissionClassifier {
896
1248
  setLogger(log) {
897
1249
  this.log = log;
898
1250
  }
1251
+ setApprovalStateListener(listener) {
1252
+ this.approvalStateListener = listener;
1253
+ }
1254
+ /**
1255
+ * Observe interactive-approval lifecycle (requested → resolved). The engine
1256
+ * wires this to the `notification` hook so plugins / settings hooks can
1257
+ * react to "waiting for the user's decision" moments (system notification,
1258
+ * IM ping, …). Listener errors are swallowed — observation must never
1259
+ * affect the approval outcome.
1260
+ */
1261
+ setApprovalEventListener(listener) {
1262
+ this.approvalEventListener = listener;
1263
+ }
1264
+ emitApprovalEvent(event) {
1265
+ try {
1266
+ this.approvalEventListener?.(event);
1267
+ }
1268
+ catch {
1269
+ /* observers must not affect approval flow */
1270
+ }
1271
+ }
899
1272
  /** Replace mode + backend in place so live tool execution sees the change. */
900
1273
  reconfigure(mode, approvalBackend, rules) {
901
1274
  this.defaultMode = mode;
@@ -919,12 +1292,16 @@ export class PermissionClassifier {
919
1292
  // YOLO classifier for Bash commands
920
1293
  if (toolName === "Bash") {
921
1294
  const level = classifyBashCommand(String(args.command ?? ""));
1295
+ // acceptEdits opts into workspace edits through the tool allowlist below;
1296
+ // it never opts into unattended shell execution. Explicit rules were
1297
+ // already honored above, and bypassPermissions returned before them.
1298
+ if (this.defaultMode === "acceptEdits")
1299
+ return "ask";
922
1300
  if (level === "dangerous")
923
1301
  return "ask";
924
1302
  if (level === "safe-read")
925
1303
  return "allow";
926
- if (level === "safe-write" &&
927
- (this.defaultMode === "acceptEdits" || this.defaultMode === "auto")) {
1304
+ if (level === "safe-write" && this.defaultMode === "auto") {
928
1305
  return "allow";
929
1306
  }
930
1307
  if (level === "unsafe")
@@ -977,6 +1354,14 @@ export class PermissionClassifier {
977
1354
  riskLevel,
978
1355
  });
979
1356
  let result;
1357
+ this.activeApprovalCount++;
1358
+ this.approvalStateListener?.(true, toolName);
1359
+ this.emitApprovalEvent({
1360
+ phase: "requested",
1361
+ toolName,
1362
+ riskLevel,
1363
+ ...(opts?.sessionId ? { sessionId: opts.sessionId } : {}),
1364
+ });
980
1365
  try {
981
1366
  const baseDescription = this.describeToolCall(toolName, args);
982
1367
  const description = reason ? `${baseDescription}\n\nReason:\n${reason}` : baseDescription;
@@ -992,12 +1377,24 @@ export class PermissionClassifier {
992
1377
  span.fail(err, { tool: toolName });
993
1378
  throw err;
994
1379
  }
1380
+ finally {
1381
+ this.activeApprovalCount = Math.max(0, this.activeApprovalCount - 1);
1382
+ if (this.activeApprovalCount === 0)
1383
+ this.approvalStateListener?.(false, toolName);
1384
+ }
995
1385
  if (result.approved) {
996
1386
  this.denialTracker.recordSuccess(toolName);
997
1387
  }
998
1388
  else {
999
1389
  this.denialTracker.record(toolName);
1000
1390
  }
1391
+ this.emitApprovalEvent({
1392
+ phase: "resolved",
1393
+ toolName,
1394
+ riskLevel,
1395
+ approved: result.approved,
1396
+ ...(opts?.sessionId ? { sessionId: opts.sessionId } : {}),
1397
+ });
1001
1398
  span.end({
1002
1399
  tool: toolName,
1003
1400
  approved: result.approved,
@@ -1032,6 +1429,8 @@ export class PermissionClassifier {
1032
1429
  return "medium";
1033
1430
  if (toolName === "Bash")
1034
1431
  return "medium";
1432
+ if (toolName === "Panel")
1433
+ return args.action === "invoke" ? "medium" : "low";
1035
1434
  // Only genuinely read-only built-ins are "low" (the sole tier
1036
1435
  // AutoApprovalBackend approves with no delegate). Everything else —
1037
1436
  // crucially every MCP tool, which can delete records, send messages, or
@@ -2,27 +2,38 @@
2
2
  * Unified tool registry — built-in tools + MCP tools.
3
3
  */
4
4
  import type { RegisteredTool, ToolDefinition, ToolResult } from "../types.js";
5
- import { type BuiltinToolFn } from "./builtin/index.js";
5
+ import { type BuiltinTool, type BuiltinToolGuard } from "./builtin/index.js";
6
6
  import type { ToolContext } from "./context.js";
7
7
  /**
8
8
  * Default execution timeout for any tool that does not declare its own
9
9
  * timeoutMs at registration time. Tools that need to run longer (Agent,
10
- * Arena, Bash, custom long-running tools) should set timeoutMs explicitly.
10
+ * Bash, or custom capability tools) should set timeoutMs explicitly.
11
11
  */
12
12
  export declare const DEFAULT_TOOL_TIMEOUT_MS = 120000;
13
13
  export interface ToolRegistryOptions {
14
14
  builtinTools?: readonly string[];
15
+ /** Core catalog plus any tools contributed by host capability packages. */
16
+ toolCatalog?: readonly BuiltinTool[];
15
17
  }
18
+ type ToolImplementation = (args: Record<string, unknown>, ctx?: ToolContext) => Promise<unknown>;
16
19
  export declare class ToolRegistry {
17
20
  private tools;
18
21
  private builtinExecutors;
22
+ private availabilityGuards;
19
23
  constructor(options?: ToolRegistryOptions);
20
24
  private registerBuiltins;
21
- registerTool(tool: RegisteredTool, executor?: BuiltinToolFn): void;
25
+ registerTool(tool: RegisteredTool, executor?: ToolImplementation): void;
26
+ /** Create an engine-local registry view without sharing mutable maps. */
27
+ fork(): ToolRegistry;
22
28
  unregisterTool(name: string): void;
23
29
  getToolDefinitions(): ToolDefinition[];
24
30
  getTool(name: string): RegisteredTool | undefined;
25
31
  hasTool(name: string): boolean;
32
+ /** Test/harness introspection: definitions without implementations are valid
33
+ * for some dynamic registrations, but every builtin catalog entry must have
34
+ * an executor. */
35
+ hasExecutor(name: string): boolean;
36
+ getAvailabilityGuard(name: string): BuiltinToolGuard | undefined;
26
37
  executeTool(name: string, args: Record<string, unknown>, options?: {
27
38
  timeoutMs?: number;
28
39
  signal?: AbortSignal;
@@ -31,3 +42,4 @@ export declare class ToolRegistry {
31
42
  listTools(): string[];
32
43
  listToolsDetailed(): RegisteredTool[];
33
44
  }
45
+ export {};