@clinebot/core 0.0.27 → 0.0.29

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 (339) hide show
  1. package/README.md +7 -0
  2. package/dist/ClineCore.d.ts +28 -2
  3. package/dist/ClineCore.d.ts.map +1 -1
  4. package/dist/account/cline-account-service.d.ts +1 -1
  5. package/dist/account/cline-account-service.d.ts.map +1 -1
  6. package/dist/account/index.d.ts +1 -1
  7. package/dist/account/index.d.ts.map +1 -1
  8. package/dist/account/types.d.ts +5 -0
  9. package/dist/account/types.d.ts.map +1 -1
  10. package/dist/auth/bounded-ttl-cache.d.ts +14 -0
  11. package/dist/auth/bounded-ttl-cache.d.ts.map +1 -0
  12. package/dist/auth/cline.d.ts +27 -2
  13. package/dist/auth/cline.d.ts.map +1 -1
  14. package/dist/auth/oca.d.ts.map +1 -1
  15. package/dist/chat/chat-schema.d.ts +8 -8
  16. package/dist/extensions/config/agent-config-loader.d.ts.map +1 -0
  17. package/dist/{agents → extensions/config}/agent-config-parser.d.ts +2 -2
  18. package/dist/extensions/config/agent-config-parser.d.ts.map +1 -0
  19. package/dist/{agents → extensions/config}/hooks-config-loader.d.ts +1 -1
  20. package/dist/extensions/config/hooks-config-loader.d.ts.map +1 -0
  21. package/dist/{agents → extensions/config}/index.d.ts +2 -4
  22. package/dist/extensions/config/index.d.ts.map +1 -0
  23. package/dist/{runtime/commands.d.ts → extensions/config/runtime-commands.d.ts} +2 -3
  24. package/dist/extensions/config/runtime-commands.d.ts.map +1 -0
  25. package/dist/extensions/config/unified-config-file-watcher.d.ts.map +1 -0
  26. package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -0
  27. package/dist/extensions/context/agentic-compaction.d.ts +13 -0
  28. package/dist/extensions/context/agentic-compaction.d.ts.map +1 -0
  29. package/dist/extensions/context/basic-compaction.d.ts +9 -0
  30. package/dist/extensions/context/basic-compaction.d.ts.map +1 -0
  31. package/dist/extensions/context/compaction-shared.d.ts +60 -0
  32. package/dist/extensions/context/compaction-shared.d.ts.map +1 -0
  33. package/dist/extensions/context/compaction.d.ts +20 -0
  34. package/dist/extensions/context/compaction.d.ts.map +1 -0
  35. package/dist/extensions/index.d.ts +5 -0
  36. package/dist/extensions/index.d.ts.map +1 -0
  37. package/dist/extensions/mcp/client.d.ts +3 -0
  38. package/dist/extensions/mcp/client.d.ts.map +1 -0
  39. package/dist/extensions/mcp/config-loader.d.ts.map +1 -0
  40. package/dist/extensions/mcp/index.d.ts +9 -0
  41. package/dist/extensions/mcp/index.d.ts.map +1 -0
  42. package/dist/{mcp → extensions/mcp}/manager.d.ts +1 -2
  43. package/dist/extensions/mcp/manager.d.ts.map +1 -0
  44. package/dist/extensions/mcp/name-transform.d.ts +3 -0
  45. package/dist/extensions/mcp/name-transform.d.ts.map +1 -0
  46. package/dist/extensions/mcp/policies.d.ts +15 -0
  47. package/dist/extensions/mcp/policies.d.ts.map +1 -0
  48. package/dist/extensions/mcp/tools.d.ts +4 -0
  49. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  50. package/dist/{mcp → extensions/mcp}/types.d.ts +29 -1
  51. package/dist/extensions/mcp/types.d.ts.map +1 -0
  52. package/dist/{agents → extensions/plugin}/plugin-config-loader.d.ts +1 -1
  53. package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -0
  54. package/dist/{agents → extensions/plugin}/plugin-loader.d.ts +1 -1
  55. package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -0
  56. package/dist/extensions/plugin/plugin-module-import.d.ts +5 -0
  57. package/dist/extensions/plugin/plugin-module-import.d.ts.map +1 -0
  58. package/dist/{agents → extensions/plugin}/plugin-sandbox.d.ts +1 -1
  59. package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -0
  60. package/dist/extensions/plugin-sandbox-bootstrap.js +485 -0
  61. package/dist/hooks/index.d.ts +4 -0
  62. package/dist/hooks/index.d.ts.map +1 -0
  63. package/dist/hooks/persistent.d.ts +64 -0
  64. package/dist/hooks/persistent.d.ts.map +1 -0
  65. package/dist/hooks/subprocess-runner.d.ts +22 -0
  66. package/dist/hooks/subprocess-runner.d.ts.map +1 -0
  67. package/dist/hooks/subprocess.d.ts +189 -0
  68. package/dist/hooks/subprocess.d.ts.map +1 -0
  69. package/dist/index.d.ts +22 -25
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +560 -447
  72. package/dist/prompt/default-system.d.ts +2 -0
  73. package/dist/prompt/default-system.d.ts.map +1 -0
  74. package/dist/providers/local-provider-service.d.ts +1 -1
  75. package/dist/providers/local-provider-service.d.ts.map +1 -1
  76. package/dist/runtime/checkpoint-hooks.d.ts +21 -0
  77. package/dist/runtime/checkpoint-hooks.d.ts.map +1 -0
  78. package/dist/runtime/hook-file-hooks.d.ts +1 -1
  79. package/dist/runtime/hook-file-hooks.d.ts.map +1 -1
  80. package/dist/runtime/rules.d.ts +1 -1
  81. package/dist/runtime/rules.d.ts.map +1 -1
  82. package/dist/runtime/runtime-builder.d.ts +1 -1
  83. package/dist/runtime/runtime-builder.d.ts.map +1 -1
  84. package/dist/runtime/session-runtime.d.ts +25 -5
  85. package/dist/runtime/session-runtime.d.ts.map +1 -1
  86. package/dist/runtime/subprocess-sandbox.d.ts.map +1 -0
  87. package/dist/runtime/team-runtime-registry.d.ts +1 -1
  88. package/dist/runtime/team-runtime-registry.d.ts.map +1 -1
  89. package/dist/runtime/tool-approval.d.ts +1 -1
  90. package/dist/session/default-session-manager.d.ts +4 -3
  91. package/dist/session/default-session-manager.d.ts.map +1 -1
  92. package/dist/session/file-session-service.d.ts +1 -1
  93. package/dist/session/file-session-service.d.ts.map +1 -1
  94. package/dist/session/{unified-session-persistence-service.d.ts → persistence-service.d.ts} +11 -42
  95. package/dist/session/persistence-service.d.ts.map +1 -0
  96. package/dist/session/rpc-session-service.d.ts +1 -1
  97. package/dist/session/rpc-session-service.d.ts.map +1 -1
  98. package/dist/session/session-agent-events.d.ts +1 -1
  99. package/dist/session/session-artifacts.d.ts.map +1 -1
  100. package/dist/session/session-config-builder.d.ts.map +1 -1
  101. package/dist/session/session-graph.d.ts +1 -1
  102. package/dist/session/session-graph.d.ts.map +1 -1
  103. package/dist/session/session-host.d.ts.map +1 -1
  104. package/dist/session/session-manager.d.ts +6 -5
  105. package/dist/session/session-manager.d.ts.map +1 -1
  106. package/dist/session/session-manifest.d.ts +1 -1
  107. package/dist/session/session-service.d.ts +3 -2
  108. package/dist/session/session-service.d.ts.map +1 -1
  109. package/dist/session/session-team-coordination.d.ts +2 -1
  110. package/dist/session/session-team-coordination.d.ts.map +1 -1
  111. package/dist/session/utils/helpers.d.ts +51 -3
  112. package/dist/session/utils/helpers.d.ts.map +1 -1
  113. package/dist/session/utils/types.d.ts +41 -7
  114. package/dist/session/utils/types.d.ts.map +1 -1
  115. package/dist/session/workspace-manager.d.ts +1 -2
  116. package/dist/session/workspace-manager.d.ts.map +1 -1
  117. package/dist/session/workspace-manifest.d.ts +1 -22
  118. package/dist/session/workspace-manifest.d.ts.map +1 -1
  119. package/dist/storage/file-team-store.d.ts +2 -1
  120. package/dist/storage/file-team-store.d.ts.map +1 -1
  121. package/dist/storage/sqlite-team-store.d.ts +4 -1
  122. package/dist/storage/sqlite-team-store.d.ts.map +1 -1
  123. package/dist/storage/team-store.d.ts.map +1 -1
  124. package/dist/team/delegated-agent.d.ts +44 -0
  125. package/dist/team/delegated-agent.d.ts.map +1 -0
  126. package/dist/team/index.d.ts +1 -0
  127. package/dist/team/index.d.ts.map +1 -1
  128. package/dist/team/multi-agent.d.ts +229 -0
  129. package/dist/team/multi-agent.d.ts.map +1 -0
  130. package/dist/team/projections.d.ts +2 -2
  131. package/dist/team/projections.d.ts.map +1 -1
  132. package/dist/team/runtime.d.ts +5 -0
  133. package/dist/team/runtime.d.ts.map +1 -0
  134. package/dist/team/spawn-agent-tool.d.ts +85 -0
  135. package/dist/team/spawn-agent-tool.d.ts.map +1 -0
  136. package/dist/team/subagent-prompts.d.ts +4 -0
  137. package/dist/team/subagent-prompts.d.ts.map +1 -0
  138. package/dist/team/team-tools.d.ts +35 -0
  139. package/dist/team/team-tools.d.ts.map +1 -0
  140. package/dist/telemetry/OpenTelemetryProvider.d.ts +11 -1
  141. package/dist/telemetry/OpenTelemetryProvider.d.ts.map +1 -1
  142. package/dist/telemetry/{LoggerTelemetryAdapter.d.ts → TelemetryLoggerSink.d.ts} +10 -4
  143. package/dist/telemetry/TelemetryLoggerSink.d.ts.map +1 -0
  144. package/dist/telemetry/TelemetryService.d.ts.map +1 -1
  145. package/dist/telemetry/index.js +15 -28
  146. package/dist/tools/definitions.d.ts +4 -3
  147. package/dist/tools/definitions.d.ts.map +1 -1
  148. package/dist/tools/index.d.ts +5 -5
  149. package/dist/tools/index.d.ts.map +1 -1
  150. package/dist/tools/model-tool-routing.d.ts.map +1 -1
  151. package/dist/tools/presets.d.ts +26 -0
  152. package/dist/tools/presets.d.ts.map +1 -1
  153. package/dist/tools/schemas.d.ts +8 -0
  154. package/dist/tools/schemas.d.ts.map +1 -1
  155. package/dist/tools/types.d.ts +23 -2
  156. package/dist/tools/types.d.ts.map +1 -1
  157. package/dist/types/config.d.ts +47 -3
  158. package/dist/types/config.d.ts.map +1 -1
  159. package/dist/types/events.d.ts +1 -1
  160. package/dist/types/provider-settings.d.ts +1 -1
  161. package/dist/types/provider-settings.d.ts.map +1 -1
  162. package/dist/types/storage.d.ts +2 -1
  163. package/dist/types/storage.d.ts.map +1 -1
  164. package/dist/types.d.ts +7 -16
  165. package/dist/types.d.ts.map +1 -1
  166. package/package.json +16 -13
  167. package/src/ClineCore.test.ts +150 -0
  168. package/src/ClineCore.ts +114 -8
  169. package/src/account/cline-account-service.test.ts +84 -0
  170. package/src/account/cline-account-service.ts +2 -2
  171. package/src/account/index.ts +1 -0
  172. package/src/account/types.ts +6 -0
  173. package/src/auth/bounded-ttl-cache.test.ts +38 -0
  174. package/src/auth/bounded-ttl-cache.ts +53 -0
  175. package/src/auth/cline.test.ts +173 -36
  176. package/src/auth/cline.ts +395 -93
  177. package/src/auth/oca.test.ts +125 -0
  178. package/src/auth/oca.ts +17 -4
  179. package/src/{agents → extensions/config}/agent-config-loader.test.ts +1 -1
  180. package/src/{agents → extensions/config}/agent-config-parser.ts +2 -2
  181. package/src/{agents → extensions/config}/hooks-config-loader.ts +1 -1
  182. package/src/{agents → extensions/config}/index.ts +7 -11
  183. package/src/{runtime/commands.test.ts → extensions/config/runtime-commands.test.ts} +20 -3
  184. package/src/{runtime/commands.ts → extensions/config/runtime-commands.ts} +1 -8
  185. package/src/{agents → extensions/config}/unified-config-file-watcher.ts +15 -2
  186. package/src/{agents → extensions/config}/user-instruction-config-loader.test.ts +90 -2
  187. package/src/{agents → extensions/config}/user-instruction-config-loader.ts +126 -12
  188. package/src/extensions/context/agentic-compaction.ts +119 -0
  189. package/src/extensions/context/basic-compaction.ts +275 -0
  190. package/src/extensions/context/compaction-shared.ts +458 -0
  191. package/src/extensions/context/compaction.test.ts +477 -0
  192. package/src/extensions/context/compaction.ts +203 -0
  193. package/src/extensions/index.ts +12 -0
  194. package/src/extensions/mcp/client.ts +420 -0
  195. package/src/{mcp → extensions/mcp}/index.ts +16 -0
  196. package/src/{mcp → extensions/mcp}/manager.test.ts +1 -2
  197. package/src/{mcp → extensions/mcp}/manager.ts +3 -5
  198. package/src/extensions/mcp/name-transform.ts +33 -0
  199. package/src/extensions/mcp/policies.ts +47 -0
  200. package/src/extensions/mcp/tools.ts +47 -0
  201. package/src/{mcp → extensions/mcp}/types.ts +35 -7
  202. package/src/{agents → extensions/plugin}/plugin-config-loader.test.ts +18 -13
  203. package/src/{agents → extensions/plugin}/plugin-config-loader.ts +1 -1
  204. package/src/{agents → extensions/plugin}/plugin-loader.test.ts +41 -4
  205. package/src/extensions/plugin/plugin-loader.ts +106 -0
  206. package/src/extensions/plugin/plugin-module-import.ts +278 -0
  207. package/src/{agents → extensions/plugin}/plugin-sandbox-bootstrap.ts +30 -92
  208. package/src/{agents → extensions/plugin}/plugin-sandbox.test.ts +60 -3
  209. package/src/{agents → extensions/plugin}/plugin-sandbox.ts +146 -56
  210. package/src/hooks/index.ts +25 -0
  211. package/src/hooks/persistent.ts +661 -0
  212. package/src/hooks/subprocess-runner.ts +196 -0
  213. package/src/hooks/subprocess.ts +669 -0
  214. package/src/index.ts +200 -118
  215. package/src/prompt/default-system.ts +21 -0
  216. package/src/providers/local-provider-registry.ts +1 -1
  217. package/src/providers/local-provider-service.test.ts +23 -2
  218. package/src/providers/local-provider-service.ts +2 -2
  219. package/src/runtime/checkpoint-hooks.test.ts +167 -0
  220. package/src/runtime/checkpoint-hooks.ts +186 -0
  221. package/src/runtime/hook-file-hooks.test.ts +40 -1
  222. package/src/runtime/hook-file-hooks.ts +35 -16
  223. package/src/runtime/index.ts +4 -19
  224. package/src/runtime/rules.ts +4 -1
  225. package/src/runtime/runtime-builder.team-persistence.test.ts +3 -6
  226. package/src/runtime/runtime-builder.test.ts +266 -160
  227. package/src/runtime/runtime-builder.ts +120 -47
  228. package/src/runtime/runtime-parity.test.ts +22 -22
  229. package/src/runtime/session-runtime.ts +36 -6
  230. package/src/runtime/{sandbox/subprocess-sandbox.ts → subprocess-sandbox.ts} +24 -3
  231. package/src/runtime/team-runtime-registry.ts +1 -4
  232. package/src/runtime/tool-approval.ts +1 -1
  233. package/src/session/default-session-manager.e2e.test.ts +2 -2
  234. package/src/session/default-session-manager.test.ts +553 -9
  235. package/src/session/default-session-manager.ts +140 -46
  236. package/src/session/file-session-service.ts +3 -3
  237. package/src/session/index.ts +6 -6
  238. package/src/session/persistence-service.test.ts +212 -0
  239. package/src/session/{unified-session-persistence-service.ts → persistence-service.ts} +106 -172
  240. package/src/session/rpc-session-service.ts +3 -3
  241. package/src/session/runtime-oauth-token-manager.ts +1 -1
  242. package/src/session/session-agent-events.ts +1 -1
  243. package/src/session/session-artifacts.ts +32 -4
  244. package/src/session/session-config-builder.ts +22 -9
  245. package/src/session/session-graph.ts +1 -1
  246. package/src/session/session-host.ts +19 -11
  247. package/src/session/session-manager.ts +11 -6
  248. package/src/session/session-service.team-persistence.test.ts +1 -1
  249. package/src/session/session-service.ts +6 -9
  250. package/src/session/session-team-coordination.ts +7 -3
  251. package/src/session/session-telemetry.ts +1 -1
  252. package/src/session/utils/helpers.test.ts +160 -0
  253. package/src/session/utils/helpers.ts +289 -42
  254. package/src/session/utils/types.ts +47 -7
  255. package/src/session/workspace-manager.ts +5 -3
  256. package/src/session/workspace-manifest.ts +3 -49
  257. package/src/storage/file-team-store.ts +2 -5
  258. package/src/storage/provider-settings-legacy-migration.ts +2 -2
  259. package/src/storage/provider-settings-manager.test.ts +1 -1
  260. package/src/storage/sqlite-team-store.ts +212 -125
  261. package/src/storage/team-store.ts +1 -5
  262. package/src/team/delegated-agent.ts +131 -0
  263. package/src/team/index.ts +1 -0
  264. package/src/team/multi-agent.lifecycle.test.ts +201 -0
  265. package/src/team/multi-agent.ts +1666 -0
  266. package/src/team/projections.ts +2 -4
  267. package/src/team/runtime.ts +54 -0
  268. package/src/team/spawn-agent-tool.test.ts +387 -0
  269. package/src/team/spawn-agent-tool.ts +207 -0
  270. package/src/team/subagent-prompts.ts +41 -0
  271. package/src/team/team-tools.test.ts +802 -0
  272. package/src/team/team-tools.ts +792 -0
  273. package/src/telemetry/OpenTelemetryProvider.test.ts +25 -3
  274. package/src/telemetry/OpenTelemetryProvider.ts +108 -18
  275. package/src/telemetry/TelemetryLoggerSink.test.ts +42 -0
  276. package/src/telemetry/{LoggerTelemetryAdapter.ts → TelemetryLoggerSink.ts} +21 -14
  277. package/src/telemetry/TelemetryService.test.ts +7 -7
  278. package/src/telemetry/TelemetryService.ts +2 -4
  279. package/src/tools/definitions.test.ts +76 -0
  280. package/src/tools/definitions.ts +41 -2
  281. package/src/tools/executors/apply-patch.ts +1 -1
  282. package/src/tools/executors/editor.ts +1 -1
  283. package/src/tools/executors/file-read.ts +1 -1
  284. package/src/tools/executors/search.ts +1 -1
  285. package/src/tools/executors/web-fetch.ts +1 -1
  286. package/src/tools/index.ts +6 -1
  287. package/src/tools/model-tool-routing.ts +2 -0
  288. package/src/tools/presets.test.ts +8 -0
  289. package/src/tools/presets.ts +40 -2
  290. package/src/tools/schemas.ts +19 -0
  291. package/src/tools/types.ts +31 -2
  292. package/src/types/config.ts +61 -7
  293. package/src/types/events.ts +1 -1
  294. package/src/types/index.ts +0 -1
  295. package/src/types/provider-settings.ts +1 -1
  296. package/src/types/storage.ts +2 -5
  297. package/src/types.ts +32 -44
  298. package/dist/agents/agent-config-loader.d.ts.map +0 -1
  299. package/dist/agents/agent-config-parser.d.ts.map +0 -1
  300. package/dist/agents/hooks-config-loader.d.ts.map +0 -1
  301. package/dist/agents/index.d.ts.map +0 -1
  302. package/dist/agents/plugin-config-loader.d.ts.map +0 -1
  303. package/dist/agents/plugin-loader.d.ts.map +0 -1
  304. package/dist/agents/plugin-sandbox-bootstrap.js +0 -446
  305. package/dist/agents/plugin-sandbox.d.ts.map +0 -1
  306. package/dist/agents/unified-config-file-watcher.d.ts.map +0 -1
  307. package/dist/agents/user-instruction-config-loader.d.ts.map +0 -1
  308. package/dist/mcp/config-loader.d.ts.map +0 -1
  309. package/dist/mcp/index.d.ts +0 -5
  310. package/dist/mcp/index.d.ts.map +0 -1
  311. package/dist/mcp/manager.d.ts.map +0 -1
  312. package/dist/mcp/types.d.ts.map +0 -1
  313. package/dist/runtime/commands.d.ts.map +0 -1
  314. package/dist/runtime/sandbox/subprocess-sandbox.d.ts.map +0 -1
  315. package/dist/runtime/skills.d.ts +0 -14
  316. package/dist/runtime/skills.d.ts.map +0 -1
  317. package/dist/runtime/workflows.d.ts +0 -14
  318. package/dist/runtime/workflows.d.ts.map +0 -1
  319. package/dist/session/unified-session-persistence-service.d.ts.map +0 -1
  320. package/dist/telemetry/LoggerTelemetryAdapter.d.ts.map +0 -1
  321. package/dist/types/workspace.d.ts +0 -8
  322. package/dist/types/workspace.d.ts.map +0 -1
  323. package/src/agents/plugin-loader.ts +0 -175
  324. package/src/runtime/skills.ts +0 -44
  325. package/src/runtime/workflows.test.ts +0 -119
  326. package/src/runtime/workflows.ts +0 -45
  327. package/src/session/unified-session-persistence-service.test.ts +0 -85
  328. package/src/telemetry/LoggerTelemetryAdapter.test.ts +0 -42
  329. package/src/types/workspace.ts +0 -7
  330. /package/dist/{agents → extensions/config}/agent-config-loader.d.ts +0 -0
  331. /package/dist/{agents → extensions/config}/unified-config-file-watcher.d.ts +0 -0
  332. /package/dist/{agents → extensions/config}/user-instruction-config-loader.d.ts +0 -0
  333. /package/dist/{mcp → extensions/mcp}/config-loader.d.ts +0 -0
  334. /package/dist/runtime/{sandbox/subprocess-sandbox.d.ts → subprocess-sandbox.d.ts} +0 -0
  335. /package/src/{agents → extensions/config}/agent-config-loader.ts +0 -0
  336. /package/src/{agents → extensions/config}/hooks-config-loader.test.ts +0 -0
  337. /package/src/{agents → extensions/config}/unified-config-file-watcher.test.ts +0 -0
  338. /package/src/{mcp → extensions/mcp}/config-loader.test.ts +0 -0
  339. /package/src/{mcp → extensions/mcp}/config-loader.ts +0 -0
@@ -1,6 +1,3 @@
1
- import { existsSync } from "node:fs";
2
- import { builtinModules, createRequire } from "node:module";
3
- import { dirname, resolve } from "node:path";
4
1
  /**
5
2
  * Bootstrap script for the plugin sandbox subprocess.
6
3
  *
@@ -9,12 +6,11 @@ import { dirname, resolve } from "node:path";
9
6
  * imports plugin modules, wiring up their contributions (tools, commands,
10
7
  * shortcuts, flags, renderers, providers) and lifecycle hooks.
11
8
  *
12
- * Because it executes in a separate process it must be self-contained no
13
- * imports from the rest of the codebase are allowed.
9
+ * Because it executes in a separate process it must stay bundle-safe and only
10
+ * depend on local helpers that can be inlined into the sandbox build.
14
11
  */
15
12
 
16
- import { fileURLToPath } from "node:url";
17
- import createJiti from "jiti";
13
+ import { importPluginModule } from "./plugin-module-import";
18
14
 
19
15
  // ---------------------------------------------------------------------------
20
16
  // Types (intentionally minimal – mirrors only what the RPC protocol needs)
@@ -47,9 +43,9 @@ interface PluginFlag {
47
43
  defaultValue?: boolean | string | number;
48
44
  }
49
45
 
50
- interface PluginMessageRenderer {
46
+ interface PluginMessageBuilder {
51
47
  name: string;
52
- render: (message: unknown) => string;
48
+ build: (message: unknown[]) => unknown[]; // Message[]
53
49
  }
54
50
 
55
51
  interface PluginProvider {
@@ -63,7 +59,7 @@ interface PluginApi {
63
59
  registerCommand(command: PluginCommand): void;
64
60
  registerShortcut(shortcut: PluginShortcut): void;
65
61
  registerFlag(flag: PluginFlag): void;
66
- registerMessageRenderer(renderer: PluginMessageRenderer): void;
62
+ registerMessageBuilder(builder: PluginMessageBuilder): void;
67
63
  registerProvider(provider: PluginProvider): void;
68
64
  }
69
65
 
@@ -95,7 +91,7 @@ interface PluginDescriptor {
95
91
  commands: ContributionDescriptor[];
96
92
  shortcuts: ContributionDescriptor[];
97
93
  flags: ContributionDescriptor[];
98
- messageRenderers: ContributionDescriptor[];
94
+ messageBuilders: ContributionDescriptor[];
99
95
  providers: ContributionDescriptor[];
100
96
  };
101
97
  }
@@ -105,7 +101,7 @@ interface PluginState {
105
101
  handlers: {
106
102
  tools: Map<string, PluginTool["execute"]>;
107
103
  commands: Map<string, NonNullable<PluginCommand["handler"]>>;
108
- messageRenderers: Map<string, PluginMessageRenderer["render"]>;
104
+ messageBuilders: Map<string, PluginMessageBuilder["build"]>;
109
105
  };
110
106
  }
111
107
 
@@ -134,11 +130,7 @@ function assertValidPluginModule(
134
130
 
135
131
  let pluginCounter = 0;
136
132
  const pluginState = new Map<string, PluginState>();
137
- const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
138
- const WORKSPACE_ALIASES = collectWorkspaceAliases(MODULE_DIR);
139
- const BUILTIN_MODULES = new Set(
140
- builtinModules.flatMap((id) => [id, id.replace(/^node:/, "")]),
141
- );
133
+ const contributionCounters = new Map<string, number>();
142
134
 
143
135
  // ---------------------------------------------------------------------------
144
136
  // IPC helpers
@@ -178,7 +170,10 @@ function sanitizeObject(value: unknown): Record<string, unknown> {
178
170
  }
179
171
 
180
172
  function makeId(pluginId: string, prefix: string): string {
181
- return `${pluginId}_${prefix}_${Math.random().toString(36).slice(2, 10)}`;
173
+ const key = `${pluginId}:${prefix}`;
174
+ const next = (contributionCounters.get(key) ?? 0) + 1;
175
+ contributionCounters.set(key, next);
176
+ return `${pluginId}_${prefix}_${next}`;
182
177
  }
183
178
 
184
179
  function getPlugin(pluginId: string): PluginState {
@@ -189,67 +184,6 @@ function getPlugin(pluginId: string): PluginState {
189
184
  return state;
190
185
  }
191
186
 
192
- function collectWorkspaceAliases(startDir: string): Record<string, string> {
193
- const root = resolve(startDir, "..", "..", "..", "..");
194
- const aliases: Record<string, string> = {};
195
- const candidates: Record<string, string> = {
196
- "@clinebot/agents": resolve(root, "packages/agents/src/index.ts"),
197
- "@clinebot/core": resolve(root, "packages/core/src/index.ts"),
198
- "@clinebot/llms": resolve(root, "packages/llms/src/index.ts"),
199
- "@clinebot/llms/models": resolve(root, "packages/llms/src/models.ts"),
200
- "@clinebot/llms/providers": resolve(root, "packages/llms/src/providers.ts"),
201
- "@clinebot/llms/runtime": resolve(root, "packages/llms/src/runtime.ts"),
202
- "@clinebot/rpc": resolve(root, "packages/rpc/src/index.ts"),
203
- "@clinebot/scheduler": resolve(root, "packages/scheduler/src/index.ts"),
204
- "@clinebot/shared": resolve(root, "packages/shared/src/index.ts"),
205
- "@clinebot/shared/storage": resolve(
206
- root,
207
- "packages/shared/src/storage/index.ts",
208
- ),
209
- "@clinebot/shared/db": resolve(root, "packages/shared/src/db/index.ts"),
210
- };
211
- for (const [key, value] of Object.entries(candidates)) {
212
- if (existsSync(value)) {
213
- aliases[key] = value;
214
- }
215
- }
216
- return aliases;
217
- }
218
-
219
- function collectPluginImportAliases(
220
- pluginPath: string,
221
- ): Record<string, string> {
222
- const pluginRequire = createRequire(pluginPath);
223
- const aliases: Record<string, string> = {};
224
- for (const [specifier, sourcePath] of Object.entries(WORKSPACE_ALIASES)) {
225
- try {
226
- pluginRequire.resolve(specifier);
227
- continue;
228
- } catch {
229
- // Use the workspace source only when the plugin package does not provide
230
- // its own installed SDK dependency.
231
- }
232
- aliases[specifier] = sourcePath;
233
- }
234
- return aliases;
235
- }
236
-
237
- async function importPluginModule(
238
- pluginPath: string,
239
- ): Promise<Record<string, unknown>> {
240
- const aliases = collectPluginImportAliases(pluginPath);
241
- const jiti = createJiti(pluginPath, {
242
- alias: aliases,
243
- cache: false,
244
- requireCache: false,
245
- esmResolve: true,
246
- interopDefault: false,
247
- nativeModules: [...BUILTIN_MODULES],
248
- transformModules: Object.keys(aliases),
249
- });
250
- return (await jiti.import(pluginPath, {})) as Record<string, unknown>;
251
- }
252
-
253
187
  // ---------------------------------------------------------------------------
254
188
  // RPC methods
255
189
  // ---------------------------------------------------------------------------
@@ -258,6 +192,10 @@ async function initialize(args: {
258
192
  pluginPaths?: string[];
259
193
  exportName?: string;
260
194
  }): Promise<PluginDescriptor[]> {
195
+ pluginState.clear();
196
+ pluginCounter = 0;
197
+ contributionCounters.clear();
198
+
261
199
  const descriptors: PluginDescriptor[] = [];
262
200
  const exportName = args.exportName || "plugin";
263
201
 
@@ -273,13 +211,13 @@ async function initialize(args: {
273
211
  commands: [],
274
212
  shortcuts: [],
275
213
  flags: [],
276
- messageRenderers: [],
214
+ messageBuilders: [],
277
215
  providers: [],
278
216
  };
279
217
  const handlers: PluginState["handlers"] = {
280
218
  tools: new Map(),
281
219
  commands: new Map(),
282
- messageRenderers: new Map(),
220
+ messageBuilders: new Map(),
283
221
  };
284
222
 
285
223
  const api: PluginApi = {
@@ -322,10 +260,10 @@ async function initialize(args: {
322
260
  defaultValue: flag.defaultValue,
323
261
  });
324
262
  },
325
- registerMessageRenderer: (renderer) => {
326
- const id = makeId(pluginId, "renderer");
327
- handlers.messageRenderers.set(id, renderer.render);
328
- contributions.messageRenderers.push({ id, name: renderer.name });
263
+ registerMessageBuilder: (builder) => {
264
+ const id = makeId(pluginId, "builder");
265
+ handlers.messageBuilders.set(id, builder.build);
266
+ contributions.messageBuilders.push({ id, name: builder.name });
329
267
  },
330
268
  registerProvider: (provider) => {
331
269
  contributions.providers.push({
@@ -395,17 +333,17 @@ async function executeCommand(args: {
395
333
  return await handler(args.input);
396
334
  }
397
335
 
398
- async function renderMessage(args: {
336
+ async function buildMessages(args: {
399
337
  pluginId: string;
400
338
  contributionId: string;
401
- message: unknown;
402
- }): Promise<string> {
339
+ messages: unknown[];
340
+ }): Promise<unknown[]> {
403
341
  const state = getPlugin(args.pluginId);
404
- const handler = state.handlers.messageRenderers.get(args.contributionId);
342
+ const handler = state.handlers.messageBuilders.get(args.contributionId);
405
343
  if (typeof handler !== "function") {
406
- return "";
344
+ return [];
407
345
  }
408
- return await handler(args.message);
346
+ return await handler(args.messages);
409
347
  }
410
348
 
411
349
  // ---------------------------------------------------------------------------
@@ -417,7 +355,7 @@ const methods: Record<string, (args: never) => Promise<unknown>> = {
417
355
  invokeHook,
418
356
  executeTool,
419
357
  executeCommand,
420
- renderMessage,
358
+ buildMessages,
421
359
  };
422
360
 
423
361
  process.on(
@@ -1,7 +1,7 @@
1
1
  import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
- import type { AgentConfig, Tool, ToolContext } from "@clinebot/agents";
4
+ import type { AgentConfig, Tool, ToolContext } from "@clinebot/shared";
5
5
  import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
6
6
  import { loadSandboxedPlugins } from "./plugin-sandbox";
7
7
 
@@ -12,7 +12,7 @@ function createApiCapture() {
12
12
  registerCommand: () => {},
13
13
  registerShortcut: () => {},
14
14
  registerFlag: () => {},
15
- registerMessageRenderer: () => {},
15
+ registerMessageBuilder: () => {},
16
16
  registerProvider: () => {},
17
17
  };
18
18
  return { tools, api };
@@ -29,6 +29,7 @@ describe("plugin-sandbox", () => {
29
29
  >();
30
30
  const forwardedEvents: Array<{ name: string; payload?: unknown }> = [];
31
31
 
32
+ // Allow generous time for jiti transpilation of multiple TS plugins in CI.
32
33
  beforeAll(async () => {
33
34
  dir = await mkdtemp(join(tmpdir(), "core-plugin-sandbox-"));
34
35
 
@@ -150,6 +151,39 @@ describe("plugin-sandbox", () => {
150
151
  "utf8",
151
152
  );
152
153
 
154
+ await writeFile(
155
+ join(dir, "plugin-host-dep.ts"),
156
+ [
157
+ "import { resolveClineDataDir } from '@clinebot/shared/storage';",
158
+ "import YAML from 'yaml';",
159
+ "export default {",
160
+ " name: YAML.stringify({ host: !!resolveClineDataDir() }).trim(),",
161
+ " manifest: { capabilities: ['tools'] },",
162
+ "};",
163
+ ].join("\n"),
164
+ "utf8",
165
+ );
166
+
167
+ await writeFile(
168
+ join(dir, "plugin-create-tool.ts"),
169
+ [
170
+ "import { createTool } from '@clinebot/agents';",
171
+ "export default {",
172
+ " name: 'sandbox-create-tool',",
173
+ " manifest: { capabilities: ['tools'] },",
174
+ " setup(api) {",
175
+ " api.registerTool(createTool({",
176
+ " name: 'created_tool',",
177
+ " description: 'created via agents export',",
178
+ " inputSchema: { type: 'object', properties: { value: { type: 'string' } }, required: ['value'] },",
179
+ " execute: async (input) => ({ echoed: input.value }),",
180
+ " }));",
181
+ " },",
182
+ "};",
183
+ ].join("\n"),
184
+ "utf8",
185
+ );
186
+
153
187
  sharedSandbox = await loadSandboxedPlugins({
154
188
  pluginPaths: [
155
189
  join(dir, "plugin.mjs"),
@@ -157,7 +191,12 @@ describe("plugin-sandbox", () => {
157
191
  join(dir, "plugin-ts.ts"),
158
192
  join(dir, "plugin-dep.ts"),
159
193
  join(dir, "plugin-sdk.ts"),
194
+ join(dir, "plugin-host-dep.ts"),
195
+ join(dir, "plugin-create-tool.ts"),
160
196
  ],
197
+ // CI environments are significantly slower for jiti transpilation;
198
+ // the default 4 000 ms is too tight for 7 plugins.
199
+ importTimeoutMs: 30_000,
161
200
  onEvent: (event) => {
162
201
  forwardedEvents.push(event);
163
202
  },
@@ -168,7 +207,7 @@ describe("plugin-sandbox", () => {
168
207
  extension,
169
208
  ]),
170
209
  );
171
- });
210
+ }, 60_000);
172
211
 
173
212
  beforeEach(() => {
174
213
  forwardedEvents.length = 0;
@@ -293,4 +332,22 @@ describe("plugin-sandbox", () => {
293
332
  "sandbox-plugin-installed-sdk",
294
333
  );
295
334
  });
335
+
336
+ it("allows standalone file plugins to use host runtime dependencies in the sandbox", async () => {
337
+ expect(sharedExtensions.get("host: true")?.name).toBe("host: true");
338
+ });
339
+
340
+ it("supports createTool through the agents package export in the sandbox", async () => {
341
+ const extension = sharedExtensions.get("sandbox-create-tool");
342
+ const { tools, api } = createApiCapture();
343
+ await extension?.setup?.(api);
344
+ const tool = tools.find((entry) => entry.name === "created_tool");
345
+ expect(tool).toBeDefined();
346
+ const result = await tool?.execute({ value: "ok" }, {
347
+ agentId: "agent-1",
348
+ conversationId: "conv-1",
349
+ iteration: 1,
350
+ } as ToolContext);
351
+ expect(result).toEqual({ echoed: "ok" });
352
+ });
296
353
  });
@@ -1,8 +1,9 @@
1
1
  import { existsSync } from "node:fs";
2
+ import { createRequire } from "node:module";
2
3
  import { dirname, join } from "node:path";
3
4
  import { fileURLToPath } from "node:url";
4
- import type { AgentConfig, Tool } from "@clinebot/agents";
5
- import { SubprocessSandbox } from "../runtime/sandbox/subprocess-sandbox";
5
+ import type { AgentConfig, HookStage, Tool } from "@clinebot/shared";
6
+ import { SubprocessSandbox } from "../../runtime/subprocess-sandbox";
6
7
 
7
8
  export interface PluginSandboxOptions {
8
9
  pluginPaths: string[];
@@ -15,16 +16,6 @@ export interface PluginSandboxOptions {
15
16
 
16
17
  type AgentExtension = NonNullable<AgentConfig["extensions"]>[number];
17
18
  type AgentExtensionApi = Parameters<NonNullable<AgentExtension["setup"]>>[0];
18
- type HookStage =
19
- | "input"
20
- | "runtime_event"
21
- | "session_start"
22
- | "before_agent_start"
23
- | "tool_call_before"
24
- | "tool_call_after"
25
- | "turn_end"
26
- | "session_shutdown"
27
- | "error";
28
19
 
29
20
  type SandboxedContributionDescriptor = {
30
21
  id: string;
@@ -47,11 +38,16 @@ type SandboxedPluginDescriptor = {
47
38
  commands: SandboxedContributionDescriptor[];
48
39
  shortcuts: SandboxedContributionDescriptor[];
49
40
  flags: SandboxedContributionDescriptor[];
50
- messageRenderers: SandboxedContributionDescriptor[];
41
+ messageBuilders: SandboxedContributionDescriptor[];
51
42
  providers: SandboxedContributionDescriptor[];
52
43
  };
53
44
  };
54
45
 
46
+ function isUnknownPluginIdError(error: unknown): boolean {
47
+ const message = error instanceof Error ? error.message : String(error);
48
+ return message.includes("Unknown sandbox plugin id:");
49
+ }
50
+
55
51
  /**
56
52
  * Resolve the bootstrap for the sandbox subprocess.
57
53
  *
@@ -62,19 +58,29 @@ type SandboxedPluginDescriptor = {
62
58
  */
63
59
  function resolveBootstrap(): { file: string } | { script: string } {
64
60
  const dir = dirname(fileURLToPath(import.meta.url));
65
- // In dev, the bootstrap sits next to this file in src/agents/.
66
- // In production, the main bundle is at dist/ but bootstrap is at dist/agents/.
61
+ const requireFromHere = createRequire(import.meta.url);
62
+ // In dev, the bootstrap sits next to this file in src/extensions/.
63
+ // In production, the main bundle is at dist/ and the bootstrap is emitted
64
+ // under dist/extensions/. Keep the older dist/agents/ fallback for
65
+ // compatibility with previously built layouts.
67
66
  const candidates = [
68
67
  join(dir, "plugin-sandbox-bootstrap.js"),
68
+ join(dir, "extensions", "plugin-sandbox-bootstrap.js"),
69
69
  join(dir, "agents", "plugin-sandbox-bootstrap.js"),
70
70
  ];
71
71
  for (const candidate of candidates) {
72
72
  if (existsSync(candidate)) return { file: candidate };
73
73
  }
74
74
  const tsPath = join(dir, "plugin-sandbox-bootstrap.ts");
75
+ let jitiSpecifier = "jiti";
76
+ try {
77
+ jitiSpecifier = requireFromHere.resolve("jiti");
78
+ } catch {
79
+ // Fall back to bare specifier and let runtime resolution handle it.
80
+ }
75
81
  return {
76
82
  script: [
77
- "const createJiti = require('jiti');",
83
+ `const createJiti = require(${JSON.stringify(jitiSpecifier)});`,
78
84
  `const jiti = createJiti(${JSON.stringify(tsPath)}, { cache: false, requireCache: false, esmResolve: true, interopDefault: false });`,
79
85
  `Promise.resolve(jiti.import(${JSON.stringify(tsPath)}, {})).catch((error) => {`,
80
86
  " console.error(error);",
@@ -118,8 +124,8 @@ const HOOK_BINDINGS: Array<{
118
124
  },
119
125
  {
120
126
  stage: "turn_end",
121
- extensionKey: "onAgentEnd",
122
- sandboxHookName: "onAgentEnd",
127
+ extensionKey: "onTurnEnd",
128
+ sandboxHookName: "onTurnEnd",
123
129
  },
124
130
  {
125
131
  stage: "session_shutdown",
@@ -162,17 +168,30 @@ export async function loadSandboxedPlugins(
162
168
  const hookTimeoutMs = withTimeoutFallback(options.hookTimeoutMs, 3000);
163
169
  const contributionTimeoutMs = withTimeoutFallback(
164
170
  options.contributionTimeoutMs,
165
- 5000,
171
+ 60_000,
166
172
  );
173
+ const initArgs = {
174
+ pluginPaths: options.pluginPaths,
175
+ exportName: options.exportName,
176
+ };
177
+
178
+ // Guard against concurrent re-initialization when multiple tools/hooks
179
+ // fail simultaneously with "Unknown sandbox plugin id:".
180
+ let reinitPromise: Promise<void> | undefined;
181
+ const reinitialize = (): Promise<void> => {
182
+ reinitPromise ??= sandbox
183
+ .call<void>("initialize", initArgs, { timeoutMs: importTimeoutMs })
184
+ .finally(() => {
185
+ reinitPromise = undefined;
186
+ });
187
+ return reinitPromise;
188
+ };
167
189
 
168
190
  let descriptors: SandboxedPluginDescriptor[];
169
191
  try {
170
192
  descriptors = await sandbox.call<SandboxedPluginDescriptor[]>(
171
193
  "initialize",
172
- {
173
- pluginPaths: options.pluginPaths,
174
- exportName: options.exportName,
175
- },
194
+ initArgs,
176
195
  { timeoutMs: importTimeoutMs },
177
196
  );
178
197
  } catch (error) {
@@ -188,13 +207,31 @@ export async function loadSandboxedPlugins(
188
207
  name: descriptor.name,
189
208
  manifest: descriptor.manifest,
190
209
  setup: (api: AgentExtensionApi) => {
191
- registerTools(api, sandbox, descriptor, contributionTimeoutMs);
192
- registerCommands(api, sandbox, descriptor, contributionTimeoutMs);
210
+ registerTools(
211
+ api,
212
+ sandbox,
213
+ descriptor,
214
+ contributionTimeoutMs,
215
+ reinitialize,
216
+ );
217
+ registerCommands(
218
+ api,
219
+ sandbox,
220
+ descriptor,
221
+ contributionTimeoutMs,
222
+ reinitialize,
223
+ );
193
224
  registerSimpleContributions(api, descriptor);
194
225
  },
195
226
  };
196
227
 
197
- bindHooks(extension, sandbox, descriptor.pluginId, hookTimeoutMs);
228
+ bindHooks(
229
+ extension,
230
+ sandbox,
231
+ descriptor.pluginId,
232
+ hookTimeoutMs,
233
+ reinitialize,
234
+ );
198
235
 
199
236
  return extension;
200
237
  },
@@ -217,6 +254,7 @@ function registerTools(
217
254
  sandbox: SubprocessSandbox,
218
255
  descriptor: SandboxedPluginDescriptor,
219
256
  timeoutMs: number,
257
+ reinitialize: () => Promise<void>,
220
258
  ): void {
221
259
  for (const td of descriptor.contributions.tools) {
222
260
  const tool: Tool = {
@@ -228,17 +266,35 @@ function registerTools(
228
266
  }) as Tool["inputSchema"],
229
267
  timeoutMs: td.timeoutMs,
230
268
  retryable: td.retryable,
231
- execute: async (input: unknown, context: unknown) =>
232
- await sandbox.call(
233
- "executeTool",
234
- {
235
- pluginId: descriptor.pluginId,
236
- contributionId: td.id,
237
- input,
238
- context,
239
- },
240
- { timeoutMs },
241
- ),
269
+ execute: async (input: unknown, context: unknown) => {
270
+ try {
271
+ return await sandbox.call(
272
+ "executeTool",
273
+ {
274
+ pluginId: descriptor.pluginId,
275
+ contributionId: td.id,
276
+ input,
277
+ context,
278
+ },
279
+ { timeoutMs },
280
+ );
281
+ } catch (error) {
282
+ if (!isUnknownPluginIdError(error)) {
283
+ throw error;
284
+ }
285
+ await reinitialize();
286
+ return await sandbox.call(
287
+ "executeTool",
288
+ {
289
+ pluginId: descriptor.pluginId,
290
+ contributionId: td.id,
291
+ input,
292
+ context,
293
+ },
294
+ { timeoutMs },
295
+ );
296
+ }
297
+ },
242
298
  };
243
299
  api.registerTool(tool);
244
300
  }
@@ -249,21 +305,39 @@ function registerCommands(
249
305
  sandbox: SubprocessSandbox,
250
306
  descriptor: SandboxedPluginDescriptor,
251
307
  timeoutMs: number,
308
+ reinitialize: () => Promise<void>,
252
309
  ): void {
253
310
  for (const cd of descriptor.contributions.commands) {
254
311
  api.registerCommand({
255
312
  name: cd.name,
256
313
  description: cd.description,
257
- handler: async (input: string) =>
258
- await sandbox.call<string>(
259
- "executeCommand",
260
- {
261
- pluginId: descriptor.pluginId,
262
- contributionId: cd.id,
263
- input,
264
- },
265
- { timeoutMs },
266
- ),
314
+ handler: async (input: string) => {
315
+ try {
316
+ return await sandbox.call<string>(
317
+ "executeCommand",
318
+ {
319
+ pluginId: descriptor.pluginId,
320
+ contributionId: cd.id,
321
+ input,
322
+ },
323
+ { timeoutMs },
324
+ );
325
+ } catch (error) {
326
+ if (!isUnknownPluginIdError(error)) {
327
+ throw error;
328
+ }
329
+ await reinitialize();
330
+ return await sandbox.call<string>(
331
+ "executeCommand",
332
+ {
333
+ pluginId: descriptor.pluginId,
334
+ contributionId: cd.id,
335
+ input,
336
+ },
337
+ { timeoutMs },
338
+ );
339
+ }
340
+ },
267
341
  });
268
342
  }
269
343
  }
@@ -288,10 +362,10 @@ function registerSimpleContributions(
288
362
  });
289
363
  }
290
364
 
291
- for (const rd of descriptor.contributions.messageRenderers) {
292
- api.registerMessageRenderer({
365
+ for (const rd of descriptor.contributions.messageBuilders) {
366
+ api.registerMessageBuilder({
293
367
  name: rd.name,
294
- render: () => `[sandbox renderer ${rd.name} requires async bridge]`,
368
+ build: (m) => m,
295
369
  });
296
370
  }
297
371
 
@@ -309,13 +383,27 @@ function makeHookHandler(
309
383
  pluginId: string,
310
384
  hookName: string,
311
385
  timeoutMs: number,
386
+ reinitialize: () => Promise<void>,
312
387
  ): (payload: unknown) => Promise<unknown> {
313
- return async (payload: unknown) =>
314
- await sandbox.call(
315
- "invokeHook",
316
- { pluginId, hookName, payload },
317
- { timeoutMs },
318
- );
388
+ return async (payload: unknown) => {
389
+ try {
390
+ return await sandbox.call(
391
+ "invokeHook",
392
+ { pluginId, hookName, payload },
393
+ { timeoutMs },
394
+ );
395
+ } catch (error) {
396
+ if (!isUnknownPluginIdError(error)) {
397
+ throw error;
398
+ }
399
+ await reinitialize();
400
+ return await sandbox.call(
401
+ "invokeHook",
402
+ { pluginId, hookName, payload },
403
+ { timeoutMs },
404
+ );
405
+ }
406
+ };
319
407
  }
320
408
 
321
409
  function bindHooks(
@@ -323,6 +411,7 @@ function bindHooks(
323
411
  sandbox: SubprocessSandbox,
324
412
  pluginId: string,
325
413
  hookTimeoutMs: number,
414
+ reinitialize: () => Promise<void>,
326
415
  ): void {
327
416
  for (const { stage, extensionKey, sandboxHookName } of HOOK_BINDINGS) {
328
417
  if (hasHookStage(extension, stage)) {
@@ -331,6 +420,7 @@ function bindHooks(
331
420
  pluginId,
332
421
  sandboxHookName,
333
422
  hookTimeoutMs,
423
+ reinitialize,
334
424
  );
335
425
  // Each hook property on AgentExtension accepts (payload: unknown) => Promise<unknown>.
336
426
  // TypeScript cannot narrow a union of optional callback keys via computed access,
@@ -0,0 +1,25 @@
1
+ export {
2
+ createPersistentSubprocessHooks,
3
+ PersistentHookClient,
4
+ type PersistentHookClientOptions,
5
+ type PersistentSubprocessHookControl,
6
+ type PersistentSubprocessHooksOptions,
7
+ } from "./persistent";
8
+ export {
9
+ createSubprocessHooks,
10
+ type HookEventName,
11
+ HookEventNameSchema,
12
+ type HookEventPayload,
13
+ HookEventPayloadSchema,
14
+ parseHookEventPayload,
15
+ type RunHookOptions,
16
+ type RunHookResult,
17
+ runHook,
18
+ type SubprocessHookControl,
19
+ type SubprocessHooksOptions,
20
+ } from "./subprocess";
21
+ export {
22
+ type RunSubprocessEventOptions,
23
+ type RunSubprocessEventResult,
24
+ runSubprocessEvent,
25
+ } from "./subprocess-runner";