@ai-agent-forge/agent-forge 0.86.7 → 0.88.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 (717) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +10 -11
  3. package/dist/artifacts/artifact-store.d.ts.map +1 -1
  4. package/dist/artifacts/artifact-store.js +9 -5
  5. package/dist/artifacts/artifact-store.js.map +1 -1
  6. package/dist/bundle/.build-manifest.json +430 -413
  7. package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
  8. package/dist/bundle/chunks/chunk-HLJEVRWP.js +13 -0
  9. package/dist/bundle/chunks/chunk-YGHQME4V.js +1456 -0
  10. package/dist/bundle/chunks/image-resize-worker.js +12 -1
  11. package/dist/bundle/chunks/{virtual-modules-3IZ4MYSQ.js → virtual-modules-KZ5DRH7Q.js} +1 -1
  12. package/dist/bundle/cli.js +1 -1
  13. package/dist/bundle/client.js +1 -1
  14. package/dist/bundle/index.js +2 -2
  15. package/dist/bundle/rpc-entry.js +1 -1
  16. package/dist/cli/args.d.ts.map +1 -1
  17. package/dist/cli/args.js +231 -185
  18. package/dist/cli/args.js.map +1 -1
  19. package/dist/cli/auth-check.d.ts.map +1 -1
  20. package/dist/cli/auth-check.js +17 -4
  21. package/dist/cli/auth-check.js.map +1 -1
  22. package/dist/cli/auth-command.d.ts.map +1 -1
  23. package/dist/cli/auth-command.js +15 -9
  24. package/dist/cli/auth-command.js.map +1 -1
  25. package/dist/cli/credential-print.d.ts.map +1 -1
  26. package/dist/cli/credential-print.js +14 -7
  27. package/dist/cli/credential-print.js.map +1 -1
  28. package/dist/cli/experimental/command.d.ts.map +1 -1
  29. package/dist/cli/experimental/command.js +6 -5
  30. package/dist/cli/experimental/command.js.map +1 -1
  31. package/dist/cli/list-models.d.ts.map +1 -1
  32. package/dist/cli/list-models.js +9 -8
  33. package/dist/cli/list-models.js.map +1 -1
  34. package/dist/cli/plugin-manager-controller.d.ts.map +1 -1
  35. package/dist/cli/plugin-manager-controller.js +2 -1
  36. package/dist/cli/plugin-manager-controller.js.map +1 -1
  37. package/dist/cli/serve.d.ts.map +1 -1
  38. package/dist/cli/serve.js +8 -5
  39. package/dist/cli/serve.js.map +1 -1
  40. package/dist/client/remote-session.d.ts.map +1 -1
  41. package/dist/client/remote-session.js +16 -9
  42. package/dist/client/remote-session.js.map +1 -1
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js +5 -3
  45. package/dist/config.js.map +1 -1
  46. package/dist/core/agent-capability-contract.d.ts +0 -7
  47. package/dist/core/agent-capability-contract.d.ts.map +1 -1
  48. package/dist/core/agent-capability-contract.js +72 -68
  49. package/dist/core/agent-capability-contract.js.map +1 -1
  50. package/dist/core/agent-session-bash.d.ts.map +1 -1
  51. package/dist/core/agent-session-bash.js +5 -4
  52. package/dist/core/agent-session-bash.js.map +1 -1
  53. package/dist/core/agent-session-compaction.d.ts +6 -10
  54. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  55. package/dist/core/agent-session-compaction.js +35 -133
  56. package/dist/core/agent-session-compaction.js.map +1 -1
  57. package/dist/core/agent-session-context.d.ts.map +1 -1
  58. package/dist/core/agent-session-context.js +18 -13
  59. package/dist/core/agent-session-context.js.map +1 -1
  60. package/dist/core/agent-session-internal.d.ts +0 -6
  61. package/dist/core/agent-session-internal.d.ts.map +1 -1
  62. package/dist/core/agent-session-internal.js.map +1 -1
  63. package/dist/core/agent-session-model.d.ts.map +1 -1
  64. package/dist/core/agent-session-model.js +2 -1
  65. package/dist/core/agent-session-model.js.map +1 -1
  66. package/dist/core/agent-session-retry.d.ts.map +1 -1
  67. package/dist/core/agent-session-retry.js +3 -3
  68. package/dist/core/agent-session-retry.js.map +1 -1
  69. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  70. package/dist/core/agent-session-runtime.js +7 -6
  71. package/dist/core/agent-session-runtime.js.map +1 -1
  72. package/dist/core/agent-session-services.d.ts +1 -1
  73. package/dist/core/agent-session-services.d.ts.map +1 -1
  74. package/dist/core/agent-session-services.js.map +1 -1
  75. package/dist/core/agent-session-tools.d.ts.map +1 -1
  76. package/dist/core/agent-session-tools.js +3 -2
  77. package/dist/core/agent-session-tools.js.map +1 -1
  78. package/dist/core/agent-session.d.ts +40 -22
  79. package/dist/core/agent-session.d.ts.map +1 -1
  80. package/dist/core/agent-session.js +147 -67
  81. package/dist/core/agent-session.js.map +1 -1
  82. package/dist/core/auth-guidance.d.ts.map +1 -1
  83. package/dist/core/auth-guidance.js +11 -5
  84. package/dist/core/auth-guidance.js.map +1 -1
  85. package/dist/core/auth-storage.d.ts.map +1 -1
  86. package/dist/core/auth-storage.js +9 -6
  87. package/dist/core/auth-storage.js.map +1 -1
  88. package/dist/core/compaction/compaction.d.ts.map +1 -1
  89. package/dist/core/compaction/compaction.js +2 -1
  90. package/dist/core/compaction/compaction.js.map +1 -1
  91. package/dist/core/embedded-sdk.d.ts.map +1 -1
  92. package/dist/core/embedded-sdk.js +10 -6
  93. package/dist/core/embedded-sdk.js.map +1 -1
  94. package/dist/core/export-html/index.d.ts.map +1 -1
  95. package/dist/core/export-html/index.js +9 -4
  96. package/dist/core/export-html/index.js.map +1 -1
  97. package/dist/core/extensions/agent-composition.d.ts.map +1 -1
  98. package/dist/core/extensions/agent-composition.js +26 -19
  99. package/dist/core/extensions/agent-composition.js.map +1 -1
  100. package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
  101. package/dist/core/extensions/bootstrap-agent-loop.js +3 -2
  102. package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
  103. package/dist/core/extensions/bootstrap-compaction-policy.d.ts.map +1 -1
  104. package/dist/core/extensions/bootstrap-compaction-policy.js +0 -34
  105. package/dist/core/extensions/bootstrap-compaction-policy.js.map +1 -1
  106. package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
  107. package/dist/core/extensions/bootstrap-lifecycle.js +20 -17
  108. package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
  109. package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -1
  110. package/dist/core/extensions/bootstrap-overflow-policy.js +2 -1
  111. package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -1
  112. package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -1
  113. package/dist/core/extensions/bootstrap-retry-policy.js +4 -3
  114. package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -1
  115. package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -1
  116. package/dist/core/extensions/bootstrap-skills.js +7 -6
  117. package/dist/core/extensions/bootstrap-skills.js.map +1 -1
  118. package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -1
  119. package/dist/core/extensions/bootstrap-tools.js +2 -1
  120. package/dist/core/extensions/bootstrap-tools.js.map +1 -1
  121. package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
  122. package/dist/core/extensions/capability-plugin.js +37 -13
  123. package/dist/core/extensions/capability-plugin.js.map +1 -1
  124. package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -1
  125. package/dist/core/extensions/capability-runtime-events.js +17 -13
  126. package/dist/core/extensions/capability-runtime-events.js.map +1 -1
  127. package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -1
  128. package/dist/core/extensions/capability-runtime-guards.js +16 -15
  129. package/dist/core/extensions/capability-runtime-guards.js.map +1 -1
  130. package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -1
  131. package/dist/core/extensions/capability-runtime-manifest.js +52 -30
  132. package/dist/core/extensions/capability-runtime-manifest.js.map +1 -1
  133. package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -1
  134. package/dist/core/extensions/capability-runtime-validation.js +66 -65
  135. package/dist/core/extensions/capability-runtime-validation.js.map +1 -1
  136. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  137. package/dist/core/extensions/capability-runtime.js +147 -127
  138. package/dist/core/extensions/capability-runtime.js.map +1 -1
  139. package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -1
  140. package/dist/core/extensions/compaction-memory-failure-mode.js +3 -2
  141. package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -1
  142. package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -1
  143. package/dist/core/extensions/context-strategy-binding.js +7 -4
  144. package/dist/core/extensions/context-strategy-binding.js.map +1 -1
  145. package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
  146. package/dist/core/extensions/lifecycle-catalog.js +290 -279
  147. package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
  148. package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -1
  149. package/dist/core/extensions/lifecycle-delivery-queue.js +3 -2
  150. package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -1
  151. package/dist/core/extensions/provider-failover.d.ts +7 -3
  152. package/dist/core/extensions/provider-failover.d.ts.map +1 -1
  153. package/dist/core/extensions/provider-failover.js +9 -8
  154. package/dist/core/extensions/provider-failover.js.map +1 -1
  155. package/dist/core/facade/coding-agent-facade.d.ts +6 -6
  156. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  157. package/dist/core/facade/coding-agent-facade.js +2 -3
  158. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  159. package/dist/core/http-dispatcher.d.ts.map +1 -1
  160. package/dist/core/http-dispatcher.js +2 -1
  161. package/dist/core/http-dispatcher.js.map +1 -1
  162. package/dist/core/i18n/index.d.ts +14 -0
  163. package/dist/core/i18n/index.d.ts.map +1 -0
  164. package/dist/core/i18n/index.js +67 -0
  165. package/dist/core/i18n/index.js.map +1 -0
  166. package/dist/core/i18n/locales/en/example.d.ts +7 -0
  167. package/dist/core/i18n/locales/en/example.d.ts.map +1 -0
  168. package/dist/core/i18n/locales/en/example.js +7 -0
  169. package/dist/core/i18n/locales/en/example.js.map +1 -0
  170. package/dist/core/i18n/locales/zh-cn/cli.d.ts +8 -0
  171. package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -0
  172. package/dist/core/i18n/locales/zh-cn/cli.js +229 -0
  173. package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -0
  174. package/dist/core/i18n/locales/zh-cn/common.d.ts +6 -0
  175. package/dist/core/i18n/locales/zh-cn/common.d.ts.map +1 -0
  176. package/dist/core/i18n/locales/zh-cn/common.js +6 -0
  177. package/dist/core/i18n/locales/zh-cn/common.js.map +1 -0
  178. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +13 -0
  179. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -0
  180. package/dist/core/i18n/locales/zh-cn/core-contract-core.js +173 -0
  181. package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -0
  182. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts +12 -0
  183. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -0
  184. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +582 -0
  185. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -0
  186. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +9 -0
  187. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -0
  188. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +55 -0
  189. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -0
  190. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts +11 -0
  191. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -0
  192. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +455 -0
  193. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -0
  194. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts +9 -0
  195. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -0
  196. package/dist/core/i18n/locales/zh-cn/core-errors.js +191 -0
  197. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -0
  198. package/dist/core/i18n/locales/zh-cn/example.d.ts +7 -0
  199. package/dist/core/i18n/locales/zh-cn/example.d.ts.map +1 -0
  200. package/dist/core/i18n/locales/zh-cn/example.js +10 -0
  201. package/dist/core/i18n/locales/zh-cn/example.js.map +1 -0
  202. package/dist/core/i18n/locales/zh-cn/index.d.ts +2 -0
  203. package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -0
  204. package/dist/core/i18n/locales/zh-cn/index.js +41 -0
  205. package/dist/core/i18n/locales/zh-cn/index.js.map +1 -0
  206. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts +10 -0
  207. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -0
  208. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +267 -0
  209. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -0
  210. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts +11 -0
  211. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts.map +1 -0
  212. package/dist/core/i18n/locales/zh-cn/keybindings.js +67 -0
  213. package/dist/core/i18n/locales/zh-cn/keybindings.js.map +1 -0
  214. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts +7 -0
  215. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -0
  216. package/dist/core/i18n/locales/zh-cn/slash-commands.js +39 -0
  217. package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -0
  218. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts +10 -0
  219. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts.map +1 -0
  220. package/dist/core/i18n/locales/zh-cn/tui-builtin.js +15 -0
  221. package/dist/core/i18n/locales/zh-cn/tui-builtin.js.map +1 -0
  222. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts +13 -0
  223. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -0
  224. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +102 -0
  225. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -0
  226. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts +12 -0
  227. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts.map +1 -0
  228. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js +286 -0
  229. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js.map +1 -0
  230. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts +9 -0
  231. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts.map +1 -0
  232. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js +79 -0
  233. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js.map +1 -0
  234. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts +8 -0
  235. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts.map +1 -0
  236. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js +72 -0
  237. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js.map +1 -0
  238. package/dist/core/keybindings.d.ts +15 -0
  239. package/dist/core/keybindings.d.ts.map +1 -1
  240. package/dist/core/keybindings.js +18 -0
  241. package/dist/core/keybindings.js.map +1 -1
  242. package/dist/core/logger.d.ts.map +1 -1
  243. package/dist/core/logger.js +5 -1
  244. package/dist/core/logger.js.map +1 -1
  245. package/dist/core/model-config.d.ts +0 -1
  246. package/dist/core/model-config.d.ts.map +1 -1
  247. package/dist/core/model-config.js +9 -1
  248. package/dist/core/model-config.js.map +1 -1
  249. package/dist/core/model-registry.d.ts.map +1 -1
  250. package/dist/core/model-registry.js +2 -1
  251. package/dist/core/model-registry.js.map +1 -1
  252. package/dist/core/model-runtime.d.ts.map +1 -1
  253. package/dist/core/model-runtime.js +11 -7
  254. package/dist/core/model-runtime.js.map +1 -1
  255. package/dist/core/package-install-host.d.ts.map +1 -1
  256. package/dist/core/package-install-host.js +4 -3
  257. package/dist/core/package-install-host.js.map +1 -1
  258. package/dist/core/package-manager.d.ts.map +1 -1
  259. package/dist/core/package-manager.js +15 -10
  260. package/dist/core/package-manager.js.map +1 -1
  261. package/dist/core/package-resource-collection.d.ts.map +1 -1
  262. package/dist/core/package-resource-collection.js +2 -1
  263. package/dist/core/package-resource-collection.js.map +1 -1
  264. package/dist/core/package-source.d.ts.map +1 -1
  265. package/dist/core/package-source.js +3 -2
  266. package/dist/core/package-source.js.map +1 -1
  267. package/dist/core/provider-composer.d.ts +2 -2
  268. package/dist/core/provider-composer.d.ts.map +1 -1
  269. package/dist/core/provider-composer.js +29 -21
  270. package/dist/core/provider-composer.js.map +1 -1
  271. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  272. package/dist/core/remote-catalog-provider.js +6 -2
  273. package/dist/core/remote-catalog-provider.js.map +1 -1
  274. package/dist/core/resolve-config-value.d.ts.map +1 -1
  275. package/dist/core/resolve-config-value.js +15 -5
  276. package/dist/core/resolve-config-value.js.map +1 -1
  277. package/dist/core/sdk.d.ts +27 -5
  278. package/dist/core/sdk.d.ts.map +1 -1
  279. package/dist/core/sdk.js +80 -55
  280. package/dist/core/sdk.js.map +1 -1
  281. package/dist/core/session-cwd.d.ts.map +1 -1
  282. package/dist/core/session-cwd.js +5 -2
  283. package/dist/core/session-cwd.js.map +1 -1
  284. package/dist/core/session-export.d.ts.map +1 -1
  285. package/dist/core/session-export.js +2 -1
  286. package/dist/core/session-export.js.map +1 -1
  287. package/dist/core/session-manager.d.ts.map +1 -1
  288. package/dist/core/session-manager.js +39 -29
  289. package/dist/core/session-manager.js.map +1 -1
  290. package/dist/core/session-storage.d.ts.map +1 -1
  291. package/dist/core/session-storage.js +3 -3
  292. package/dist/core/session-storage.js.map +1 -1
  293. package/dist/core/settings-manager.d.ts +20 -20
  294. package/dist/core/settings-manager.d.ts.map +1 -1
  295. package/dist/core/settings-manager.js +47 -59
  296. package/dist/core/settings-manager.js.map +1 -1
  297. package/dist/core/slash-commands.d.ts.map +1 -1
  298. package/dist/core/slash-commands.js +53 -32
  299. package/dist/core/slash-commands.js.map +1 -1
  300. package/dist/core/system-prompt.d.ts.map +1 -1
  301. package/dist/core/system-prompt.js +25 -2
  302. package/dist/core/system-prompt.js.map +1 -1
  303. package/dist/core/tools/bash.d.ts.map +1 -1
  304. package/dist/core/tools/bash.js +11 -7
  305. package/dist/core/tools/bash.js.map +1 -1
  306. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  307. package/dist/core/tools/edit-diff.js +9 -4
  308. package/dist/core/tools/edit-diff.js.map +1 -1
  309. package/dist/core/tools/edit.d.ts.map +1 -1
  310. package/dist/core/tools/edit.js +4 -3
  311. package/dist/core/tools/edit.js.map +1 -1
  312. package/dist/core/tools/index.d.ts.map +1 -1
  313. package/dist/core/tools/index.js +3 -2
  314. package/dist/core/tools/index.js.map +1 -1
  315. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  316. package/dist/core/tools/output-accumulator.js +2 -1
  317. package/dist/core/tools/output-accumulator.js.map +1 -1
  318. package/dist/core/tools/read.d.ts.map +1 -1
  319. package/dist/core/tools/read.js +6 -2
  320. package/dist/core/tools/read.js.map +1 -1
  321. package/dist/core/tools/write.d.ts.map +1 -1
  322. package/dist/core/tools/write.js +2 -1
  323. package/dist/core/tools/write.js.map +1 -1
  324. package/dist/durable/durable-service.d.ts.map +1 -1
  325. package/dist/durable/durable-service.js +25 -18
  326. package/dist/durable/durable-service.js.map +1 -1
  327. package/dist/host/checkpoint-commit.d.ts.map +1 -1
  328. package/dist/host/checkpoint-commit.js +2 -1
  329. package/dist/host/checkpoint-commit.js.map +1 -1
  330. package/dist/host/manual-compaction.d.ts.map +1 -1
  331. package/dist/host/manual-compaction.js +2 -1
  332. package/dist/host/manual-compaction.js.map +1 -1
  333. package/dist/host/output-projection.d.ts +0 -13
  334. package/dist/host/output-projection.d.ts.map +1 -1
  335. package/dist/host/output-projection.js +16 -2
  336. package/dist/host/output-projection.js.map +1 -1
  337. package/dist/host/summary-retry.d.ts.map +1 -1
  338. package/dist/host/summary-retry.js +3 -2
  339. package/dist/host/summary-retry.js.map +1 -1
  340. package/dist/main.d.ts.map +1 -1
  341. package/dist/main.js +97 -60
  342. package/dist/main.js.map +1 -1
  343. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  344. package/dist/modes/interactive/components/agents-view.js +18 -15
  345. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  346. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  347. package/dist/modes/interactive/components/assistant-message.js +6 -5
  348. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  349. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/bash-execution.js +12 -7
  351. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  352. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/bordered-loader.js +2 -1
  354. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  355. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  356. package/dist/modes/interactive/components/branch-summary-message.js +6 -5
  357. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  358. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  359. package/dist/modes/interactive/components/compaction-summary-message.js +9 -5
  360. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  361. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  362. package/dist/modes/interactive/components/config-selector.js +18 -15
  363. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  364. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  365. package/dist/modes/interactive/components/custom-entry.js +2 -1
  366. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  367. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  368. package/dist/modes/interactive/components/dialog-editor.js +5 -4
  369. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  370. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  371. package/dist/modes/interactive/components/dialog-input.js +2 -1
  372. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  373. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  374. package/dist/modes/interactive/components/dialog-selector.js +4 -3
  375. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  376. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/first-time-setup.js +11 -10
  378. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  379. package/dist/modes/interactive/components/footer.d.ts +0 -2
  380. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  381. package/dist/modes/interactive/components/footer.js +8 -10
  382. package/dist/modes/interactive/components/footer.js.map +1 -1
  383. package/dist/modes/interactive/components/index.d.ts +1 -0
  384. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  385. package/dist/modes/interactive/components/index.js +1 -0
  386. package/dist/modes/interactive/components/index.js.map +1 -1
  387. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  388. package/dist/modes/interactive/components/keybinding-hints.js +3 -2
  389. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  390. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/login-dialog.js +12 -11
  392. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  393. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  394. package/dist/modes/interactive/components/mermaid.js +6 -2
  395. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  396. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/model-selector.js +28 -16
  398. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  399. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  400. package/dist/modes/interactive/components/oauth-selector.js +10 -9
  401. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  402. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  403. package/dist/modes/interactive/components/plugin-manager-entry.js +22 -13
  404. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  405. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  406. package/dist/modes/interactive/components/plugin-selection-entry.js +27 -12
  407. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  408. package/dist/modes/interactive/components/queue-manager-selector.d.ts +60 -0
  409. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -0
  410. package/dist/modes/interactive/components/queue-manager-selector.js +166 -0
  411. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -0
  412. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  413. package/dist/modes/interactive/components/scoped-models-selector.js +16 -14
  414. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  415. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  416. package/dist/modes/interactive/components/session-selector.js +43 -31
  417. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  418. package/dist/modes/interactive/components/settings-selector.d.ts +4 -6
  419. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  420. package/dist/modes/interactive/components/settings-selector.js +115 -120
  421. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  422. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  423. package/dist/modes/interactive/components/settings-submenu.js +5 -4
  424. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  425. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  426. package/dist/modes/interactive/components/show-images-selector.js +3 -2
  427. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  428. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  429. package/dist/modes/interactive/components/skill-invocation-message.js +4 -3
  430. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  431. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  432. package/dist/modes/interactive/components/status-indicator.js +14 -5
  433. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  434. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/theme-selector.js +2 -1
  436. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  437. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/thinking-selector.js +11 -4
  439. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  440. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  441. package/dist/modes/interactive/components/tool-execution.js +8 -3
  442. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  443. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  444. package/dist/modes/interactive/components/tree-list.js +7 -6
  445. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  446. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  447. package/dist/modes/interactive/components/tree-render.js +28 -23
  448. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  449. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/tree-selector.js +9 -7
  451. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  452. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/user-message-selector.js +5 -4
  454. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  455. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/workflow-view.js +36 -21
  457. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  458. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  459. package/dist/modes/interactive/external-editor.js +2 -1
  460. package/dist/modes/interactive/external-editor.js.map +1 -1
  461. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  462. package/dist/modes/interactive/interactive-auth.js +71 -40
  463. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  464. package/dist/modes/interactive/interactive-commands.d.ts +1 -0
  465. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  466. package/dist/modes/interactive/interactive-commands.js +3 -0
  467. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  468. package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -1
  469. package/dist/modes/interactive/interactive-dialog-ui.js +5 -5
  470. package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -1
  471. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  472. package/dist/modes/interactive/interactive-format.js +34 -18
  473. package/dist/modes/interactive/interactive-format.js.map +1 -1
  474. package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -1
  475. package/dist/modes/interactive/interactive-helpers.js +7 -2
  476. package/dist/modes/interactive/interactive-helpers.js.map +1 -1
  477. package/dist/modes/interactive/interactive-mode.d.ts +4 -2
  478. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  479. package/dist/modes/interactive/interactive-mode.js +350 -279
  480. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  481. package/dist/modes/interactive/interactive-selectors.d.ts +9 -0
  482. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  483. package/dist/modes/interactive/interactive-selectors.js +79 -25
  484. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  485. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  486. package/dist/modes/interactive/theme/theme-controller.js +5 -1
  487. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  488. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  489. package/dist/modes/interactive/theme/theme.js +26 -23
  490. package/dist/modes/interactive/theme/theme.js.map +1 -1
  491. package/dist/modes/json-event.d.ts.map +1 -1
  492. package/dist/modes/json-event.js +3 -2
  493. package/dist/modes/json-event.js.map +1 -1
  494. package/dist/modes/print-mode.d.ts.map +1 -1
  495. package/dist/modes/print-mode.js +3 -2
  496. package/dist/modes/print-mode.js.map +1 -1
  497. package/dist/modes/rpc/rpc-client.d.ts +0 -8
  498. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  499. package/dist/modes/rpc/rpc-client.js +3 -14
  500. package/dist/modes/rpc/rpc-client.js.map +1 -1
  501. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  502. package/dist/modes/rpc/rpc-mode.js +0 -9
  503. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  504. package/dist/modes/rpc/rpc-types.d.ts +0 -19
  505. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  506. package/dist/modes/rpc/rpc-types.js.map +1 -1
  507. package/dist/package-manager-cli.d.ts.map +1 -1
  508. package/dist/package-manager-cli.js +28 -13
  509. package/dist/package-manager-cli.js.map +1 -1
  510. package/dist/plugins/ecosystem/catalog.d.ts.map +1 -1
  511. package/dist/plugins/ecosystem/catalog.js +3 -2
  512. package/dist/plugins/ecosystem/catalog.js.map +1 -1
  513. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  514. package/dist/plugins/ecosystem/cli.js +2 -1
  515. package/dist/plugins/ecosystem/cli.js.map +1 -1
  516. package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -1
  517. package/dist/plugins/ecosystem/default-plugin-market.js +3 -2
  518. package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -1
  519. package/dist/plugins/ecosystem/distribution.d.ts.map +1 -1
  520. package/dist/plugins/ecosystem/distribution.js +2 -1
  521. package/dist/plugins/ecosystem/distribution.js.map +1 -1
  522. package/dist/plugins/ecosystem/installer.d.ts.map +1 -1
  523. package/dist/plugins/ecosystem/installer.js +3 -2
  524. package/dist/plugins/ecosystem/installer.js.map +1 -1
  525. package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
  526. package/dist/plugins/ecosystem/node-disk-registry-source.js +20 -17
  527. package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
  528. package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -1
  529. package/dist/plugins/ecosystem/node-distribution-host.js +35 -34
  530. package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -1
  531. package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
  532. package/dist/plugins/ecosystem/node-npm-registry-source.js +35 -34
  533. package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
  534. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
  535. package/dist/plugins/ecosystem/node-package-install-host.js +9 -8
  536. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
  537. package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
  538. package/dist/plugins/ecosystem/node-package-install-persistence.js +4 -3
  539. package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
  540. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +9 -2
  541. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  542. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +44 -5
  543. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  544. package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -1
  545. package/dist/plugins/ecosystem/node-plugin-trust-root.js +10 -9
  546. package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -1
  547. package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -1
  548. package/dist/plugins/ecosystem/node-registry-source.js +31 -30
  549. package/dist/plugins/ecosystem/node-registry-source.js.map +1 -1
  550. package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -1
  551. package/dist/plugins/ecosystem/node-release-package-source.js +30 -29
  552. package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -1
  553. package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -1
  554. package/dist/plugins/ecosystem/node-tar-writer.js +11 -10
  555. package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -1
  556. package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -1
  557. package/dist/plugins/ecosystem/node-url-package-source.js +21 -20
  558. package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -1
  559. package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -1
  560. package/dist/plugins/ecosystem/plugin-acquisition.js +3 -2
  561. package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -1
  562. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +9 -1
  563. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
  564. package/dist/plugins/ecosystem/plugin-bootstrap.js +5 -0
  565. package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -1
  566. package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -1
  567. package/dist/plugins/ecosystem/registry-cli-adapter.js +2 -1
  568. package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -1
  569. package/dist/plugins/ecosystem/registry.d.ts.map +1 -1
  570. package/dist/plugins/ecosystem/registry.js +35 -32
  571. package/dist/plugins/ecosystem/registry.js.map +1 -1
  572. package/dist/plugins/ecosystem/resolver.d.ts.map +1 -1
  573. package/dist/plugins/ecosystem/resolver.js +3 -2
  574. package/dist/plugins/ecosystem/resolver.js.map +1 -1
  575. package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -1
  576. package/dist/plugins/ecosystem/selection-store.js +11 -10
  577. package/dist/plugins/ecosystem/selection-store.js.map +1 -1
  578. package/dist/plugins/ecosystem/selection.d.ts.map +1 -1
  579. package/dist/plugins/ecosystem/selection.js +8 -7
  580. package/dist/plugins/ecosystem/selection.js.map +1 -1
  581. package/dist/plugins/ecosystem/state.d.ts.map +1 -1
  582. package/dist/plugins/ecosystem/state.js +24 -23
  583. package/dist/plugins/ecosystem/state.js.map +1 -1
  584. package/dist/plugins/ecosystem/updates.d.ts.map +1 -1
  585. package/dist/plugins/ecosystem/updates.js +5 -4
  586. package/dist/plugins/ecosystem/updates.js.map +1 -1
  587. package/dist/plugins/mcp-http.d.ts +0 -17
  588. package/dist/plugins/mcp-http.d.ts.map +1 -1
  589. package/dist/plugins/mcp-http.js +30 -7
  590. package/dist/plugins/mcp-http.js.map +1 -1
  591. package/dist/plugins/plugin-supervisor.d.ts.map +1 -1
  592. package/dist/plugins/plugin-supervisor.js +19 -1
  593. package/dist/plugins/plugin-supervisor.js.map +1 -1
  594. package/dist/profile/first-roles.d.ts.map +1 -1
  595. package/dist/profile/first-roles.js +10 -1
  596. package/dist/profile/first-roles.js.map +1 -1
  597. package/dist/profile/goal-plugin.d.ts.map +1 -1
  598. package/dist/profile/goal-plugin.js +24 -5
  599. package/dist/profile/goal-plugin.js.map +1 -1
  600. package/dist/profile/identity.d.ts.map +1 -1
  601. package/dist/profile/identity.js +7 -6
  602. package/dist/profile/identity.js.map +1 -1
  603. package/dist/profile/lock.d.ts.map +1 -1
  604. package/dist/profile/lock.js +15 -1
  605. package/dist/profile/lock.js.map +1 -1
  606. package/dist/profile/plan-plugin.d.ts.map +1 -1
  607. package/dist/profile/plan-plugin.js +26 -13
  608. package/dist/profile/plan-plugin.js.map +1 -1
  609. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  610. package/dist/profile/plugin-profiles.js +2 -1
  611. package/dist/profile/plugin-profiles.js.map +1 -1
  612. package/dist/profile/policy-manifest.d.ts.map +1 -1
  613. package/dist/profile/policy-manifest.js +5 -4
  614. package/dist/profile/policy-manifest.js.map +1 -1
  615. package/dist/profile/profile-registry.d.ts +0 -12
  616. package/dist/profile/profile-registry.d.ts.map +1 -1
  617. package/dist/profile/profile-registry.js +14 -1
  618. package/dist/profile/profile-registry.js.map +1 -1
  619. package/dist/profile/role-catalog.d.ts +0 -1
  620. package/dist/profile/role-catalog.d.ts.map +1 -1
  621. package/dist/profile/role-catalog.js +17 -15
  622. package/dist/profile/role-catalog.js.map +1 -1
  623. package/dist/profile/role-orchestrator.d.ts.map +1 -1
  624. package/dist/profile/role-orchestrator.js +8 -7
  625. package/dist/profile/role-orchestrator.js.map +1 -1
  626. package/dist/profile/role-runner.d.ts.map +1 -1
  627. package/dist/profile/role-runner.js +3 -2
  628. package/dist/profile/role-runner.js.map +1 -1
  629. package/dist/profile/root-facade.d.ts.map +1 -1
  630. package/dist/profile/root-facade.js +2 -1
  631. package/dist/profile/root-facade.js.map +1 -1
  632. package/dist/profile/skill-discovery-wiring.d.ts.map +1 -1
  633. package/dist/profile/skill-discovery-wiring.js +7 -2
  634. package/dist/profile/skill-discovery-wiring.js.map +1 -1
  635. package/dist/profile/state-store.d.ts.map +1 -1
  636. package/dist/profile/state-store.js +13 -9
  637. package/dist/profile/state-store.js.map +1 -1
  638. package/dist/profile/todo-plugin.d.ts.map +1 -1
  639. package/dist/profile/todo-plugin.js +9 -4
  640. package/dist/profile/todo-plugin.js.map +1 -1
  641. package/dist/profiles/builtin-suites.d.ts +13 -6
  642. package/dist/profiles/builtin-suites.d.ts.map +1 -1
  643. package/dist/profiles/builtin-suites.js +15 -6
  644. package/dist/profiles/builtin-suites.js.map +1 -1
  645. package/dist/profiles/suite-loader.d.ts +25 -1
  646. package/dist/profiles/suite-loader.d.ts.map +1 -1
  647. package/dist/profiles/suite-loader.js +34 -9
  648. package/dist/profiles/suite-loader.js.map +1 -1
  649. package/dist/remote/server-entry.d.ts.map +1 -1
  650. package/dist/remote/server-entry.js +3 -2
  651. package/dist/remote/server-entry.js.map +1 -1
  652. package/dist/remote/session-source.d.ts.map +1 -1
  653. package/dist/remote/session-source.js +8 -4
  654. package/dist/remote/session-source.js.map +1 -1
  655. package/dist/share/session-share.d.ts.map +1 -1
  656. package/dist/share/session-share.js +14 -2
  657. package/dist/share/session-share.js.map +1 -1
  658. package/dist/testing/plugin-testkit.d.ts.map +1 -1
  659. package/dist/testing/plugin-testkit.js +4 -3
  660. package/dist/testing/plugin-testkit.js.map +1 -1
  661. package/dist/testing/runtime-delivery-queue.d.ts.map +1 -1
  662. package/dist/testing/runtime-delivery-queue.js +2 -1
  663. package/dist/testing/runtime-delivery-queue.js.map +1 -1
  664. package/dist/testing/session-plugin-testkit.d.ts.map +1 -1
  665. package/dist/testing/session-plugin-testkit.js +10 -7
  666. package/dist/testing/session-plugin-testkit.js.map +1 -1
  667. package/dist/utils/ansi.d.ts.map +1 -1
  668. package/dist/utils/ansi.js +2 -1
  669. package/dist/utils/ansi.js.map +1 -1
  670. package/dist/utils/clipboard.d.ts.map +1 -1
  671. package/dist/utils/clipboard.js +7 -6
  672. package/dist/utils/clipboard.js.map +1 -1
  673. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  674. package/dist/utils/image-resize-worker.js +3 -2
  675. package/dist/utils/image-resize-worker.js.map +1 -1
  676. package/dist/utils/photon.d.ts +2 -2
  677. package/dist/utils/photon.d.ts.map +1 -1
  678. package/dist/utils/photon.js +2 -2
  679. package/dist/utils/photon.js.map +1 -1
  680. package/dist/utils/shell.d.ts.map +1 -1
  681. package/dist/utils/shell.js +9 -8
  682. package/dist/utils/shell.js.map +1 -1
  683. package/dist/utils/tools-manager.d.ts.map +1 -1
  684. package/dist/utils/tools-manager.js +23 -13
  685. package/dist/utils/tools-manager.js.map +1 -1
  686. package/dist/utils/version-check.d.ts.map +1 -1
  687. package/dist/utils/version-check.js +5 -1
  688. package/dist/utils/version-check.js.map +1 -1
  689. package/docs/compaction.md +1 -3
  690. package/docs/docs.json +4 -0
  691. package/docs/index.md +1 -0
  692. package/docs/keybindings.md +3 -0
  693. package/docs/mcp.md +103 -0
  694. package/docs/models.md +14 -22
  695. package/docs/providers.md +0 -1
  696. package/docs/quickstart.md +1 -1
  697. package/docs/rpc.md +1 -26
  698. package/docs/sdk.md +4 -6
  699. package/docs/settings.md +10 -12
  700. package/docs/skills.md +1 -9
  701. package/docs/terminal-setup.md +2 -3
  702. package/docs/usage.md +7 -6
  703. package/examples/extensions/with-deps/package-lock.json +2 -2
  704. package/examples/extensions/with-deps/package.json +1 -1
  705. package/examples/extensions/with-deps/plugin.json +1 -1
  706. package/examples/sdk/10-settings.ts +2 -4
  707. package/examples/sdk/12-full-control.ts +1 -2
  708. package/package.json +1 -3
  709. package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
  710. package/dist/core/extensions/microcompact.d.ts +0 -80
  711. package/dist/core/extensions/microcompact.d.ts.map +0 -1
  712. package/dist/core/extensions/microcompact.js +0 -134
  713. package/dist/core/extensions/microcompact.js.map +0 -1
  714. package/dist/server/create-harness.d.ts +0 -26
  715. package/dist/server/create-harness.d.ts.map +0 -1
  716. package/dist/server/create-harness.js +0 -106
  717. package/dist/server/create-harness.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/installer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PluginDistributionArtifactV1 } from \"./distribution.ts\";\nimport type { HostFactsV1, PluginSourceVerifierV1, PluginUpdateRecordV1 } from \"./types.ts\";\n\nimport { stagePluginUpdateV1, type UpdateVerificationV1, verifyPluginUpdateV1 } from \"./updates.ts\";\n\nconst MAX_INSTALLATION_REF_CHARS_V1 = 2048;\nexport const MAX_PLUGIN_SCOPE_REF_CHARS_V1 = 2048;\n/** Stable host namespace for installations that are not project-local. */\nexport const DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1 = \"global:default\";\n\nexport type PluginInstallationScopeV1 = \"global\" | \"project\";\n\ninterface PluginScopeIdentityV1 {\n\treadonly scope: PluginInstallationScopeV1;\n\t/** Opaque host namespace; it must never disclose a local project path. */\n\treadonly scopeRef: string;\n}\n\nexport interface PluginInstallationV1 {\n\treadonly version: 1;\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\t/** The host installation namespace. It is part of the opaque installation identity. */\n\treadonly scope: PluginInstallationScopeV1;\n\t/** Concrete host namespace that distinguishes global and individual project installations. */\n\treadonly scopeRef?: string;\n\t/** Opaque host-owned installation handle; never a local path. */\n\treadonly installationRef: string;\n\treadonly state: \"installed\" | \"active\" | \"retained\";\n}\n\nexport interface PluginInstallHostV1 {\n\t/**\n\t * Scopes that this host can isolate physically. Omitting this declaration\n\t * preserves the legacy global-only host behavior; project operations must be\n\t * declared explicitly.\n\t */\n\treadonly supportedScopes?: readonly PluginInstallationScopeV1[];\n\t/** Host operations are atomic from the installer's perspective: an abort may\n\t * prevent starting work, but once a method resolves its side effect is committed. */\n\tinstall(input: {\n\t\treadonly record: PluginUpdateRecordV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\t/** A host-owned, digest-bound package reference. Package bytes never cross this contract. */\n\t\treadonly artifact?: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<{\n\t\treadonly installationRef: string;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t}>;\n\tactivate(input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly record: PluginUpdateRecordV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void>;\n\trollback(input: {\n\t\treadonly failed: PluginInstallationV1;\n\t\treadonly previous: PluginInstallationV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void>;\n\t/**\n\t * Remove a host-owned installation. The method is optional so hosts can\n\t * still expose state-only management while they are migrating; callers that\n\t * need physical cleanup must treat a missing method as unsupported.\n\t */\n\tuninstall?: (input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => Promise<void>;\n}\n\nexport interface PluginInstallerOptionsV1 {\n\treadonly host: PluginInstallHostV1;\n\treadonly verifier?: PluginSourceVerifierV1;\n}\n\nexport type PluginInstallerErrorCodeV1 =\n\t| \"invalid_installation\"\n\t| \"unsupported_scope\"\n\t| \"install_failed\"\n\t| \"activation_failed\"\n\t| \"rollback_failed\"\n\t| \"uninstall_failed\";\n\nexport type PluginInstallerResultV1 =\n\t| {\n\t\t\treadonly status: \"succeeded\";\n\t\t\treadonly installation: PluginInstallationV1;\n\t }\n\t| {\n\t\t\treadonly status: \"cancelled\";\n\t\t\treadonly error: { readonly code: \"cancelled\"; readonly message: string };\n\t }\n\t| {\n\t\t\treadonly status: \"failed\";\n\t\t\treadonly error: {\n\t\t\t\treadonly code: PluginInstallerErrorCodeV1;\n\t\t\t\treadonly message: string;\n\t\t\t};\n\t };\n\nexport interface PluginInstallerV1 {\n\t/** Declared, host-backed installation scopes. Project support is never inferred. */\n\treadonly supportedScopes: readonly PluginInstallationScopeV1[];\n\tprepare(input: {\n\t\treadonly manifest: PluginUpdateRecordV1[\"manifest\"];\n\t\treadonly source: string;\n\t\treadonly host: HostFactsV1;\n\t\treadonly expectedDigest?: string;\n\t}): UpdateVerificationV1;\n\tinstall(input: {\n\t\treadonly record: PluginUpdateRecordV1;\n\t\t/** Omitting scope preserves the existing global installation behavior. */\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\t/** Required for project installations; global defaults to `global:default`. */\n\t\treadonly scopeRef?: string;\n\t\treadonly artifact?: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n\tactivate(input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly record: PluginUpdateRecordV1;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n\trollback(input: {\n\t\treadonly failed: PluginInstallationV1;\n\t\treadonly previous: PluginInstallationV1;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n\t/** Remove one installed version after validating its opaque identity. */\n\tremove(input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n}\n\nfunction opaqueInstallationRef(value: unknown): string {\n\tif (typeof value !== \"string\" || value.trim() === \"\" || value.length > MAX_INSTALLATION_REF_CHARS_V1)\n\t\tthrow new Error(\"installation reference is invalid\");\n\tif (/^(?:file:|[a-zA-Z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value) || /\\s/u.test(value))\n\t\tthrow new Error(\"installation reference must be opaque\");\n\treturn value;\n}\n\nfunction opaqueScopeRef(value: unknown): string {\n\tif (typeof value !== \"string\" || value.trim() === \"\" || value.length > MAX_PLUGIN_SCOPE_REF_CHARS_V1)\n\t\tthrow new Error(\"plugin installation scope reference is invalid\");\n\tif (/^(?:file:|[a-zA-Z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value) || /\\s/u.test(value))\n\t\tthrow new Error(\"plugin installation scope reference must be opaque\");\n\treturn value;\n}\n\nfunction installationFrom(\n\trecord: PluginUpdateRecordV1,\n\tinstallationRef: string,\n\tscopeIdentity: PluginScopeIdentityV1,\n\tstate: PluginInstallationV1[\"state\"],\n): PluginInstallationV1 {\n\treturn Object.freeze({\n\t\tversion: 1,\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: scopeIdentity.scope,\n\t\tscopeRef: scopeIdentity.scopeRef,\n\t\tinstallationRef: opaqueInstallationRef(installationRef),\n\t\tstate,\n\t});\n}\n\nfunction cancelled(): PluginInstallerResultV1 {\n\treturn {\n\t\tstatus: \"cancelled\",\n\t\terror: {\n\t\t\tcode: \"cancelled\",\n\t\t\tmessage: \"Plugin installation operation was cancelled\",\n\t\t},\n\t};\n}\n\nfunction failure(code: PluginInstallerErrorCodeV1): PluginInstallerResultV1 {\n\treturn {\n\t\tstatus: \"failed\",\n\t\terror: {\n\t\t\tcode,\n\t\t\tmessage:\n\t\t\t\tcode === \"invalid_installation\"\n\t\t\t\t\t? \"The plugin installation handle is invalid\"\n\t\t\t\t\t: code === \"unsupported_scope\"\n\t\t\t\t\t\t? \"The plugin installer does not support this scope\"\n\t\t\t\t\t\t: code === \"install_failed\"\n\t\t\t\t\t\t\t? \"The host plugin installer failed\"\n\t\t\t\t\t\t\t: code === \"activation_failed\"\n\t\t\t\t\t\t\t\t? \"The host plugin activation failed\"\n\t\t\t\t\t\t\t\t: code === \"rollback_failed\"\n\t\t\t\t\t\t\t\t\t? \"The host plugin rollback failed\"\n\t\t\t\t\t\t\t\t\t: \"The host plugin uninstall failed\",\n\t\t},\n\t};\n}\n\nfunction validateInstallation(installation: PluginInstallationV1): void {\n\tif (\n\t\tinstallation.version !== 1 ||\n\t\ttypeof installation.pluginId !== \"string\" ||\n\t\ttypeof installation.pluginVersion !== \"string\" ||\n\t\ttypeof installation.manifestDigest !== \"string\" ||\n\t\tinstallation.pluginId.trim() === \"\" ||\n\t\tinstallation.pluginVersion.trim() === \"\" ||\n\t\tinstallation.manifestDigest.trim() === \"\"\n\t)\n\t\tthrow new Error(\"plugin installation handle is invalid\");\n\tif (installation.scope !== \"global\" && installation.scope !== \"project\")\n\t\tthrow new Error(\"plugin installation scope is invalid\");\n\tconst scopeRef =\n\t\tinstallation.scopeRef === undefined\n\t\t\t? installation.scope === \"global\"\n\t\t\t\t? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1\n\t\t\t\t: (() => {\n\t\t\t\t\t\tthrow new Error(\"project installation scope reference is required\");\n\t\t\t\t\t})()\n\t\t\t: opaqueScopeRef(installation.scopeRef);\n\tif (installation.scope === \"global\" && scopeRef !== DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1)\n\t\tthrow new Error(\"plugin global installation scope reference is invalid\");\n\topaqueInstallationRef(installation.installationRef);\n}\n\nfunction ensureIdentity(\n\tinstallation: PluginInstallationV1,\n\trecord: PluginUpdateRecordV1,\n\tscopeIdentity: PluginScopeIdentityV1,\n): void {\n\tvalidateInstallation(installation);\n\tif (\n\t\tinstallation.pluginId !== record.pluginId ||\n\t\tinstallation.pluginVersion !== record.pluginVersion ||\n\t\tinstallation.manifestDigest !== record.manifestDigest ||\n\t\tinstallation.scope !== scopeIdentity.scope ||\n\t\t(installation.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef\n\t)\n\t\tthrow new Error(\"plugin installation identity mismatch\");\n}\n\nfunction normalizeScope(scope: PluginInstallationScopeV1 | undefined): PluginInstallationScopeV1 {\n\tif (scope === undefined) return \"global\";\n\tif (scope === \"global\" || scope === \"project\") return scope;\n\tthrow new Error(\"plugin installation scope is invalid\");\n}\n\nfunction normalizeScopeIdentity(\n\tscope: PluginInstallationScopeV1 | undefined,\n\tscopeRef: string | undefined,\n): PluginScopeIdentityV1 {\n\tconst normalizedScope = normalizeScope(scope);\n\tif (scopeRef === undefined) {\n\t\tif (normalizedScope !== \"global\") throw new Error(\"project installation scope reference is required\");\n\t\treturn Object.freeze({ scope: normalizedScope, scopeRef: DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1 });\n\t}\n\tconst normalizedScopeRef = opaqueScopeRef(scopeRef);\n\tif (normalizedScope === \"global\" && normalizedScopeRef !== DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1)\n\t\tthrow new Error(\"plugin global installation scope reference is invalid\");\n\treturn Object.freeze({ scope: normalizedScope, scopeRef: normalizedScopeRef });\n}\n\nfunction declaredScopes(host: PluginInstallHostV1): readonly PluginInstallationScopeV1[] {\n\tif (host.supportedScopes === undefined) return Object.freeze([\"global\"]);\n\tif (\n\t\t!Array.isArray(host.supportedScopes) ||\n\t\tnew Set(host.supportedScopes).size !== host.supportedScopes.length ||\n\t\thost.supportedScopes.some((scope) => scope !== \"global\" && scope !== \"project\")\n\t)\n\t\treturn Object.freeze([]);\n\treturn Object.freeze([...host.supportedScopes]);\n}\n\nfunction hostAcceptedScope(\n\tinstallation: { readonly scope?: PluginInstallationScopeV1; readonly scopeRef?: string },\n\tscopeIdentity: PluginScopeIdentityV1,\n): void {\n\tif (scopeIdentity.scope === \"global\" && installation.scope === undefined && installation.scopeRef === undefined)\n\t\treturn;\n\tif (installation.scope !== scopeIdentity.scope || installation.scopeRef !== scopeIdentity.scopeRef)\n\t\tthrow new Error(\"plugin installation scope mismatch\");\n}\n\nfunction ensureArtifactIdentity(artifact: PluginDistributionArtifactV1, record: PluginUpdateRecordV1): void {\n\tif (\n\t\tartifact.version !== 1 ||\n\t\tartifact.pluginId !== record.pluginId ||\n\t\tartifact.pluginVersion !== record.pluginVersion ||\n\t\tartifact.manifestDigest !== record.manifestDigest ||\n\t\ttypeof artifact.artifactRef !== \"string\" ||\n\t\tartifact.artifactRef.trim() === \"\"\n\t)\n\t\tthrow new Error(\"plugin distribution artifact identity mismatch\");\n\topaqueInstallationRef(artifact.artifactRef);\n}\n\nfunction isInvalidInstallationError(value: unknown): boolean {\n\treturn (\n\t\tvalue instanceof Error &&\n\t\t(value.message === \"plugin installation handle is invalid\" ||\n\t\t\tvalue.message === \"plugin installation scope is invalid\" ||\n\t\t\tvalue.message === \"plugin installation scope reference is invalid\" ||\n\t\t\tvalue.message === \"plugin installation scope reference must be opaque\" ||\n\t\t\tvalue.message === \"plugin global installation scope reference is invalid\" ||\n\t\t\tvalue.message === \"project installation scope reference is required\" ||\n\t\t\tvalue.message === \"plugin installation identity mismatch\" ||\n\t\t\tvalue.message === \"plugin installation scope mismatch\" ||\n\t\t\tvalue.message === \"plugin distribution artifact identity mismatch\")\n\t);\n}\n\nexport function createPluginInstallerV1(options: PluginInstallerOptionsV1): PluginInstallerV1 {\n\tconst supportedScopes = declaredScopes(options.host);\n\tconst supportsScope = (scope: PluginInstallationScopeV1): boolean => supportedScopes.includes(scope);\n\treturn {\n\t\tsupportedScopes,\n\t\tprepare(input) {\n\t\t\tconst staged = stagePluginUpdateV1({\n\t\t\t\tmanifest: input.manifest,\n\t\t\t\tsource: input.source,\n\t\t\t});\n\t\t\treturn verifyPluginUpdateV1({\n\t\t\t\trecord: staged,\n\t\t\t\thost: input.host,\n\t\t\t\texpectedDigest: input.expectedDigest,\n\t\t\t\tverifier: options.verifier,\n\t\t\t});\n\t\t},\n\t\tasync install(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t} catch {\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t}\n\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\tif (input.record.state !== \"verified\") return failure(\"invalid_installation\");\n\t\t\ttry {\n\t\t\t\tif (input.artifact !== undefined) ensureArtifactIdentity(input.artifact, input.record);\n\t\t\t\tconst installed = await options.host.install({\n\t\t\t\t\trecord: input.record,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\t...(input.artifact === undefined ? {} : { artifact: input.artifact }),\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\thostAcceptedScope(installed, scopeIdentity);\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: installationFrom(input.record, installed.installationRef, scopeIdentity, \"installed\"),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tif (isInvalidInstallationError(error)) return failure(\"invalid_installation\");\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"install_failed\");\n\t\t\t}\n\t\t},\n\t\tasync activate(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\t\tensureIdentity(input.installation, input.record, scopeIdentity);\n\t\t\t\tif (input.installation.state !== \"installed\" || input.record.state !== \"verified\")\n\t\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t\tawait options.host.activate({\n\t\t\t\t\tinstallation: input.installation,\n\t\t\t\t\trecord: input.record,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: Object.freeze({\n\t\t\t\t\t\t...input.installation,\n\t\t\t\t\t\tstate: \"active\" as const,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tif (isInvalidInstallationError(error)) return failure(\"invalid_installation\");\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"activation_failed\");\n\t\t\t}\n\t\t},\n\t\tasync rollback(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\t\tvalidateInstallation(input.failed);\n\t\t\t\tvalidateInstallation(input.previous);\n\t\t\t\tif (input.failed.state !== \"installed\" && input.failed.state !== \"active\")\n\t\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t\tif (input.previous.state !== \"active\") return failure(\"invalid_installation\");\n\t\t\t\tif (\n\t\t\t\t\tinput.failed.pluginId !== input.previous.pluginId ||\n\t\t\t\t\tinput.failed.scope !== scopeIdentity.scope ||\n\t\t\t\t\tinput.previous.scope !== scopeIdentity.scope ||\n\t\t\t\t\t(input.failed.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef ||\n\t\t\t\t\t(input.previous.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef\n\t\t\t\t)\n\t\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t\tawait options.host.rollback({\n\t\t\t\t\tfailed: input.failed,\n\t\t\t\t\tprevious: input.previous,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: Object.freeze({\n\t\t\t\t\t\t...input.previous,\n\t\t\t\t\t\tstate: \"active\" as const,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tif (isInvalidInstallationError(error)) return failure(\"invalid_installation\");\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"rollback_failed\");\n\t\t\t}\n\t\t},\n\t\tasync remove(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\t\tvalidateInstallation(input.installation);\n\t\t\t} catch {\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t}\n\t\t\tif (\n\t\t\t\tinput.installation.state !== \"installed\" &&\n\t\t\t\tinput.installation.state !== \"active\" &&\n\t\t\t\tinput.installation.state !== \"retained\"\n\t\t\t)\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\tif (\n\t\t\t\tinput.installation.scope !== scopeIdentity.scope ||\n\t\t\t\t(input.installation.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef\n\t\t\t)\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\tif (options.host.uninstall === undefined) return failure(\"uninstall_failed\");\n\t\t\ttry {\n\t\t\t\tawait options.host.uninstall({\n\t\t\t\t\tinstallation: input.installation,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: Object.freeze({\n\t\t\t\t\t\t...input.installation,\n\t\t\t\t\t\tstate: \"retained\" as const,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"uninstall_failed\");\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/installer.ts"],"names":[],"mappings":"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","sourcesContent":["import { t } from \"../../core/i18n/index.ts\";\nimport type { PluginDistributionArtifactV1 } from \"./distribution.ts\";\nimport type { HostFactsV1, PluginSourceVerifierV1, PluginUpdateRecordV1 } from \"./types.ts\";\n\nimport { stagePluginUpdateV1, type UpdateVerificationV1, verifyPluginUpdateV1 } from \"./updates.ts\";\n\nconst MAX_INSTALLATION_REF_CHARS_V1 = 2048;\nexport const MAX_PLUGIN_SCOPE_REF_CHARS_V1 = 2048;\n/** Stable host namespace for installations that are not project-local. */\nexport const DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1 = \"global:default\";\n\nexport type PluginInstallationScopeV1 = \"global\" | \"project\";\n\ninterface PluginScopeIdentityV1 {\n\treadonly scope: PluginInstallationScopeV1;\n\t/** Opaque host namespace; it must never disclose a local project path. */\n\treadonly scopeRef: string;\n}\n\nexport interface PluginInstallationV1 {\n\treadonly version: 1;\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\t/** The host installation namespace. It is part of the opaque installation identity. */\n\treadonly scope: PluginInstallationScopeV1;\n\t/** Concrete host namespace that distinguishes global and individual project installations. */\n\treadonly scopeRef?: string;\n\t/** Opaque host-owned installation handle; never a local path. */\n\treadonly installationRef: string;\n\treadonly state: \"installed\" | \"active\" | \"retained\";\n}\n\nexport interface PluginInstallHostV1 {\n\t/**\n\t * Scopes that this host can isolate physically. Omitting this declaration\n\t * preserves the legacy global-only host behavior; project operations must be\n\t * declared explicitly.\n\t */\n\treadonly supportedScopes?: readonly PluginInstallationScopeV1[];\n\t/** Host operations are atomic from the installer's perspective: an abort may\n\t * prevent starting work, but once a method resolves its side effect is committed. */\n\tinstall(input: {\n\t\treadonly record: PluginUpdateRecordV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\t/** A host-owned, digest-bound package reference. Package bytes never cross this contract. */\n\t\treadonly artifact?: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<{\n\t\treadonly installationRef: string;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t}>;\n\tactivate(input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly record: PluginUpdateRecordV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void>;\n\trollback(input: {\n\t\treadonly failed: PluginInstallationV1;\n\t\treadonly previous: PluginInstallationV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void>;\n\t/**\n\t * Remove a host-owned installation. The method is optional so hosts can\n\t * still expose state-only management while they are migrating; callers that\n\t * need physical cleanup must treat a missing method as unsupported.\n\t */\n\tuninstall?: (input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly scope: PluginInstallationScopeV1;\n\t\treadonly scopeRef: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => Promise<void>;\n}\n\nexport interface PluginInstallerOptionsV1 {\n\treadonly host: PluginInstallHostV1;\n\treadonly verifier?: PluginSourceVerifierV1;\n}\n\nexport type PluginInstallerErrorCodeV1 =\n\t| \"invalid_installation\"\n\t| \"unsupported_scope\"\n\t| \"install_failed\"\n\t| \"activation_failed\"\n\t| \"rollback_failed\"\n\t| \"uninstall_failed\";\n\nexport type PluginInstallerResultV1 =\n\t| {\n\t\t\treadonly status: \"succeeded\";\n\t\t\treadonly installation: PluginInstallationV1;\n\t }\n\t| {\n\t\t\treadonly status: \"cancelled\";\n\t\t\treadonly error: { readonly code: \"cancelled\"; readonly message: string };\n\t }\n\t| {\n\t\t\treadonly status: \"failed\";\n\t\t\treadonly error: {\n\t\t\t\treadonly code: PluginInstallerErrorCodeV1;\n\t\t\t\treadonly message: string;\n\t\t\t};\n\t };\n\nexport interface PluginInstallerV1 {\n\t/** Declared, host-backed installation scopes. Project support is never inferred. */\n\treadonly supportedScopes: readonly PluginInstallationScopeV1[];\n\tprepare(input: {\n\t\treadonly manifest: PluginUpdateRecordV1[\"manifest\"];\n\t\treadonly source: string;\n\t\treadonly host: HostFactsV1;\n\t\treadonly expectedDigest?: string;\n\t}): UpdateVerificationV1;\n\tinstall(input: {\n\t\treadonly record: PluginUpdateRecordV1;\n\t\t/** Omitting scope preserves the existing global installation behavior. */\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\t/** Required for project installations; global defaults to `global:default`. */\n\t\treadonly scopeRef?: string;\n\t\treadonly artifact?: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n\tactivate(input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly record: PluginUpdateRecordV1;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n\trollback(input: {\n\t\treadonly failed: PluginInstallationV1;\n\t\treadonly previous: PluginInstallationV1;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n\t/** Remove one installed version after validating its opaque identity. */\n\tremove(input: {\n\t\treadonly installation: PluginInstallationV1;\n\t\treadonly scope?: PluginInstallationScopeV1;\n\t\treadonly scopeRef?: string;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginInstallerResultV1>;\n}\n\nfunction opaqueInstallationRef(value: unknown): string {\n\tif (typeof value !== \"string\" || value.trim() === \"\" || value.length > MAX_INSTALLATION_REF_CHARS_V1)\n\t\tthrow new Error(t(\"installation reference is invalid\"));\n\tif (/^(?:file:|[a-zA-Z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value) || /\\s/u.test(value))\n\t\tthrow new Error(t(\"installation reference must be opaque\"));\n\treturn value;\n}\n\nfunction opaqueScopeRef(value: unknown): string {\n\tif (typeof value !== \"string\" || value.trim() === \"\" || value.length > MAX_PLUGIN_SCOPE_REF_CHARS_V1)\n\t\tthrow new Error(\"plugin installation scope reference is invalid\");\n\tif (/^(?:file:|[a-zA-Z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value) || /\\s/u.test(value))\n\t\tthrow new Error(\"plugin installation scope reference must be opaque\");\n\treturn value;\n}\n\nfunction installationFrom(\n\trecord: PluginUpdateRecordV1,\n\tinstallationRef: string,\n\tscopeIdentity: PluginScopeIdentityV1,\n\tstate: PluginInstallationV1[\"state\"],\n): PluginInstallationV1 {\n\treturn Object.freeze({\n\t\tversion: 1,\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: scopeIdentity.scope,\n\t\tscopeRef: scopeIdentity.scopeRef,\n\t\tinstallationRef: opaqueInstallationRef(installationRef),\n\t\tstate,\n\t});\n}\n\nfunction cancelled(): PluginInstallerResultV1 {\n\treturn {\n\t\tstatus: \"cancelled\",\n\t\terror: {\n\t\t\tcode: \"cancelled\",\n\t\t\tmessage: \"Plugin installation operation was cancelled\",\n\t\t},\n\t};\n}\n\nfunction failure(code: PluginInstallerErrorCodeV1): PluginInstallerResultV1 {\n\treturn {\n\t\tstatus: \"failed\",\n\t\terror: {\n\t\t\tcode,\n\t\t\tmessage:\n\t\t\t\tcode === \"invalid_installation\"\n\t\t\t\t\t? \"The plugin installation handle is invalid\"\n\t\t\t\t\t: code === \"unsupported_scope\"\n\t\t\t\t\t\t? \"The plugin installer does not support this scope\"\n\t\t\t\t\t\t: code === \"install_failed\"\n\t\t\t\t\t\t\t? \"The host plugin installer failed\"\n\t\t\t\t\t\t\t: code === \"activation_failed\"\n\t\t\t\t\t\t\t\t? \"The host plugin activation failed\"\n\t\t\t\t\t\t\t\t: code === \"rollback_failed\"\n\t\t\t\t\t\t\t\t\t? \"The host plugin rollback failed\"\n\t\t\t\t\t\t\t\t\t: \"The host plugin uninstall failed\",\n\t\t},\n\t};\n}\n\nfunction validateInstallation(installation: PluginInstallationV1): void {\n\tif (\n\t\tinstallation.version !== 1 ||\n\t\ttypeof installation.pluginId !== \"string\" ||\n\t\ttypeof installation.pluginVersion !== \"string\" ||\n\t\ttypeof installation.manifestDigest !== \"string\" ||\n\t\tinstallation.pluginId.trim() === \"\" ||\n\t\tinstallation.pluginVersion.trim() === \"\" ||\n\t\tinstallation.manifestDigest.trim() === \"\"\n\t)\n\t\tthrow new Error(\"plugin installation handle is invalid\");\n\tif (installation.scope !== \"global\" && installation.scope !== \"project\")\n\t\tthrow new Error(\"plugin installation scope is invalid\");\n\tconst scopeRef =\n\t\tinstallation.scopeRef === undefined\n\t\t\t? installation.scope === \"global\"\n\t\t\t\t? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1\n\t\t\t\t: (() => {\n\t\t\t\t\t\tthrow new Error(\"project installation scope reference is required\");\n\t\t\t\t\t})()\n\t\t\t: opaqueScopeRef(installation.scopeRef);\n\tif (installation.scope === \"global\" && scopeRef !== DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1)\n\t\tthrow new Error(\"plugin global installation scope reference is invalid\");\n\topaqueInstallationRef(installation.installationRef);\n}\n\nfunction ensureIdentity(\n\tinstallation: PluginInstallationV1,\n\trecord: PluginUpdateRecordV1,\n\tscopeIdentity: PluginScopeIdentityV1,\n): void {\n\tvalidateInstallation(installation);\n\tif (\n\t\tinstallation.pluginId !== record.pluginId ||\n\t\tinstallation.pluginVersion !== record.pluginVersion ||\n\t\tinstallation.manifestDigest !== record.manifestDigest ||\n\t\tinstallation.scope !== scopeIdentity.scope ||\n\t\t(installation.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef\n\t)\n\t\tthrow new Error(\"plugin installation identity mismatch\");\n}\n\nfunction normalizeScope(scope: PluginInstallationScopeV1 | undefined): PluginInstallationScopeV1 {\n\tif (scope === undefined) return \"global\";\n\tif (scope === \"global\" || scope === \"project\") return scope;\n\tthrow new Error(\"plugin installation scope is invalid\");\n}\n\nfunction normalizeScopeIdentity(\n\tscope: PluginInstallationScopeV1 | undefined,\n\tscopeRef: string | undefined,\n): PluginScopeIdentityV1 {\n\tconst normalizedScope = normalizeScope(scope);\n\tif (scopeRef === undefined) {\n\t\tif (normalizedScope !== \"global\") throw new Error(\"project installation scope reference is required\");\n\t\treturn Object.freeze({ scope: normalizedScope, scopeRef: DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1 });\n\t}\n\tconst normalizedScopeRef = opaqueScopeRef(scopeRef);\n\tif (normalizedScope === \"global\" && normalizedScopeRef !== DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1)\n\t\tthrow new Error(\"plugin global installation scope reference is invalid\");\n\treturn Object.freeze({ scope: normalizedScope, scopeRef: normalizedScopeRef });\n}\n\nfunction declaredScopes(host: PluginInstallHostV1): readonly PluginInstallationScopeV1[] {\n\tif (host.supportedScopes === undefined) return Object.freeze([\"global\"]);\n\tif (\n\t\t!Array.isArray(host.supportedScopes) ||\n\t\tnew Set(host.supportedScopes).size !== host.supportedScopes.length ||\n\t\thost.supportedScopes.some((scope) => scope !== \"global\" && scope !== \"project\")\n\t)\n\t\treturn Object.freeze([]);\n\treturn Object.freeze([...host.supportedScopes]);\n}\n\nfunction hostAcceptedScope(\n\tinstallation: { readonly scope?: PluginInstallationScopeV1; readonly scopeRef?: string },\n\tscopeIdentity: PluginScopeIdentityV1,\n): void {\n\tif (scopeIdentity.scope === \"global\" && installation.scope === undefined && installation.scopeRef === undefined)\n\t\treturn;\n\tif (installation.scope !== scopeIdentity.scope || installation.scopeRef !== scopeIdentity.scopeRef)\n\t\tthrow new Error(\"plugin installation scope mismatch\");\n}\n\nfunction ensureArtifactIdentity(artifact: PluginDistributionArtifactV1, record: PluginUpdateRecordV1): void {\n\tif (\n\t\tartifact.version !== 1 ||\n\t\tartifact.pluginId !== record.pluginId ||\n\t\tartifact.pluginVersion !== record.pluginVersion ||\n\t\tartifact.manifestDigest !== record.manifestDigest ||\n\t\ttypeof artifact.artifactRef !== \"string\" ||\n\t\tartifact.artifactRef.trim() === \"\"\n\t)\n\t\tthrow new Error(\"plugin distribution artifact identity mismatch\");\n\topaqueInstallationRef(artifact.artifactRef);\n}\n\nfunction isInvalidInstallationError(value: unknown): boolean {\n\treturn (\n\t\tvalue instanceof Error &&\n\t\t(value.message === \"plugin installation handle is invalid\" ||\n\t\t\tvalue.message === \"plugin installation scope is invalid\" ||\n\t\t\tvalue.message === \"plugin installation scope reference is invalid\" ||\n\t\t\tvalue.message === \"plugin installation scope reference must be opaque\" ||\n\t\t\tvalue.message === \"plugin global installation scope reference is invalid\" ||\n\t\t\tvalue.message === \"project installation scope reference is required\" ||\n\t\t\tvalue.message === \"plugin installation identity mismatch\" ||\n\t\t\tvalue.message === \"plugin installation scope mismatch\" ||\n\t\t\tvalue.message === \"plugin distribution artifact identity mismatch\")\n\t);\n}\n\nexport function createPluginInstallerV1(options: PluginInstallerOptionsV1): PluginInstallerV1 {\n\tconst supportedScopes = declaredScopes(options.host);\n\tconst supportsScope = (scope: PluginInstallationScopeV1): boolean => supportedScopes.includes(scope);\n\treturn {\n\t\tsupportedScopes,\n\t\tprepare(input) {\n\t\t\tconst staged = stagePluginUpdateV1({\n\t\t\t\tmanifest: input.manifest,\n\t\t\t\tsource: input.source,\n\t\t\t});\n\t\t\treturn verifyPluginUpdateV1({\n\t\t\t\trecord: staged,\n\t\t\t\thost: input.host,\n\t\t\t\texpectedDigest: input.expectedDigest,\n\t\t\t\tverifier: options.verifier,\n\t\t\t});\n\t\t},\n\t\tasync install(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t} catch {\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t}\n\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\tif (input.record.state !== \"verified\") return failure(\"invalid_installation\");\n\t\t\ttry {\n\t\t\t\tif (input.artifact !== undefined) ensureArtifactIdentity(input.artifact, input.record);\n\t\t\t\tconst installed = await options.host.install({\n\t\t\t\t\trecord: input.record,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\t...(input.artifact === undefined ? {} : { artifact: input.artifact }),\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\thostAcceptedScope(installed, scopeIdentity);\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: installationFrom(input.record, installed.installationRef, scopeIdentity, \"installed\"),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tif (isInvalidInstallationError(error)) return failure(\"invalid_installation\");\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"install_failed\");\n\t\t\t}\n\t\t},\n\t\tasync activate(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\t\tensureIdentity(input.installation, input.record, scopeIdentity);\n\t\t\t\tif (input.installation.state !== \"installed\" || input.record.state !== \"verified\")\n\t\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t\tawait options.host.activate({\n\t\t\t\t\tinstallation: input.installation,\n\t\t\t\t\trecord: input.record,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: Object.freeze({\n\t\t\t\t\t\t...input.installation,\n\t\t\t\t\t\tstate: \"active\" as const,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tif (isInvalidInstallationError(error)) return failure(\"invalid_installation\");\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"activation_failed\");\n\t\t\t}\n\t\t},\n\t\tasync rollback(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\t\tvalidateInstallation(input.failed);\n\t\t\t\tvalidateInstallation(input.previous);\n\t\t\t\tif (input.failed.state !== \"installed\" && input.failed.state !== \"active\")\n\t\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t\tif (input.previous.state !== \"active\") return failure(\"invalid_installation\");\n\t\t\t\tif (\n\t\t\t\t\tinput.failed.pluginId !== input.previous.pluginId ||\n\t\t\t\t\tinput.failed.scope !== scopeIdentity.scope ||\n\t\t\t\t\tinput.previous.scope !== scopeIdentity.scope ||\n\t\t\t\t\t(input.failed.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef ||\n\t\t\t\t\t(input.previous.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef\n\t\t\t\t)\n\t\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t\tawait options.host.rollback({\n\t\t\t\t\tfailed: input.failed,\n\t\t\t\t\tprevious: input.previous,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: Object.freeze({\n\t\t\t\t\t\t...input.previous,\n\t\t\t\t\t\tstate: \"active\" as const,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tif (isInvalidInstallationError(error)) return failure(\"invalid_installation\");\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"rollback_failed\");\n\t\t\t}\n\t\t},\n\t\tasync remove(input) {\n\t\t\tif (input.signal?.aborted) return cancelled();\n\t\t\tlet scopeIdentity: PluginScopeIdentityV1;\n\t\t\ttry {\n\t\t\t\tscopeIdentity = normalizeScopeIdentity(input.scope, input.scopeRef);\n\t\t\t\tif (!supportsScope(scopeIdentity.scope)) return failure(\"unsupported_scope\");\n\t\t\t\tvalidateInstallation(input.installation);\n\t\t\t} catch {\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\t}\n\t\t\tif (\n\t\t\t\tinput.installation.state !== \"installed\" &&\n\t\t\t\tinput.installation.state !== \"active\" &&\n\t\t\t\tinput.installation.state !== \"retained\"\n\t\t\t)\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\tif (\n\t\t\t\tinput.installation.scope !== scopeIdentity.scope ||\n\t\t\t\t(input.installation.scopeRef ?? DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1) !== scopeIdentity.scopeRef\n\t\t\t)\n\t\t\t\treturn failure(\"invalid_installation\");\n\t\t\tif (options.host.uninstall === undefined) return failure(\"uninstall_failed\");\n\t\t\ttry {\n\t\t\t\tawait options.host.uninstall({\n\t\t\t\t\tinstallation: input.installation,\n\t\t\t\t\tscope: scopeIdentity.scope,\n\t\t\t\t\tscopeRef: scopeIdentity.scopeRef,\n\t\t\t\t\tsignal: input.signal,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"succeeded\",\n\t\t\t\t\tinstallation: Object.freeze({\n\t\t\t\t\t\t...input.installation,\n\t\t\t\t\t\tstate: \"retained\" as const,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\treturn input.signal?.aborted ? cancelled() : failure(\"uninstall_failed\");\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"node-disk-registry-source.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-disk-registry-source.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoC,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAG9F,QAAA,MAAM,oCAAoC,GAAa,CAAC;AACxD,oEAAoE;AACpE,eAAO,MAAM,qCAAqC,QAAc,CAAC;AACjE,+EAA+E;AAC/E,eAAO,MAAM,wCAAwC,QAAY,CAAC;AAClE,6FAA6F;AAC7F,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAOrD,MAAM,MAAM,iCAAiC,GAC1C,WAAW,GACX,uBAAuB,GACvB,eAAe,GACf,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,WAAW,CAAC;AAEf;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IAEjD,YAAY,IAAI,EAAE,iCAAiC,EAAE,OAAO,EAAE,MAAM,EAInE;CACD;AAED,MAAM,WAAW,+BAA+B;IAC/C,0FAA0F;IAC1F,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,oCAAoC;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAyB,SAAQ,sBAAsB;IACvE,QAAQ,CAAC,OAAO,EAAE,OAAO,oCAAoC,CAAC;IAC9D;;;;;;OAMG;IACH,QAAQ,CAAC,6BAA6B,CAAC,EAAE,CACxC,KAAK,EAAE,oCAAoC,KACvC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACjC;AAuJD;;;;;;GAMG;AACH,wBAAgB,oCAAoC,CACnD,OAAO,EAAE,+BAA+B,GACtC,wBAAwB,CAkD1B","sourcesContent":["import { open } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { withinInstallStoreRoot } from \"./install-store-paths.ts\";\nimport type { PluginRegistryManifestEnvelopeV1, PluginRegistrySourceV1 } from \"./registry.ts\";\nimport type { PluginManifestV1 } from \"./types.ts\";\n\nconst NODE_DISK_REGISTRY_SOURCE_VERSION_V1 = 1 as const;\n/** Maximum index.v1.json bytes accepted by this source boundary. */\nexport const MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1 = 1024 * 1024;\n/** Maximum per-installation agent-forge.json bytes accepted by this source. */\nexport const MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1 = 64 * 1024;\n/** Maximum index records projected by one list() call; matches the registry manifest cap. */\nexport const MAX_NODE_DISK_REGISTRY_RECORDS_V1 = 256;\n\nconst INDEX_FILE_V1 = \"index.v1.json\";\nconst ECOSYSTEM_MANIFEST_FILE_V1 = \"agent-forge.json\";\nconst CAPABILITY_MANIFEST_FILE_V1 = \"plugin.json\";\nconst NODE_PACKAGE_FORMAT_VERSION_V1 = 1;\n\nexport type NodeDiskRegistrySourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"invalid_index\"\n\t| \"invalid_manifest\"\n\t| \"identity_mismatch\"\n\t| \"too_many_records\"\n\t| \"io_failed\";\n\n/**\n * Deliberately does not retain filesystem exceptions or file contents: callers\n * must not turn registry diagnostics into a path or package disclosure.\n */\nexport class NodeDiskRegistrySourceErrorV1 extends Error {\n\treadonly code: NodeDiskRegistrySourceErrorCodeV1;\n\n\tconstructor(code: NodeDiskRegistrySourceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeDiskRegistrySourceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface NodeDiskRegistrySourceOptionsV1 {\n\t/** Absolute host-owned default install store directory. It is never returned in a DTO. */\n\treadonly rootDirectory: string;\n}\n\nexport interface NodeDiskRegistrySourceResolveInputV1 {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly signal?: AbortSignal;\n}\n\nexport interface NodeDiskRegistrySourceV1 extends PluginRegistrySourceV1 {\n\treadonly version: typeof NODE_DISK_REGISTRY_SOURCE_VERSION_V1;\n\t/**\n\t * Internal host channel (D-075 S2): absolute `plugin.json` path of the\n\t * installation directory matching `{pluginId, pluginVersion}` in the store\n\t * index, for the sdk's installed-plugin code loading. Registry snapshots\n\t * still carry no paths; undefined means no matching record or the manifest\n\t * file is absent from the installation directory.\n\t */\n\treadonly resolveCapabilityManifestPath?: (\n\t\tinput: NodeDiskRegistrySourceResolveInputV1,\n\t) => Promise<string | undefined>;\n}\n\ninterface DiskIndexRecordV1 {\n\treadonly installationRef: string;\n\treadonly directory: string;\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\treadonly scope: \"global\" | \"project\";\n\treadonly scopeRef: string;\n\treadonly state: \"installed\" | \"active\" | \"retained\";\n}\n\nconst INDEX_KEYS_V1 = [\n\t\"installationRef\",\n\t\"directory\",\n\t\"pluginId\",\n\t\"pluginVersion\",\n\t\"manifestDigest\",\n\t\"scope\",\n\t\"scopeRef\",\n\t\"state\",\n] as const;\n\nfunction opaqueField(value: unknown, max: number): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= max &&\n\t\t!/[\\u0000-\\u001f\\u007f]/u.test(value) &&\n\t\t!/\\s/u.test(value) &&\n\t\t!/^(?:file:|[a-z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value)\n\t);\n}\n\nfunction boundedField(value: unknown, max: number): value is string {\n\treturn typeof value === \"string\" && value.length > 0 && value.length <= max && !/[\\u0000-\\u001f\\u007f]/u.test(value);\n}\n\nfunction validateRecord(root: string, value: unknown, index: number): DiskIndexRecordV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", `Index record ${index} is not an object`);\n\tconst record = value as Record<string, unknown>;\n\tconst keys = INDEX_KEYS_V1;\n\tif (Object.keys(record).length !== keys.length || keys.some((key) => !(key in record)))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", `Index record ${index} has an invalid schema`);\n\tif (\n\t\t!opaqueField(record.installationRef, 2048) ||\n\t\t!boundedField(record.directory, 2048) ||\n\t\t!boundedField(record.pluginId, 256) ||\n\t\t!boundedField(record.pluginVersion, 256) ||\n\t\t!boundedField(record.manifestDigest, 512) ||\n\t\t!opaqueField(record.scopeRef, 2048) ||\n\t\t(record.scope !== \"global\" && record.scope !== \"project\") ||\n\t\t(record.state !== \"installed\" && record.state !== \"active\" && record.state !== \"retained\") ||\n\t\t!withinInstallStoreRoot(root, record.directory)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", `Index record ${index} is invalid`);\n\treturn {\n\t\tinstallationRef: record.installationRef,\n\t\tdirectory: record.directory,\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: record.scope,\n\t\tscopeRef: record.scopeRef,\n\t\tstate: record.state,\n\t};\n}\n\nfunction parseIndex(root: string, raw: string): readonly DiskIndexRecordV1[] {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", \"Install store index JSON is invalid\");\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", \"Install store index is not an object\");\n\tconst value = parsed as Record<string, unknown>;\n\tif (\n\t\tObject.keys(value).length !== 2 ||\n\t\tvalue.version !== NODE_DISK_REGISTRY_SOURCE_VERSION_V1 ||\n\t\t!Array.isArray(value.records)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", \"Install store index schema is unsupported\");\n\tif (value.records.length > MAX_NODE_DISK_REGISTRY_RECORDS_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"too_many_records\", \"Install store index exceeds the record limit\");\n\treturn value.records.map((record, index) => validateRecord(root, record, index));\n}\n\n/** Read a bounded UTF-8 file; the absolute path never appears in a thrown message. */\nasync function readBoundedFile(path: string, maxBytes: number, label: string): Promise<string> {\n\tconst handle = await open(path, \"r\");\n\ttry {\n\t\tconst stat = await handle.stat();\n\t\tif (!stat.isFile() || stat.size > maxBytes)\n\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\tlabel === \"index\" ? \"invalid_index\" : \"invalid_manifest\",\n\t\t\t\t`${label} exceeds the size limit`,\n\t\t\t);\n\t\treturn await handle.readFile(\"utf8\");\n\t} finally {\n\t\tawait handle.close().catch(() => undefined);\n\t}\n}\n\nfunction parseManifest(record: DiskIndexRecordV1, raw: string): PluginManifestV1 {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", \"Installed plugin manifest JSON is invalid\");\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", \"Installed plugin manifest is not an object\");\n\tconst value = { ...(parsed as Record<string, unknown>) };\n\tif (value.packageFormatVersion !== undefined && value.packageFormatVersion !== NODE_PACKAGE_FORMAT_VERSION_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", \"Installed plugin package format is unsupported\");\n\t// The package envelope version is an install-host field; it is not part of\n\t// PluginManifestV1 and the stable manifest digest excludes it.\n\tdelete value.packageFormatVersion;\n\tif (value.id !== record.pluginId || value.pluginVersion !== record.pluginVersion)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"identity_mismatch\",\n\t\t\t`Installed plugin manifest identity does not match index record for ${record.pluginId}@${record.pluginVersion}`,\n\t\t);\n\treturn value as unknown as PluginManifestV1;\n}\n\n/** Read the install store index records; undefined when the store is empty. */\nasync function readIndexRecords(\n\trootDirectory: string,\n\tsignal: AbortSignal | undefined,\n): Promise<readonly DiskIndexRecordV1[] | undefined> {\n\tif (signal?.aborted) throw new NodeDiskRegistrySourceErrorV1(\"cancelled\", \"Disk registry source read was cancelled\");\n\tlet rawIndex: string;\n\ttry {\n\t\trawIndex = await readBoundedFile(\n\t\t\tjoin(rootDirectory, INDEX_FILE_V1),\n\t\t\tMAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1,\n\t\t\t\"index\",\n\t\t);\n\t} catch (error) {\n\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return undefined;\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", \"Install store index could not be read\");\n\t}\n\treturn parseIndex(rootDirectory, rawIndex);\n}\n\n/**\n * Read-only registry source over the default install store. It projects the\n * persistent index and each installation instance's ecosystem manifest as\n * bounded envelopes for the registry's own digest verification. It never\n * writes the index or installation directories, and installation directories\n * stay inside the host-owned store.\n */\nexport function createNodeDiskPluginRegistrySourceV1(\n\toptions: NodeDiskRegistrySourceOptionsV1,\n): NodeDiskRegistrySourceV1 {\n\tconst rootDirectory = options.rootDirectory;\n\tif (typeof rootDirectory !== \"string\" || !isAbsolute(rootDirectory) || rootDirectory.trim() === \"\")\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_configuration\", \"Install store root directory must be absolute\");\n\treturn {\n\t\tversion: NODE_DISK_REGISTRY_SOURCE_VERSION_V1,\n\t\tlist: async ({ signal } = {}) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return Object.freeze([]);\n\t\t\tconst envelopes: PluginRegistryManifestEnvelopeV1[] = [];\n\t\t\tfor (const record of records) {\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"cancelled\", \"Disk registry source read was cancelled\");\n\t\t\t\tlet rawManifest: string;\n\t\t\t\ttry {\n\t\t\t\t\trawManifest = await readBoundedFile(\n\t\t\t\t\t\tjoin(record.directory, ECOSYSTEM_MANIFEST_FILE_V1),\n\t\t\t\t\t\tMAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1,\n\t\t\t\t\t\t\"manifest\",\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", \"Installed plugin manifest could not be read\");\n\t\t\t\t}\n\t\t\t\tconst manifest = parseManifest(record, rawManifest);\n\t\t\t\tenvelopes.push({\n\t\t\t\t\tmanifest,\n\t\t\t\t\tsource: record.installationRef,\n\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn Object.freeze(envelopes);\n\t\t},\n\t\tresolveCapabilityManifestPath: async ({ pluginId, pluginVersion, signal }) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return undefined;\n\t\t\tconst record = records.find(\n\t\t\t\t(candidate) => candidate.pluginId === pluginId && candidate.pluginVersion === pluginVersion,\n\t\t\t);\n\t\t\tif (record === undefined) return undefined;\n\t\t\tconst manifestPath = join(record.directory, CAPABILITY_MANIFEST_FILE_V1);\n\t\t\ttry {\n\t\t\t\tconst handle = await open(manifestPath, \"r\");\n\t\t\t\tawait handle.close().catch(() => undefined);\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn manifestPath;\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"node-disk-registry-source.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-disk-registry-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAoC,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAG9F,QAAA,MAAM,oCAAoC,GAAa,CAAC;AACxD,oEAAoE;AACpE,eAAO,MAAM,qCAAqC,QAAc,CAAC;AACjE,+EAA+E;AAC/E,eAAO,MAAM,wCAAwC,QAAY,CAAC;AAClE,6FAA6F;AAC7F,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAOrD,MAAM,MAAM,iCAAiC,GAC1C,WAAW,GACX,uBAAuB,GACvB,eAAe,GACf,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,WAAW,CAAC;AAEf;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IAEjD,YAAY,IAAI,EAAE,iCAAiC,EAAE,OAAO,EAAE,MAAM,EAInE;CACD;AAED,MAAM,WAAW,+BAA+B;IAC/C,0FAA0F;IAC1F,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,oCAAoC;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAyB,SAAQ,sBAAsB;IACvE,QAAQ,CAAC,OAAO,EAAE,OAAO,oCAAoC,CAAC;IAC9D;;;;;;OAMG;IACH,QAAQ,CAAC,6BAA6B,CAAC,EAAE,CACxC,KAAK,EAAE,oCAAoC,KACvC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACjC;AA6JD;;;;;;GAMG;AACH,wBAAgB,oCAAoC,CACnD,OAAO,EAAE,+BAA+B,GACtC,wBAAwB,CAqD1B","sourcesContent":["import { open } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { t } from \"../../core/i18n/index.ts\";\nimport { withinInstallStoreRoot } from \"./install-store-paths.ts\";\nimport type { PluginRegistryManifestEnvelopeV1, PluginRegistrySourceV1 } from \"./registry.ts\";\nimport type { PluginManifestV1 } from \"./types.ts\";\n\nconst NODE_DISK_REGISTRY_SOURCE_VERSION_V1 = 1 as const;\n/** Maximum index.v1.json bytes accepted by this source boundary. */\nexport const MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1 = 1024 * 1024;\n/** Maximum per-installation agent-forge.json bytes accepted by this source. */\nexport const MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1 = 64 * 1024;\n/** Maximum index records projected by one list() call; matches the registry manifest cap. */\nexport const MAX_NODE_DISK_REGISTRY_RECORDS_V1 = 256;\n\nconst INDEX_FILE_V1 = \"index.v1.json\";\nconst ECOSYSTEM_MANIFEST_FILE_V1 = \"agent-forge.json\";\nconst CAPABILITY_MANIFEST_FILE_V1 = \"plugin.json\";\nconst NODE_PACKAGE_FORMAT_VERSION_V1 = 1;\n\nexport type NodeDiskRegistrySourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"invalid_index\"\n\t| \"invalid_manifest\"\n\t| \"identity_mismatch\"\n\t| \"too_many_records\"\n\t| \"io_failed\";\n\n/**\n * Deliberately does not retain filesystem exceptions or file contents: callers\n * must not turn registry diagnostics into a path or package disclosure.\n */\nexport class NodeDiskRegistrySourceErrorV1 extends Error {\n\treadonly code: NodeDiskRegistrySourceErrorCodeV1;\n\n\tconstructor(code: NodeDiskRegistrySourceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeDiskRegistrySourceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface NodeDiskRegistrySourceOptionsV1 {\n\t/** Absolute host-owned default install store directory. It is never returned in a DTO. */\n\treadonly rootDirectory: string;\n}\n\nexport interface NodeDiskRegistrySourceResolveInputV1 {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly signal?: AbortSignal;\n}\n\nexport interface NodeDiskRegistrySourceV1 extends PluginRegistrySourceV1 {\n\treadonly version: typeof NODE_DISK_REGISTRY_SOURCE_VERSION_V1;\n\t/**\n\t * Internal host channel (D-075 S2): absolute `plugin.json` path of the\n\t * installation directory matching `{pluginId, pluginVersion}` in the store\n\t * index, for the sdk's installed-plugin code loading. Registry snapshots\n\t * still carry no paths; undefined means no matching record or the manifest\n\t * file is absent from the installation directory.\n\t */\n\treadonly resolveCapabilityManifestPath?: (\n\t\tinput: NodeDiskRegistrySourceResolveInputV1,\n\t) => Promise<string | undefined>;\n}\n\ninterface DiskIndexRecordV1 {\n\treadonly installationRef: string;\n\treadonly directory: string;\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\treadonly scope: \"global\" | \"project\";\n\treadonly scopeRef: string;\n\treadonly state: \"installed\" | \"active\" | \"retained\";\n}\n\nconst INDEX_KEYS_V1 = [\n\t\"installationRef\",\n\t\"directory\",\n\t\"pluginId\",\n\t\"pluginVersion\",\n\t\"manifestDigest\",\n\t\"scope\",\n\t\"scopeRef\",\n\t\"state\",\n] as const;\n\nfunction opaqueField(value: unknown, max: number): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= max &&\n\t\t!/[\\u0000-\\u001f\\u007f]/u.test(value) &&\n\t\t!/\\s/u.test(value) &&\n\t\t!/^(?:file:|[a-z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value)\n\t);\n}\n\nfunction boundedField(value: unknown, max: number): value is string {\n\treturn typeof value === \"string\" && value.length > 0 && value.length <= max && !/[\\u0000-\\u001f\\u007f]/u.test(value);\n}\n\nfunction validateRecord(root: string, value: unknown, index: number): DiskIndexRecordV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Index record {index} is not an object\", { index }));\n\tconst record = value as Record<string, unknown>;\n\tconst keys = INDEX_KEYS_V1;\n\tif (Object.keys(record).length !== keys.length || keys.some((key) => !(key in record)))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"invalid_index\",\n\t\t\tt(\"Index record {index} has an invalid schema\", { index }),\n\t\t);\n\tif (\n\t\t!opaqueField(record.installationRef, 2048) ||\n\t\t!boundedField(record.directory, 2048) ||\n\t\t!boundedField(record.pluginId, 256) ||\n\t\t!boundedField(record.pluginVersion, 256) ||\n\t\t!boundedField(record.manifestDigest, 512) ||\n\t\t!opaqueField(record.scopeRef, 2048) ||\n\t\t(record.scope !== \"global\" && record.scope !== \"project\") ||\n\t\t(record.state !== \"installed\" && record.state !== \"active\" && record.state !== \"retained\") ||\n\t\t!withinInstallStoreRoot(root, record.directory)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Index record {index} is invalid\", { index }));\n\treturn {\n\t\tinstallationRef: record.installationRef,\n\t\tdirectory: record.directory,\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: record.scope,\n\t\tscopeRef: record.scopeRef,\n\t\tstate: record.state,\n\t};\n}\n\nfunction parseIndex(root: string, raw: string): readonly DiskIndexRecordV1[] {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Install store index JSON is invalid\"));\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Install store index is not an object\"));\n\tconst value = parsed as Record<string, unknown>;\n\tif (\n\t\tObject.keys(value).length !== 2 ||\n\t\tvalue.version !== NODE_DISK_REGISTRY_SOURCE_VERSION_V1 ||\n\t\t!Array.isArray(value.records)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Install store index schema is unsupported\"));\n\tif (value.records.length > MAX_NODE_DISK_REGISTRY_RECORDS_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"too_many_records\", t(\"Install store index exceeds the record limit\"));\n\treturn value.records.map((record, index) => validateRecord(root, record, index));\n}\n\n/** Read a bounded UTF-8 file; the absolute path never appears in a thrown message. */\nasync function readBoundedFile(path: string, maxBytes: number, label: string): Promise<string> {\n\tconst handle = await open(path, \"r\");\n\ttry {\n\t\tconst stat = await handle.stat();\n\t\tif (!stat.isFile() || stat.size > maxBytes)\n\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\tlabel === \"index\" ? \"invalid_index\" : \"invalid_manifest\",\n\t\t\t\tt(\"{label} exceeds the size limit\", { label }),\n\t\t\t);\n\t\treturn await handle.readFile(\"utf8\");\n\t} finally {\n\t\tawait handle.close().catch(() => undefined);\n\t}\n}\n\nfunction parseManifest(record: DiskIndexRecordV1, raw: string): PluginManifestV1 {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", t(\"Installed plugin manifest JSON is invalid\"));\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", t(\"Installed plugin manifest is not an object\"));\n\tconst value = { ...(parsed as Record<string, unknown>) };\n\tif (value.packageFormatVersion !== undefined && value.packageFormatVersion !== NODE_PACKAGE_FORMAT_VERSION_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", t(\"Installed plugin package format is unsupported\"));\n\t// The package envelope version is an install-host field; it is not part of\n\t// PluginManifestV1 and the stable manifest digest excludes it.\n\tdelete value.packageFormatVersion;\n\tif (value.id !== record.pluginId || value.pluginVersion !== record.pluginVersion)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"identity_mismatch\",\n\t\t\tt(\"Installed plugin manifest identity does not match index record for {identity}\", {\n\t\t\t\tidentity: `${record.pluginId}@${record.pluginVersion}`,\n\t\t\t}),\n\t\t);\n\treturn value as unknown as PluginManifestV1;\n}\n\n/** Read the install store index records; undefined when the store is empty. */\nasync function readIndexRecords(\n\trootDirectory: string,\n\tsignal: AbortSignal | undefined,\n): Promise<readonly DiskIndexRecordV1[] | undefined> {\n\tif (signal?.aborted)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"cancelled\", t(\"Disk registry source read was cancelled\"));\n\tlet rawIndex: string;\n\ttry {\n\t\trawIndex = await readBoundedFile(\n\t\t\tjoin(rootDirectory, INDEX_FILE_V1),\n\t\t\tMAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1,\n\t\t\t\"index\",\n\t\t);\n\t} catch (error) {\n\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return undefined;\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", t(\"Install store index could not be read\"));\n\t}\n\treturn parseIndex(rootDirectory, rawIndex);\n}\n\n/**\n * Read-only registry source over the default install store. It projects the\n * persistent index and each installation instance's ecosystem manifest as\n * bounded envelopes for the registry's own digest verification. It never\n * writes the index or installation directories, and installation directories\n * stay inside the host-owned store.\n */\nexport function createNodeDiskPluginRegistrySourceV1(\n\toptions: NodeDiskRegistrySourceOptionsV1,\n): NodeDiskRegistrySourceV1 {\n\tconst rootDirectory = options.rootDirectory;\n\tif (typeof rootDirectory !== \"string\" || !isAbsolute(rootDirectory) || rootDirectory.trim() === \"\")\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"Install store root directory must be absolute\"),\n\t\t);\n\treturn {\n\t\tversion: NODE_DISK_REGISTRY_SOURCE_VERSION_V1,\n\t\tlist: async ({ signal } = {}) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return Object.freeze([]);\n\t\t\tconst envelopes: PluginRegistryManifestEnvelopeV1[] = [];\n\t\t\tfor (const record of records) {\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"cancelled\", t(\"Disk registry source read was cancelled\"));\n\t\t\t\tlet rawManifest: string;\n\t\t\t\ttry {\n\t\t\t\t\trawManifest = await readBoundedFile(\n\t\t\t\t\t\tjoin(record.directory, ECOSYSTEM_MANIFEST_FILE_V1),\n\t\t\t\t\t\tMAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1,\n\t\t\t\t\t\t\"manifest\",\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", t(\"Installed plugin manifest could not be read\"));\n\t\t\t\t}\n\t\t\t\tconst manifest = parseManifest(record, rawManifest);\n\t\t\t\tenvelopes.push({\n\t\t\t\t\tmanifest,\n\t\t\t\t\tsource: record.installationRef,\n\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn Object.freeze(envelopes);\n\t\t},\n\t\tresolveCapabilityManifestPath: async ({ pluginId, pluginVersion, signal }) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return undefined;\n\t\t\tconst record = records.find(\n\t\t\t\t(candidate) => candidate.pluginId === pluginId && candidate.pluginVersion === pluginVersion,\n\t\t\t);\n\t\t\tif (record === undefined) return undefined;\n\t\t\tconst manifestPath = join(record.directory, CAPABILITY_MANIFEST_FILE_V1);\n\t\t\ttry {\n\t\t\t\tconst handle = await open(manifestPath, \"r\");\n\t\t\t\tawait handle.close().catch(() => undefined);\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn manifestPath;\n\t\t},\n\t};\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { open } from "node:fs/promises";
2
2
  import { isAbsolute, join } from "node:path";
3
+ import { t } from "../../core/i18n/index.js";
3
4
  import { withinInstallStoreRoot } from "./install-store-paths.js";
4
5
  const NODE_DISK_REGISTRY_SOURCE_VERSION_V1 = 1;
5
6
  /** Maximum index.v1.json bytes accepted by this source boundary. */
@@ -47,11 +48,11 @@ function boundedField(value, max) {
47
48
  }
48
49
  function validateRecord(root, value, index) {
49
50
  if (value === null || typeof value !== "object" || Array.isArray(value))
50
- throw new NodeDiskRegistrySourceErrorV1("invalid_index", `Index record ${index} is not an object`);
51
+ throw new NodeDiskRegistrySourceErrorV1("invalid_index", t("Index record {index} is not an object", { index }));
51
52
  const record = value;
52
53
  const keys = INDEX_KEYS_V1;
53
54
  if (Object.keys(record).length !== keys.length || keys.some((key) => !(key in record)))
54
- throw new NodeDiskRegistrySourceErrorV1("invalid_index", `Index record ${index} has an invalid schema`);
55
+ throw new NodeDiskRegistrySourceErrorV1("invalid_index", t("Index record {index} has an invalid schema", { index }));
55
56
  if (!opaqueField(record.installationRef, 2048) ||
56
57
  !boundedField(record.directory, 2048) ||
57
58
  !boundedField(record.pluginId, 256) ||
@@ -61,7 +62,7 @@ function validateRecord(root, value, index) {
61
62
  (record.scope !== "global" && record.scope !== "project") ||
62
63
  (record.state !== "installed" && record.state !== "active" && record.state !== "retained") ||
63
64
  !withinInstallStoreRoot(root, record.directory))
64
- throw new NodeDiskRegistrySourceErrorV1("invalid_index", `Index record ${index} is invalid`);
65
+ throw new NodeDiskRegistrySourceErrorV1("invalid_index", t("Index record {index} is invalid", { index }));
65
66
  return {
66
67
  installationRef: record.installationRef,
67
68
  directory: record.directory,
@@ -79,17 +80,17 @@ function parseIndex(root, raw) {
79
80
  parsed = JSON.parse(raw);
80
81
  }
81
82
  catch {
82
- throw new NodeDiskRegistrySourceErrorV1("invalid_index", "Install store index JSON is invalid");
83
+ throw new NodeDiskRegistrySourceErrorV1("invalid_index", t("Install store index JSON is invalid"));
83
84
  }
84
85
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
85
- throw new NodeDiskRegistrySourceErrorV1("invalid_index", "Install store index is not an object");
86
+ throw new NodeDiskRegistrySourceErrorV1("invalid_index", t("Install store index is not an object"));
86
87
  const value = parsed;
87
88
  if (Object.keys(value).length !== 2 ||
88
89
  value.version !== NODE_DISK_REGISTRY_SOURCE_VERSION_V1 ||
89
90
  !Array.isArray(value.records))
90
- throw new NodeDiskRegistrySourceErrorV1("invalid_index", "Install store index schema is unsupported");
91
+ throw new NodeDiskRegistrySourceErrorV1("invalid_index", t("Install store index schema is unsupported"));
91
92
  if (value.records.length > MAX_NODE_DISK_REGISTRY_RECORDS_V1)
92
- throw new NodeDiskRegistrySourceErrorV1("too_many_records", "Install store index exceeds the record limit");
93
+ throw new NodeDiskRegistrySourceErrorV1("too_many_records", t("Install store index exceeds the record limit"));
93
94
  return value.records.map((record, index) => validateRecord(root, record, index));
94
95
  }
95
96
  /** Read a bounded UTF-8 file; the absolute path never appears in a thrown message. */
@@ -98,7 +99,7 @@ async function readBoundedFile(path, maxBytes, label) {
98
99
  try {
99
100
  const stat = await handle.stat();
100
101
  if (!stat.isFile() || stat.size > maxBytes)
101
- throw new NodeDiskRegistrySourceErrorV1(label === "index" ? "invalid_index" : "invalid_manifest", `${label} exceeds the size limit`);
102
+ throw new NodeDiskRegistrySourceErrorV1(label === "index" ? "invalid_index" : "invalid_manifest", t("{label} exceeds the size limit", { label }));
102
103
  return await handle.readFile("utf8");
103
104
  }
104
105
  finally {
@@ -111,24 +112,26 @@ function parseManifest(record, raw) {
111
112
  parsed = JSON.parse(raw);
112
113
  }
113
114
  catch {
114
- throw new NodeDiskRegistrySourceErrorV1("invalid_manifest", "Installed plugin manifest JSON is invalid");
115
+ throw new NodeDiskRegistrySourceErrorV1("invalid_manifest", t("Installed plugin manifest JSON is invalid"));
115
116
  }
116
117
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
117
- throw new NodeDiskRegistrySourceErrorV1("invalid_manifest", "Installed plugin manifest is not an object");
118
+ throw new NodeDiskRegistrySourceErrorV1("invalid_manifest", t("Installed plugin manifest is not an object"));
118
119
  const value = { ...parsed };
119
120
  if (value.packageFormatVersion !== undefined && value.packageFormatVersion !== NODE_PACKAGE_FORMAT_VERSION_V1)
120
- throw new NodeDiskRegistrySourceErrorV1("invalid_manifest", "Installed plugin package format is unsupported");
121
+ throw new NodeDiskRegistrySourceErrorV1("invalid_manifest", t("Installed plugin package format is unsupported"));
121
122
  // The package envelope version is an install-host field; it is not part of
122
123
  // PluginManifestV1 and the stable manifest digest excludes it.
123
124
  delete value.packageFormatVersion;
124
125
  if (value.id !== record.pluginId || value.pluginVersion !== record.pluginVersion)
125
- throw new NodeDiskRegistrySourceErrorV1("identity_mismatch", `Installed plugin manifest identity does not match index record for ${record.pluginId}@${record.pluginVersion}`);
126
+ throw new NodeDiskRegistrySourceErrorV1("identity_mismatch", t("Installed plugin manifest identity does not match index record for {identity}", {
127
+ identity: `${record.pluginId}@${record.pluginVersion}`,
128
+ }));
126
129
  return value;
127
130
  }
128
131
  /** Read the install store index records; undefined when the store is empty. */
129
132
  async function readIndexRecords(rootDirectory, signal) {
130
133
  if (signal?.aborted)
131
- throw new NodeDiskRegistrySourceErrorV1("cancelled", "Disk registry source read was cancelled");
134
+ throw new NodeDiskRegistrySourceErrorV1("cancelled", t("Disk registry source read was cancelled"));
132
135
  let rawIndex;
133
136
  try {
134
137
  rawIndex = await readBoundedFile(join(rootDirectory, INDEX_FILE_V1), MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1, "index");
@@ -138,7 +141,7 @@ async function readIndexRecords(rootDirectory, signal) {
138
141
  throw error;
139
142
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
140
143
  return undefined;
141
- throw new NodeDiskRegistrySourceErrorV1("io_failed", "Install store index could not be read");
144
+ throw new NodeDiskRegistrySourceErrorV1("io_failed", t("Install store index could not be read"));
142
145
  }
143
146
  return parseIndex(rootDirectory, rawIndex);
144
147
  }
@@ -152,7 +155,7 @@ async function readIndexRecords(rootDirectory, signal) {
152
155
  export function createNodeDiskPluginRegistrySourceV1(options) {
153
156
  const rootDirectory = options.rootDirectory;
154
157
  if (typeof rootDirectory !== "string" || !isAbsolute(rootDirectory) || rootDirectory.trim() === "")
155
- throw new NodeDiskRegistrySourceErrorV1("invalid_configuration", "Install store root directory must be absolute");
158
+ throw new NodeDiskRegistrySourceErrorV1("invalid_configuration", t("Install store root directory must be absolute"));
156
159
  return {
157
160
  version: NODE_DISK_REGISTRY_SOURCE_VERSION_V1,
158
161
  list: async ({ signal } = {}) => {
@@ -162,7 +165,7 @@ export function createNodeDiskPluginRegistrySourceV1(options) {
162
165
  const envelopes = [];
163
166
  for (const record of records) {
164
167
  if (signal?.aborted)
165
- throw new NodeDiskRegistrySourceErrorV1("cancelled", "Disk registry source read was cancelled");
168
+ throw new NodeDiskRegistrySourceErrorV1("cancelled", t("Disk registry source read was cancelled"));
166
169
  let rawManifest;
167
170
  try {
168
171
  rawManifest = await readBoundedFile(join(record.directory, ECOSYSTEM_MANIFEST_FILE_V1), MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1, "manifest");
@@ -170,7 +173,7 @@ export function createNodeDiskPluginRegistrySourceV1(options) {
170
173
  catch (error) {
171
174
  if (error instanceof NodeDiskRegistrySourceErrorV1)
172
175
  throw error;
173
- throw new NodeDiskRegistrySourceErrorV1("io_failed", "Installed plugin manifest could not be read");
176
+ throw new NodeDiskRegistrySourceErrorV1("io_failed", t("Installed plugin manifest could not be read"));
174
177
  }
175
178
  const manifest = parseManifest(record, rawManifest);
176
179
  envelopes.push({
@@ -1 +1 @@
1
- {"version":3,"file":"node-disk-registry-source.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-disk-registry-source.ts"],"names":[],"mappings":"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","sourcesContent":["import { open } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { withinInstallStoreRoot } from \"./install-store-paths.ts\";\nimport type { PluginRegistryManifestEnvelopeV1, PluginRegistrySourceV1 } from \"./registry.ts\";\nimport type { PluginManifestV1 } from \"./types.ts\";\n\nconst NODE_DISK_REGISTRY_SOURCE_VERSION_V1 = 1 as const;\n/** Maximum index.v1.json bytes accepted by this source boundary. */\nexport const MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1 = 1024 * 1024;\n/** Maximum per-installation agent-forge.json bytes accepted by this source. */\nexport const MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1 = 64 * 1024;\n/** Maximum index records projected by one list() call; matches the registry manifest cap. */\nexport const MAX_NODE_DISK_REGISTRY_RECORDS_V1 = 256;\n\nconst INDEX_FILE_V1 = \"index.v1.json\";\nconst ECOSYSTEM_MANIFEST_FILE_V1 = \"agent-forge.json\";\nconst CAPABILITY_MANIFEST_FILE_V1 = \"plugin.json\";\nconst NODE_PACKAGE_FORMAT_VERSION_V1 = 1;\n\nexport type NodeDiskRegistrySourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"invalid_index\"\n\t| \"invalid_manifest\"\n\t| \"identity_mismatch\"\n\t| \"too_many_records\"\n\t| \"io_failed\";\n\n/**\n * Deliberately does not retain filesystem exceptions or file contents: callers\n * must not turn registry diagnostics into a path or package disclosure.\n */\nexport class NodeDiskRegistrySourceErrorV1 extends Error {\n\treadonly code: NodeDiskRegistrySourceErrorCodeV1;\n\n\tconstructor(code: NodeDiskRegistrySourceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeDiskRegistrySourceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface NodeDiskRegistrySourceOptionsV1 {\n\t/** Absolute host-owned default install store directory. It is never returned in a DTO. */\n\treadonly rootDirectory: string;\n}\n\nexport interface NodeDiskRegistrySourceResolveInputV1 {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly signal?: AbortSignal;\n}\n\nexport interface NodeDiskRegistrySourceV1 extends PluginRegistrySourceV1 {\n\treadonly version: typeof NODE_DISK_REGISTRY_SOURCE_VERSION_V1;\n\t/**\n\t * Internal host channel (D-075 S2): absolute `plugin.json` path of the\n\t * installation directory matching `{pluginId, pluginVersion}` in the store\n\t * index, for the sdk's installed-plugin code loading. Registry snapshots\n\t * still carry no paths; undefined means no matching record or the manifest\n\t * file is absent from the installation directory.\n\t */\n\treadonly resolveCapabilityManifestPath?: (\n\t\tinput: NodeDiskRegistrySourceResolveInputV1,\n\t) => Promise<string | undefined>;\n}\n\ninterface DiskIndexRecordV1 {\n\treadonly installationRef: string;\n\treadonly directory: string;\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\treadonly scope: \"global\" | \"project\";\n\treadonly scopeRef: string;\n\treadonly state: \"installed\" | \"active\" | \"retained\";\n}\n\nconst INDEX_KEYS_V1 = [\n\t\"installationRef\",\n\t\"directory\",\n\t\"pluginId\",\n\t\"pluginVersion\",\n\t\"manifestDigest\",\n\t\"scope\",\n\t\"scopeRef\",\n\t\"state\",\n] as const;\n\nfunction opaqueField(value: unknown, max: number): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= max &&\n\t\t!/[\\u0000-\\u001f\\u007f]/u.test(value) &&\n\t\t!/\\s/u.test(value) &&\n\t\t!/^(?:file:|[a-z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value)\n\t);\n}\n\nfunction boundedField(value: unknown, max: number): value is string {\n\treturn typeof value === \"string\" && value.length > 0 && value.length <= max && !/[\\u0000-\\u001f\\u007f]/u.test(value);\n}\n\nfunction validateRecord(root: string, value: unknown, index: number): DiskIndexRecordV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", `Index record ${index} is not an object`);\n\tconst record = value as Record<string, unknown>;\n\tconst keys = INDEX_KEYS_V1;\n\tif (Object.keys(record).length !== keys.length || keys.some((key) => !(key in record)))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", `Index record ${index} has an invalid schema`);\n\tif (\n\t\t!opaqueField(record.installationRef, 2048) ||\n\t\t!boundedField(record.directory, 2048) ||\n\t\t!boundedField(record.pluginId, 256) ||\n\t\t!boundedField(record.pluginVersion, 256) ||\n\t\t!boundedField(record.manifestDigest, 512) ||\n\t\t!opaqueField(record.scopeRef, 2048) ||\n\t\t(record.scope !== \"global\" && record.scope !== \"project\") ||\n\t\t(record.state !== \"installed\" && record.state !== \"active\" && record.state !== \"retained\") ||\n\t\t!withinInstallStoreRoot(root, record.directory)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", `Index record ${index} is invalid`);\n\treturn {\n\t\tinstallationRef: record.installationRef,\n\t\tdirectory: record.directory,\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: record.scope,\n\t\tscopeRef: record.scopeRef,\n\t\tstate: record.state,\n\t};\n}\n\nfunction parseIndex(root: string, raw: string): readonly DiskIndexRecordV1[] {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", \"Install store index JSON is invalid\");\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", \"Install store index is not an object\");\n\tconst value = parsed as Record<string, unknown>;\n\tif (\n\t\tObject.keys(value).length !== 2 ||\n\t\tvalue.version !== NODE_DISK_REGISTRY_SOURCE_VERSION_V1 ||\n\t\t!Array.isArray(value.records)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", \"Install store index schema is unsupported\");\n\tif (value.records.length > MAX_NODE_DISK_REGISTRY_RECORDS_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"too_many_records\", \"Install store index exceeds the record limit\");\n\treturn value.records.map((record, index) => validateRecord(root, record, index));\n}\n\n/** Read a bounded UTF-8 file; the absolute path never appears in a thrown message. */\nasync function readBoundedFile(path: string, maxBytes: number, label: string): Promise<string> {\n\tconst handle = await open(path, \"r\");\n\ttry {\n\t\tconst stat = await handle.stat();\n\t\tif (!stat.isFile() || stat.size > maxBytes)\n\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\tlabel === \"index\" ? \"invalid_index\" : \"invalid_manifest\",\n\t\t\t\t`${label} exceeds the size limit`,\n\t\t\t);\n\t\treturn await handle.readFile(\"utf8\");\n\t} finally {\n\t\tawait handle.close().catch(() => undefined);\n\t}\n}\n\nfunction parseManifest(record: DiskIndexRecordV1, raw: string): PluginManifestV1 {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", \"Installed plugin manifest JSON is invalid\");\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", \"Installed plugin manifest is not an object\");\n\tconst value = { ...(parsed as Record<string, unknown>) };\n\tif (value.packageFormatVersion !== undefined && value.packageFormatVersion !== NODE_PACKAGE_FORMAT_VERSION_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", \"Installed plugin package format is unsupported\");\n\t// The package envelope version is an install-host field; it is not part of\n\t// PluginManifestV1 and the stable manifest digest excludes it.\n\tdelete value.packageFormatVersion;\n\tif (value.id !== record.pluginId || value.pluginVersion !== record.pluginVersion)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"identity_mismatch\",\n\t\t\t`Installed plugin manifest identity does not match index record for ${record.pluginId}@${record.pluginVersion}`,\n\t\t);\n\treturn value as unknown as PluginManifestV1;\n}\n\n/** Read the install store index records; undefined when the store is empty. */\nasync function readIndexRecords(\n\trootDirectory: string,\n\tsignal: AbortSignal | undefined,\n): Promise<readonly DiskIndexRecordV1[] | undefined> {\n\tif (signal?.aborted) throw new NodeDiskRegistrySourceErrorV1(\"cancelled\", \"Disk registry source read was cancelled\");\n\tlet rawIndex: string;\n\ttry {\n\t\trawIndex = await readBoundedFile(\n\t\t\tjoin(rootDirectory, INDEX_FILE_V1),\n\t\t\tMAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1,\n\t\t\t\"index\",\n\t\t);\n\t} catch (error) {\n\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return undefined;\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", \"Install store index could not be read\");\n\t}\n\treturn parseIndex(rootDirectory, rawIndex);\n}\n\n/**\n * Read-only registry source over the default install store. It projects the\n * persistent index and each installation instance's ecosystem manifest as\n * bounded envelopes for the registry's own digest verification. It never\n * writes the index or installation directories, and installation directories\n * stay inside the host-owned store.\n */\nexport function createNodeDiskPluginRegistrySourceV1(\n\toptions: NodeDiskRegistrySourceOptionsV1,\n): NodeDiskRegistrySourceV1 {\n\tconst rootDirectory = options.rootDirectory;\n\tif (typeof rootDirectory !== \"string\" || !isAbsolute(rootDirectory) || rootDirectory.trim() === \"\")\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_configuration\", \"Install store root directory must be absolute\");\n\treturn {\n\t\tversion: NODE_DISK_REGISTRY_SOURCE_VERSION_V1,\n\t\tlist: async ({ signal } = {}) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return Object.freeze([]);\n\t\t\tconst envelopes: PluginRegistryManifestEnvelopeV1[] = [];\n\t\t\tfor (const record of records) {\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"cancelled\", \"Disk registry source read was cancelled\");\n\t\t\t\tlet rawManifest: string;\n\t\t\t\ttry {\n\t\t\t\t\trawManifest = await readBoundedFile(\n\t\t\t\t\t\tjoin(record.directory, ECOSYSTEM_MANIFEST_FILE_V1),\n\t\t\t\t\t\tMAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1,\n\t\t\t\t\t\t\"manifest\",\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", \"Installed plugin manifest could not be read\");\n\t\t\t\t}\n\t\t\t\tconst manifest = parseManifest(record, rawManifest);\n\t\t\t\tenvelopes.push({\n\t\t\t\t\tmanifest,\n\t\t\t\t\tsource: record.installationRef,\n\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn Object.freeze(envelopes);\n\t\t},\n\t\tresolveCapabilityManifestPath: async ({ pluginId, pluginVersion, signal }) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return undefined;\n\t\t\tconst record = records.find(\n\t\t\t\t(candidate) => candidate.pluginId === pluginId && candidate.pluginVersion === pluginVersion,\n\t\t\t);\n\t\t\tif (record === undefined) return undefined;\n\t\t\tconst manifestPath = join(record.directory, CAPABILITY_MANIFEST_FILE_V1);\n\t\t\ttry {\n\t\t\t\tconst handle = await open(manifestPath, \"r\");\n\t\t\t\tawait handle.close().catch(() => undefined);\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn manifestPath;\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"node-disk-registry-source.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-disk-registry-source.ts"],"names":[],"mappings":"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","sourcesContent":["import { open } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { t } from \"../../core/i18n/index.ts\";\nimport { withinInstallStoreRoot } from \"./install-store-paths.ts\";\nimport type { PluginRegistryManifestEnvelopeV1, PluginRegistrySourceV1 } from \"./registry.ts\";\nimport type { PluginManifestV1 } from \"./types.ts\";\n\nconst NODE_DISK_REGISTRY_SOURCE_VERSION_V1 = 1 as const;\n/** Maximum index.v1.json bytes accepted by this source boundary. */\nexport const MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1 = 1024 * 1024;\n/** Maximum per-installation agent-forge.json bytes accepted by this source. */\nexport const MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1 = 64 * 1024;\n/** Maximum index records projected by one list() call; matches the registry manifest cap. */\nexport const MAX_NODE_DISK_REGISTRY_RECORDS_V1 = 256;\n\nconst INDEX_FILE_V1 = \"index.v1.json\";\nconst ECOSYSTEM_MANIFEST_FILE_V1 = \"agent-forge.json\";\nconst CAPABILITY_MANIFEST_FILE_V1 = \"plugin.json\";\nconst NODE_PACKAGE_FORMAT_VERSION_V1 = 1;\n\nexport type NodeDiskRegistrySourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"invalid_index\"\n\t| \"invalid_manifest\"\n\t| \"identity_mismatch\"\n\t| \"too_many_records\"\n\t| \"io_failed\";\n\n/**\n * Deliberately does not retain filesystem exceptions or file contents: callers\n * must not turn registry diagnostics into a path or package disclosure.\n */\nexport class NodeDiskRegistrySourceErrorV1 extends Error {\n\treadonly code: NodeDiskRegistrySourceErrorCodeV1;\n\n\tconstructor(code: NodeDiskRegistrySourceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeDiskRegistrySourceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface NodeDiskRegistrySourceOptionsV1 {\n\t/** Absolute host-owned default install store directory. It is never returned in a DTO. */\n\treadonly rootDirectory: string;\n}\n\nexport interface NodeDiskRegistrySourceResolveInputV1 {\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly signal?: AbortSignal;\n}\n\nexport interface NodeDiskRegistrySourceV1 extends PluginRegistrySourceV1 {\n\treadonly version: typeof NODE_DISK_REGISTRY_SOURCE_VERSION_V1;\n\t/**\n\t * Internal host channel (D-075 S2): absolute `plugin.json` path of the\n\t * installation directory matching `{pluginId, pluginVersion}` in the store\n\t * index, for the sdk's installed-plugin code loading. Registry snapshots\n\t * still carry no paths; undefined means no matching record or the manifest\n\t * file is absent from the installation directory.\n\t */\n\treadonly resolveCapabilityManifestPath?: (\n\t\tinput: NodeDiskRegistrySourceResolveInputV1,\n\t) => Promise<string | undefined>;\n}\n\ninterface DiskIndexRecordV1 {\n\treadonly installationRef: string;\n\treadonly directory: string;\n\treadonly pluginId: string;\n\treadonly pluginVersion: string;\n\treadonly manifestDigest: string;\n\treadonly scope: \"global\" | \"project\";\n\treadonly scopeRef: string;\n\treadonly state: \"installed\" | \"active\" | \"retained\";\n}\n\nconst INDEX_KEYS_V1 = [\n\t\"installationRef\",\n\t\"directory\",\n\t\"pluginId\",\n\t\"pluginVersion\",\n\t\"manifestDigest\",\n\t\"scope\",\n\t\"scopeRef\",\n\t\"state\",\n] as const;\n\nfunction opaqueField(value: unknown, max: number): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= max &&\n\t\t!/[\\u0000-\\u001f\\u007f]/u.test(value) &&\n\t\t!/\\s/u.test(value) &&\n\t\t!/^(?:file:|[a-z]:[\\\\/]|[\\\\/]{1,2}|\\\\\\\\)/iu.test(value)\n\t);\n}\n\nfunction boundedField(value: unknown, max: number): value is string {\n\treturn typeof value === \"string\" && value.length > 0 && value.length <= max && !/[\\u0000-\\u001f\\u007f]/u.test(value);\n}\n\nfunction validateRecord(root: string, value: unknown, index: number): DiskIndexRecordV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Index record {index} is not an object\", { index }));\n\tconst record = value as Record<string, unknown>;\n\tconst keys = INDEX_KEYS_V1;\n\tif (Object.keys(record).length !== keys.length || keys.some((key) => !(key in record)))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"invalid_index\",\n\t\t\tt(\"Index record {index} has an invalid schema\", { index }),\n\t\t);\n\tif (\n\t\t!opaqueField(record.installationRef, 2048) ||\n\t\t!boundedField(record.directory, 2048) ||\n\t\t!boundedField(record.pluginId, 256) ||\n\t\t!boundedField(record.pluginVersion, 256) ||\n\t\t!boundedField(record.manifestDigest, 512) ||\n\t\t!opaqueField(record.scopeRef, 2048) ||\n\t\t(record.scope !== \"global\" && record.scope !== \"project\") ||\n\t\t(record.state !== \"installed\" && record.state !== \"active\" && record.state !== \"retained\") ||\n\t\t!withinInstallStoreRoot(root, record.directory)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Index record {index} is invalid\", { index }));\n\treturn {\n\t\tinstallationRef: record.installationRef,\n\t\tdirectory: record.directory,\n\t\tpluginId: record.pluginId,\n\t\tpluginVersion: record.pluginVersion,\n\t\tmanifestDigest: record.manifestDigest,\n\t\tscope: record.scope,\n\t\tscopeRef: record.scopeRef,\n\t\tstate: record.state,\n\t};\n}\n\nfunction parseIndex(root: string, raw: string): readonly DiskIndexRecordV1[] {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Install store index JSON is invalid\"));\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Install store index is not an object\"));\n\tconst value = parsed as Record<string, unknown>;\n\tif (\n\t\tObject.keys(value).length !== 2 ||\n\t\tvalue.version !== NODE_DISK_REGISTRY_SOURCE_VERSION_V1 ||\n\t\t!Array.isArray(value.records)\n\t)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_index\", t(\"Install store index schema is unsupported\"));\n\tif (value.records.length > MAX_NODE_DISK_REGISTRY_RECORDS_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"too_many_records\", t(\"Install store index exceeds the record limit\"));\n\treturn value.records.map((record, index) => validateRecord(root, record, index));\n}\n\n/** Read a bounded UTF-8 file; the absolute path never appears in a thrown message. */\nasync function readBoundedFile(path: string, maxBytes: number, label: string): Promise<string> {\n\tconst handle = await open(path, \"r\");\n\ttry {\n\t\tconst stat = await handle.stat();\n\t\tif (!stat.isFile() || stat.size > maxBytes)\n\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\tlabel === \"index\" ? \"invalid_index\" : \"invalid_manifest\",\n\t\t\t\tt(\"{label} exceeds the size limit\", { label }),\n\t\t\t);\n\t\treturn await handle.readFile(\"utf8\");\n\t} finally {\n\t\tawait handle.close().catch(() => undefined);\n\t}\n}\n\nfunction parseManifest(record: DiskIndexRecordV1, raw: string): PluginManifestV1 {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", t(\"Installed plugin manifest JSON is invalid\"));\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", t(\"Installed plugin manifest is not an object\"));\n\tconst value = { ...(parsed as Record<string, unknown>) };\n\tif (value.packageFormatVersion !== undefined && value.packageFormatVersion !== NODE_PACKAGE_FORMAT_VERSION_V1)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"invalid_manifest\", t(\"Installed plugin package format is unsupported\"));\n\t// The package envelope version is an install-host field; it is not part of\n\t// PluginManifestV1 and the stable manifest digest excludes it.\n\tdelete value.packageFormatVersion;\n\tif (value.id !== record.pluginId || value.pluginVersion !== record.pluginVersion)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"identity_mismatch\",\n\t\t\tt(\"Installed plugin manifest identity does not match index record for {identity}\", {\n\t\t\t\tidentity: `${record.pluginId}@${record.pluginVersion}`,\n\t\t\t}),\n\t\t);\n\treturn value as unknown as PluginManifestV1;\n}\n\n/** Read the install store index records; undefined when the store is empty. */\nasync function readIndexRecords(\n\trootDirectory: string,\n\tsignal: AbortSignal | undefined,\n): Promise<readonly DiskIndexRecordV1[] | undefined> {\n\tif (signal?.aborted)\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"cancelled\", t(\"Disk registry source read was cancelled\"));\n\tlet rawIndex: string;\n\ttry {\n\t\trawIndex = await readBoundedFile(\n\t\t\tjoin(rootDirectory, INDEX_FILE_V1),\n\t\t\tMAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1,\n\t\t\t\"index\",\n\t\t);\n\t} catch (error) {\n\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return undefined;\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", t(\"Install store index could not be read\"));\n\t}\n\treturn parseIndex(rootDirectory, rawIndex);\n}\n\n/**\n * Read-only registry source over the default install store. It projects the\n * persistent index and each installation instance's ecosystem manifest as\n * bounded envelopes for the registry's own digest verification. It never\n * writes the index or installation directories, and installation directories\n * stay inside the host-owned store.\n */\nexport function createNodeDiskPluginRegistrySourceV1(\n\toptions: NodeDiskRegistrySourceOptionsV1,\n): NodeDiskRegistrySourceV1 {\n\tconst rootDirectory = options.rootDirectory;\n\tif (typeof rootDirectory !== \"string\" || !isAbsolute(rootDirectory) || rootDirectory.trim() === \"\")\n\t\tthrow new NodeDiskRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"Install store root directory must be absolute\"),\n\t\t);\n\treturn {\n\t\tversion: NODE_DISK_REGISTRY_SOURCE_VERSION_V1,\n\t\tlist: async ({ signal } = {}) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return Object.freeze([]);\n\t\t\tconst envelopes: PluginRegistryManifestEnvelopeV1[] = [];\n\t\t\tfor (const record of records) {\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"cancelled\", t(\"Disk registry source read was cancelled\"));\n\t\t\t\tlet rawManifest: string;\n\t\t\t\ttry {\n\t\t\t\t\trawManifest = await readBoundedFile(\n\t\t\t\t\t\tjoin(record.directory, ECOSYSTEM_MANIFEST_FILE_V1),\n\t\t\t\t\t\tMAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1,\n\t\t\t\t\t\t\"manifest\",\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof NodeDiskRegistrySourceErrorV1) throw error;\n\t\t\t\t\tthrow new NodeDiskRegistrySourceErrorV1(\"io_failed\", t(\"Installed plugin manifest could not be read\"));\n\t\t\t\t}\n\t\t\t\tconst manifest = parseManifest(record, rawManifest);\n\t\t\t\tenvelopes.push({\n\t\t\t\t\tmanifest,\n\t\t\t\t\tsource: record.installationRef,\n\t\t\t\t\tmanifestDigest: record.manifestDigest,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn Object.freeze(envelopes);\n\t\t},\n\t\tresolveCapabilityManifestPath: async ({ pluginId, pluginVersion, signal }) => {\n\t\t\tconst records = await readIndexRecords(rootDirectory, signal);\n\t\t\tif (records === undefined) return undefined;\n\t\t\tconst record = records.find(\n\t\t\t\t(candidate) => candidate.pluginId === pluginId && candidate.pluginVersion === pluginVersion,\n\t\t\t);\n\t\t\tif (record === undefined) return undefined;\n\t\t\tconst manifestPath = join(record.directory, CAPABILITY_MANIFEST_FILE_V1);\n\t\t\ttry {\n\t\t\t\tconst handle = await open(manifestPath, \"r\");\n\t\t\t\tawait handle.close().catch(() => undefined);\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn manifestPath;\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"node-distribution-host.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-distribution-host.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEX,4BAA4B,EAE5B,wBAAwB,EAExB,oBAAoB,EACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAA+B,KAAK,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAE7G,QAAA,MAAM,iCAAiC,GAAa,CAAC;AAOrD,MAAM,WAAW,uCAAuC;IACvD,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,oFAAoF;IACpF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gCAAgC;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,iCAAiC,CAAC;IAC3D,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE;QAC9B,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;QAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;KAC9B,KAAK,aAAa,CAAC,UAAU,CAAC,CAAC;IAChC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,wCAAyC,SAAQ,uCAAuC;IACxG,QAAQ,CAAC,SAAS,EAAE,4BAA4B,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iCAAkC,SAAQ,gCAAgC;IAC1F,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;CAC5C;AA8JD;;;;GAIG;AACH,wBAAsB,sCAAsC,CAC3D,OAAO,EAAE,uCAAuC,GAC9C,OAAO,CAAC,gCAAgC,CAAC,CAmQ3C;AAED;;;;GAIG;AACH,wBAAsB,uCAAuC,CAC5D,OAAO,EAAE,wCAAwC,GAC/C,OAAO,CAAC,iCAAiC,CAAC,CAY5C","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport { mkdir, mkdtemp, open, rename, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\nimport type {\n\tPluginDistributionArtifactHandleV1,\n\tPluginDistributionArtifactV1,\n\tPluginDistributionDescriptorV1,\n\tPluginDistributionHostV1,\n\tPluginDistributionMetadataV1,\n\tPluginDistributionV1,\n} from \"./distribution.ts\";\nimport { createPluginDistributionV1 } from \"./distribution.ts\";\nimport { createNodePluginTrustRootV1, type NodePluginTrustRootOptionsV1 } from \"./node-plugin-trust-root.ts\";\n\nconst NODE_DISTRIBUTION_HOST_VERSION_V1 = 1 as const;\nconst DEFAULT_TIMEOUT_MS_V1 = 30_000;\nconst MAX_TIMEOUT_MS_V1 = 120_000;\nconst DEFAULT_REDIRECTS_V1 = 3;\nconst MAX_REDIRECTS_V1 = 5;\nconst REDIRECT_STATUS = new Set([301, 302, 303, 307, 308]);\n\nexport interface NodeHttpPluginDistributionHostOptionsV1 {\n\t/** Real `fetch` or a deterministic replacement for tests. */\n\treadonly fetch?: typeof globalThis.fetch;\n\t/** Exact `http(s)` origins. An empty allowlist is rejected. */\n\treadonly allowedOrigins: readonly string[];\n\t/** Optional host-owned directory. It is never returned as an artifact reference. */\n\treadonly artifactDirectory?: string;\n\treadonly requestTimeoutMs?: number;\n\treadonly maxRedirects?: number;\n\treadonly userAgent?: string;\n}\n\nexport interface NodeHttpPluginDistributionHostV1 {\n\treadonly version: typeof NODE_DISTRIBUTION_HOST_VERSION_V1;\n\treadonly host: PluginDistributionHostV1;\n\t/**\n\t * Private Node-host reader for an installer that shares this host instance.\n\t * It is not part of the model-facing distribution contract and never exposes\n\t * a file path. The caller must consume it before releasing the artifact.\n\t */\n\treadonly openArtifact: (input: {\n\t\treadonly artifact: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}) => AsyncIterable<Uint8Array>;\n\t/** Remove all artifacts owned by this host instance. */\n\treadonly close: () => Promise<void>;\n}\n\n/**\n * Explicitly composed Node distribution stack. The caller supplies the trust\n * root; no key or network origin is discovered implicitly.\n */\nexport interface NodeHttpPluginDistributionStackOptionsV1 extends NodeHttpPluginDistributionHostOptionsV1 {\n\treadonly trustRoot: NodePluginTrustRootOptionsV1;\n\t/** Shared clock for descriptor expiry and trust-key validity. */\n\treadonly now?: () => number;\n}\n\nexport interface NodeHttpPluginDistributionStackV1 extends NodeHttpPluginDistributionHostV1 {\n\treadonly distribution: PluginDistributionV1;\n}\n\ninterface ArtifactRecord {\n\treadonly path: string;\n\treadonly descriptor: PluginDistributionDescriptorV1;\n\treaders: number;\n}\n\ninterface RequestSignal {\n\treadonly signal: AbortSignal;\n\treadonly timedOut: () => boolean;\n\treadonly cleanup: () => void;\n}\n\nfunction cancelledRequestError(): Error {\n\tconst error = new Error(\"plugin request was cancelled\");\n\terror.name = \"AbortError\";\n\treturn error;\n}\n\nfunction throwIfRequestCancelled(request: RequestSignal): void {\n\tif (request.timedOut()) throw new Error(\"plugin request timed out\");\n\tif (request.signal.aborted) throw cancelledRequestError();\n}\n\nfunction boundedPositive(value: number | undefined, fallback: number, maximum: number, label: string): number {\n\tconst result = value ?? fallback;\n\tif (!Number.isSafeInteger(result) || result <= 0 || result > maximum)\n\t\tthrow new Error(`${label} must be a positive integer at most ${maximum}`);\n\treturn result;\n}\n\nfunction allowedOrigin(value: string): string {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new Error(\"allowed origin is invalid\");\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password)\n\t\tthrow new Error(\"allowed origin must be an http(s) origin\");\n\tif (parsed.pathname !== \"/\" || parsed.search !== \"\" || parsed.hash !== \"\")\n\t\tthrow new Error(\"allowed origin must not include a path or query\");\n\treturn parsed.origin;\n}\n\nfunction requestUrl(value: string, origins: ReadonlySet<string>): URL {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new Error(\"plugin source URL is invalid\");\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password)\n\t\tthrow new Error(\"plugin source URL must use http(s) without credentials\");\n\tif (!origins.has(parsed.origin)) throw new Error(\"plugin source origin is not allowed\");\n\treturn parsed;\n}\n\nfunction requestSignal(parent: AbortSignal | undefined, timeoutMs: number): RequestSignal {\n\tconst controller = new AbortController();\n\tlet didTimeout = false;\n\tconst abort = () => controller.abort(parent?.reason);\n\tif (parent?.aborted === true) abort();\n\telse parent?.addEventListener(\"abort\", abort, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\tdidTimeout = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\treturn {\n\t\tsignal: controller.signal,\n\t\ttimedOut: () => didTimeout,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tparent?.removeEventListener(\"abort\", abort);\n\t\t},\n\t};\n}\n\nfunction contentLength(response: Response): number | undefined {\n\tconst value = response.headers.get(\"content-length\");\n\tif (value === null) return undefined;\n\tif (!/^\\d+$/u.test(value)) throw new Error(\"plugin response content length is invalid\");\n\tconst result = Number(value);\n\tif (!Number.isSafeInteger(result)) throw new Error(\"plugin response content length is invalid\");\n\treturn result;\n}\n\nfunction contentType(response: Response): string | undefined {\n\tconst value = response.headers.get(\"content-type\");\n\tif (value === null) return undefined;\n\treturn value.split(\";\", 1)[0]?.trim().toLowerCase() || undefined;\n}\n\nfunction assertResponseMetadata(response: Response, descriptor: PluginDistributionDescriptorV1): void {\n\tconst length = contentLength(response);\n\tif (length !== descriptor.sizeBytes) throw new Error(\"plugin response size mismatch\");\n\tconst mediaType = contentType(response);\n\tif (mediaType !== descriptor.mediaType.toLowerCase()) throw new Error(\"plugin response media type mismatch\");\n}\n\nasync function cancelBody(response: Response): Promise<void> {\n\tif (response.body !== null) await response.body.cancel().catch(() => undefined);\n}\n\nfunction expectedDigest(value: string): { readonly algorithm: \"sha256\" | \"sha512\"; readonly hex: string } {\n\tconst prefixed = /^(sha256|sha512):([0-9a-f]+)$/iu.exec(value);\n\tif (prefixed !== null) {\n\t\tconst algorithm = prefixed[1]?.toLowerCase();\n\t\tconst hex = prefixed[2]?.toLowerCase();\n\t\tif ((algorithm === \"sha256\" && hex?.length === 64) || (algorithm === \"sha512\" && hex?.length === 128))\n\t\t\treturn { algorithm, hex };\n\t}\n\tif (/^[0-9a-f]{64}$/iu.test(value)) return { algorithm: \"sha256\", hex: value.toLowerCase() };\n\tif (/^[0-9a-f]{128}$/iu.test(value)) return { algorithm: \"sha512\", hex: value.toLowerCase() };\n\tthrow new Error(\"plugin artifact digest algorithm is unsupported\");\n}\n\nfunction metadataFromDescriptor(descriptor: PluginDistributionDescriptorV1): PluginDistributionMetadataV1 {\n\treturn {\n\t\tversion: 1,\n\t\tsource: descriptor.source,\n\t\tpluginId: descriptor.pluginId,\n\t\tpluginVersion: descriptor.pluginVersion,\n\t\tmanifestDigest: descriptor.manifestDigest,\n\t\tartifactDigest: descriptor.artifactDigest,\n\t\texpiresAt: descriptor.expiresAt,\n\t\tsizeBytes: descriptor.sizeBytes,\n\t\tmediaType: descriptor.mediaType,\n\t};\n}\n\nfunction artifactMatchesDescriptor(\n\tartifact: PluginDistributionArtifactV1,\n\tdescriptor: PluginDistributionDescriptorV1,\n): boolean {\n\treturn (\n\t\tartifact.version === 1 &&\n\t\tartifact.pluginId === descriptor.pluginId &&\n\t\tartifact.pluginVersion === descriptor.pluginVersion &&\n\t\tartifact.manifestDigest === descriptor.manifestDigest &&\n\t\tartifact.artifactDigest === descriptor.artifactDigest &&\n\t\tartifact.sizeBytes === descriptor.sizeBytes &&\n\t\tartifact.mediaType === descriptor.mediaType &&\n\t\tartifact.source === descriptor.source &&\n\t\tartifact.expiresAt === descriptor.expiresAt\n\t);\n}\n\nasync function writeFully(file: Awaited<ReturnType<typeof open>>, chunk: Uint8Array): Promise<void> {\n\tlet offset = 0;\n\twhile (offset < chunk.byteLength) {\n\t\tconst result = await file.write(chunk, offset, chunk.byteLength - offset, null);\n\t\tif (result.bytesWritten <= 0) throw new Error(\"plugin artifact file write failed\");\n\t\toffset += result.bytesWritten;\n\t}\n}\n\n/**\n * Node/undici distribution transport. It is a host adapter, not Core logic:\n * package bytes stay in a private artifact directory and are never returned by\n * the public distribution contract.\n */\nexport async function createNodeHttpPluginDistributionHostV1(\n\toptions: NodeHttpPluginDistributionHostOptionsV1,\n): Promise<NodeHttpPluginDistributionHostV1> {\n\tconst transport = options.fetch ?? globalThis.fetch;\n\tif (typeof transport !== \"function\") throw new Error(\"Node fetch is unavailable\");\n\tif (!Array.isArray(options.allowedOrigins) || options.allowedOrigins.length === 0)\n\t\tthrow new Error(\"at least one allowed origin is required\");\n\tconst origins = new Set(options.allowedOrigins.map(allowedOrigin));\n\tconst timeoutMs = boundedPositive(\n\t\toptions.requestTimeoutMs,\n\t\tDEFAULT_TIMEOUT_MS_V1,\n\t\tMAX_TIMEOUT_MS_V1,\n\t\t\"requestTimeoutMs\",\n\t);\n\tconst maxRedirects = options.maxRedirects ?? DEFAULT_REDIRECTS_V1;\n\tif (!Number.isSafeInteger(maxRedirects) || maxRedirects < 0 || maxRedirects > MAX_REDIRECTS_V1)\n\t\tthrow new Error(`maxRedirects must be an integer between 0 and ${MAX_REDIRECTS_V1}`);\n\tconst userAgent = options.userAgent ?? \"agent-forge-plugin-distribution/1\";\n\tif (userAgent.length === 0 || userAgent.length > 256 || /[\\r\\n]/u.test(userAgent))\n\t\tthrow new Error(\"userAgent is invalid\");\n\tconst configuredDirectory = options.artifactDirectory;\n\tif (configuredDirectory !== undefined && !isAbsolute(configuredDirectory))\n\t\tthrow new Error(\"artifactDirectory must be absolute\");\n\tconst baseDirectoryPromise: Promise<string> =\n\t\tconfiguredDirectory === undefined\n\t\t\t? mkdtemp(join(tmpdir(), \"agent-forge-plugin-distribution-\"))\n\t\t\t: (async () => {\n\t\t\t\t\tawait mkdir(configuredDirectory, { recursive: true });\n\t\t\t\t\treturn await mkdtemp(join(configuredDirectory, \"agent-forge-plugin-distribution-\"));\n\t\t\t\t})();\n\tconst artifacts = new Map<string, ArtifactRecord>();\n\tconst activeOperations = new Set<AbortController>();\n\tlet operationsDrained: (() => void) | undefined;\n\tlet closePromise: Promise<void> | undefined;\n\tlet closed = false;\n\n\tconst assertOpen = (): void => {\n\t\tif (closed) throw new Error(\"plugin distribution host is closed\");\n\t};\n\n\tconst beginOperation = (): AbortController => {\n\t\tassertOpen();\n\t\tconst controller = new AbortController();\n\t\tactiveOperations.add(controller);\n\t\treturn controller;\n\t};\n\n\tconst endOperation = (controller: AbortController): void => {\n\t\tactiveOperations.delete(controller);\n\t\tif (activeOperations.size === 0) {\n\t\t\toperationsDrained?.();\n\t\t\toperationsDrained = undefined;\n\t\t}\n\t};\n\n\tconst waitForOperations = async (): Promise<void> => {\n\t\tif (activeOperations.size === 0) return;\n\t\tawait new Promise<void>((resolve) => {\n\t\t\toperationsDrained = resolve;\n\t\t});\n\t};\n\n\tconst fetchResponse = async (\n\t\tvalue: string,\n\t\tmethod: \"HEAD\" | \"GET\",\n\t\tparentSignal: AbortSignal | undefined,\n\t\toperationSignal: AbortSignal,\n\t): Promise<{ readonly response: Response; readonly request: RequestSignal }> => {\n\t\tlet current = requestUrl(value, origins);\n\t\tfor (let redirect = 0; ; redirect += 1) {\n\t\t\tif (operationSignal.aborted) throw cancelledRequestError();\n\t\t\tassertOpen();\n\t\t\tconst request = requestSignal(\n\t\t\t\tAbortSignal.any([parentSignal, operationSignal].filter(Boolean) as AbortSignal[]),\n\t\t\t\ttimeoutMs,\n\t\t\t);\n\t\t\tlet response: Response;\n\t\t\ttry {\n\t\t\t\tresponse = await transport(current.toString(), {\n\t\t\t\t\tmethod,\n\t\t\t\t\theaders: { accept: \"*/*\", \"user-agent\": userAgent },\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\tsignal: request.signal,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\trequest.cleanup();\n\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (!REDIRECT_STATUS.has(response.status)) return { response, request };\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tawait cancelBody(response);\n\t\t\trequest.cleanup();\n\t\t\tif (location === null || redirect >= maxRedirects) throw new Error(\"plugin redirect limit exceeded\");\n\t\t\tcurrent = requestUrl(new URL(location, current).toString(), origins);\n\t\t}\n\t};\n\n\tconst resolveMetadata = async (input: {\n\t\treadonly descriptor: PluginDistributionDescriptorV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginDistributionMetadataV1> => {\n\t\tconst operation = beginOperation();\n\t\ttry {\n\t\t\tconst { response, request } = await fetchResponse(\n\t\t\t\tinput.descriptor.source,\n\t\t\t\t\"HEAD\",\n\t\t\t\tinput.signal,\n\t\t\t\toperation.signal,\n\t\t\t);\n\t\t\ttry {\n\t\t\t\tif (response.status < 200 || response.status >= 300) throw new Error(\"plugin metadata request failed\");\n\t\t\t\tassertResponseMetadata(response, input.descriptor);\n\t\t\t\treturn metadataFromDescriptor(input.descriptor);\n\t\t\t} finally {\n\t\t\t\tawait cancelBody(response);\n\t\t\t\trequest.cleanup();\n\t\t\t}\n\t\t} finally {\n\t\t\tendOperation(operation);\n\t\t}\n\t};\n\n\tconst acquireArtifact = async (input: {\n\t\treadonly descriptor: PluginDistributionDescriptorV1;\n\t\treadonly metadata: PluginDistributionMetadataV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginDistributionArtifactHandleV1> => {\n\t\tconst operation = beginOperation();\n\t\tlet temporaryPath: string | undefined;\n\t\tlet finalPath: string | undefined;\n\t\tlet published = false;\n\t\ttry {\n\t\t\tconst digest = expectedDigest(input.descriptor.artifactDigest);\n\t\t\tconst { response, request } = await fetchResponse(\n\t\t\t\tinput.descriptor.source,\n\t\t\t\t\"GET\",\n\t\t\t\tinput.signal,\n\t\t\t\toperation.signal,\n\t\t\t);\n\t\t\tlet file: Awaited<ReturnType<typeof open>> | undefined;\n\t\t\ttry {\n\t\t\t\tif (response.status < 200 || response.status >= 300) throw new Error(\"plugin artifact request failed\");\n\t\t\t\tassertResponseMetadata(response, input.descriptor);\n\t\t\t\tif (response.body === null) throw new Error(\"plugin artifact response has no body\");\n\t\t\t\tconst directory = await baseDirectoryPromise;\n\t\t\t\ttemporaryPath = join(directory, `.partial-${randomUUID()}`);\n\t\t\t\tfinalPath = join(directory, `artifact-${randomUUID()}`);\n\t\t\t\tfile = await open(temporaryPath, \"wx\");\n\t\t\t\tconst reader = response.body.getReader();\n\t\t\t\tconst hash = createHash(digest.algorithm);\n\t\t\t\tlet total = 0;\n\t\t\t\ttry {\n\t\t\t\t\tfor (;;) {\n\t\t\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\t\t\tconst item = await reader.read();\n\t\t\t\t\t\tif (item.done) break;\n\t\t\t\t\t\tconst chunk = item.value;\n\t\t\t\t\t\ttotal += chunk.byteLength;\n\t\t\t\t\t\tif (total > input.descriptor.sizeBytes) throw new Error(\"plugin artifact exceeds its size limit\");\n\t\t\t\t\t\thash.update(chunk);\n\t\t\t\t\t\tawait writeFully(file, chunk);\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\treader.releaseLock();\n\t\t\t\t}\n\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\tif (total !== input.descriptor.sizeBytes) throw new Error(\"plugin artifact size mismatch\");\n\t\t\t\tif (hash.digest(\"hex\") !== digest.hex) throw new Error(\"plugin artifact digest mismatch\");\n\t\t\t\tawait file.close();\n\t\t\t\tfile = undefined;\n\t\t\t\tawait rename(temporaryPath, finalPath);\n\t\t\t\tassertOpen();\n\t\t\t\tconst artifactRef = `artifact://node-http/${randomUUID()}`;\n\t\t\t\tartifacts.set(artifactRef, { path: finalPath, descriptor: input.descriptor, readers: 0 });\n\t\t\t\tpublished = true;\n\t\t\t\treturn {\n\t\t\t\t\tartifactRef,\n\t\t\t\t\tartifactDigest: input.descriptor.artifactDigest,\n\t\t\t\t\tsizeBytes: input.descriptor.sizeBytes,\n\t\t\t\t\tmediaType: input.descriptor.mediaType,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tif (file !== undefined) await file.close().catch(() => undefined);\n\t\t\t\tawait cancelBody(response);\n\t\t\t\trequest.cleanup();\n\t\t\t}\n\t\t} finally {\n\t\t\tif (temporaryPath !== undefined) await rm(temporaryPath, { force: true }).catch(() => undefined);\n\t\t\tif (!published && finalPath !== undefined) await rm(finalPath, { force: true }).catch(() => undefined);\n\t\t\tendOperation(operation);\n\t\t}\n\t};\n\n\tconst releaseArtifact = async (input: {\n\t\treadonly artifact: { readonly artifactRef: string };\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void> => {\n\t\tassertOpen();\n\t\tif (input.signal?.aborted) throw new Error(\"plugin artifact release was cancelled\");\n\t\tconst record = artifacts.get(input.artifact.artifactRef);\n\t\tif (record === undefined) throw new Error(\"plugin artifact reference is unknown\");\n\t\tif (record.readers > 0) throw new Error(\"plugin artifact is still being read\");\n\t\tawait rm(record.path, { force: false });\n\t\tartifacts.delete(input.artifact.artifactRef);\n\t};\n\n\tconst openArtifact = (input: {\n\t\treadonly artifact: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}): AsyncIterable<Uint8Array> =>\n\t\t(async function* (): AsyncGenerator<Uint8Array> {\n\t\t\tconst operation = beginOperation();\n\t\t\tlet stream: ReturnType<typeof createReadStream> | undefined;\n\t\t\tlet acquiredRecord: ArtifactRecord | undefined;\n\t\t\tconst abort = () => stream?.destroy(new Error(\"plugin artifact read was cancelled\"));\n\t\t\ttry {\n\t\t\t\tif (input.signal?.aborted) throw new Error(\"plugin artifact read was cancelled\");\n\t\t\t\tconst record = artifacts.get(input.artifact.artifactRef);\n\t\t\t\tif (record === undefined || !artifactMatchesDescriptor(input.artifact, record.descriptor))\n\t\t\t\t\tthrow new Error(\"plugin artifact reference is unknown\");\n\t\t\t\trecord.readers += 1;\n\t\t\t\tacquiredRecord = record;\n\t\t\t\tstream = createReadStream(record.path, { highWaterMark: 64 * 1024 });\n\t\t\t\tinput.signal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\t\toperation.signal.addEventListener(\"abort\", abort, { once: true });\n\t\t\t\tfor await (const chunk of stream) {\n\t\t\t\t\tif (input.signal?.aborted || operation.signal.aborted)\n\t\t\t\t\t\tthrow new Error(\"plugin artifact read was cancelled\");\n\t\t\t\t\tyield new Uint8Array(chunk);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tinput.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\toperation.signal.removeEventListener(\"abort\", abort);\n\t\t\t\tstream?.destroy();\n\t\t\t\tif (acquiredRecord !== undefined && acquiredRecord.readers > 0) acquiredRecord.readers -= 1;\n\t\t\t\tendOperation(operation);\n\t\t\t}\n\t\t})();\n\n\treturn {\n\t\tversion: NODE_DISTRIBUTION_HOST_VERSION_V1,\n\t\thost: { resolveMetadata, acquireArtifact, releaseArtifact },\n\t\topenArtifact,\n\t\tclose: async () => {\n\t\t\tif (closePromise !== undefined) return await closePromise;\n\t\t\tclosed = true;\n\t\t\tfor (const operation of activeOperations) operation.abort();\n\t\t\tclosePromise = (async () => {\n\t\t\t\tawait waitForOperations();\n\t\t\t\tconst directory = await baseDirectoryPromise;\n\t\t\t\tawait Promise.all([...artifacts.values()].map((record) => rm(record.path, { force: true })));\n\t\t\t\tartifacts.clear();\n\t\t\t\tawait rm(directory, { recursive: true, force: true });\n\t\t\t})();\n\t\t\treturn await closePromise;\n\t\t},\n\t};\n}\n\n/**\n * Compose the real Node HTTP transport with the explicit Ed25519 trust root.\n * Distribution descriptors are verified before metadata or artifact access;\n * the returned host still keeps bytes behind its private reader.\n */\nexport async function createNodeHttpPluginDistributionStackV1(\n\toptions: NodeHttpPluginDistributionStackOptionsV1,\n): Promise<NodeHttpPluginDistributionStackV1> {\n\tconst { trustRoot, now: configuredNow, ...hostOptions } = options;\n\tconst host = await createNodeHttpPluginDistributionHostV1(hostOptions);\n\ttry {\n\t\tconst now = configuredNow ?? trustRoot.now ?? (() => Date.now());\n\t\tconst verifySignature = createNodePluginTrustRootV1({ ...trustRoot, now });\n\t\tconst distribution = createPluginDistributionV1({ host: host.host, verifySignature, now });\n\t\treturn Object.freeze({ ...host, distribution });\n\t} catch (error) {\n\t\tawait host.close().catch(() => undefined);\n\t\tthrow error;\n\t}\n}\n"]}
1
+ {"version":3,"file":"node-distribution-host.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-distribution-host.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEX,4BAA4B,EAE5B,wBAAwB,EAExB,oBAAoB,EACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAA+B,KAAK,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAE7G,QAAA,MAAM,iCAAiC,GAAa,CAAC;AAOrD,MAAM,WAAW,uCAAuC;IACvD,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,oFAAoF;IACpF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gCAAgC;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,iCAAiC,CAAC;IAC3D,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE;QAC9B,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;QAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;KAC9B,KAAK,aAAa,CAAC,UAAU,CAAC,CAAC;IAChC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,wCAAyC,SAAQ,uCAAuC;IACxG,QAAQ,CAAC,SAAS,EAAE,4BAA4B,CAAC;IACjD,iEAAiE;IACjE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iCAAkC,SAAQ,gCAAgC;IAC1F,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;CAC5C;AA8JD;;;;GAIG;AACH,wBAAsB,sCAAsC,CAC3D,OAAO,EAAE,uCAAuC,GAC9C,OAAO,CAAC,gCAAgC,CAAC,CAmQ3C;AAED;;;;GAIG;AACH,wBAAsB,uCAAuC,CAC5D,OAAO,EAAE,wCAAwC,GAC/C,OAAO,CAAC,iCAAiC,CAAC,CAY5C","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\nimport { mkdir, mkdtemp, open, rename, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport { t } from \"../../core/i18n/index.ts\";\nimport type {\n\tPluginDistributionArtifactHandleV1,\n\tPluginDistributionArtifactV1,\n\tPluginDistributionDescriptorV1,\n\tPluginDistributionHostV1,\n\tPluginDistributionMetadataV1,\n\tPluginDistributionV1,\n} from \"./distribution.ts\";\nimport { createPluginDistributionV1 } from \"./distribution.ts\";\nimport { createNodePluginTrustRootV1, type NodePluginTrustRootOptionsV1 } from \"./node-plugin-trust-root.ts\";\n\nconst NODE_DISTRIBUTION_HOST_VERSION_V1 = 1 as const;\nconst DEFAULT_TIMEOUT_MS_V1 = 30_000;\nconst MAX_TIMEOUT_MS_V1 = 120_000;\nconst DEFAULT_REDIRECTS_V1 = 3;\nconst MAX_REDIRECTS_V1 = 5;\nconst REDIRECT_STATUS = new Set([301, 302, 303, 307, 308]);\n\nexport interface NodeHttpPluginDistributionHostOptionsV1 {\n\t/** Real `fetch` or a deterministic replacement for tests. */\n\treadonly fetch?: typeof globalThis.fetch;\n\t/** Exact `http(s)` origins. An empty allowlist is rejected. */\n\treadonly allowedOrigins: readonly string[];\n\t/** Optional host-owned directory. It is never returned as an artifact reference. */\n\treadonly artifactDirectory?: string;\n\treadonly requestTimeoutMs?: number;\n\treadonly maxRedirects?: number;\n\treadonly userAgent?: string;\n}\n\nexport interface NodeHttpPluginDistributionHostV1 {\n\treadonly version: typeof NODE_DISTRIBUTION_HOST_VERSION_V1;\n\treadonly host: PluginDistributionHostV1;\n\t/**\n\t * Private Node-host reader for an installer that shares this host instance.\n\t * It is not part of the model-facing distribution contract and never exposes\n\t * a file path. The caller must consume it before releasing the artifact.\n\t */\n\treadonly openArtifact: (input: {\n\t\treadonly artifact: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}) => AsyncIterable<Uint8Array>;\n\t/** Remove all artifacts owned by this host instance. */\n\treadonly close: () => Promise<void>;\n}\n\n/**\n * Explicitly composed Node distribution stack. The caller supplies the trust\n * root; no key or network origin is discovered implicitly.\n */\nexport interface NodeHttpPluginDistributionStackOptionsV1 extends NodeHttpPluginDistributionHostOptionsV1 {\n\treadonly trustRoot: NodePluginTrustRootOptionsV1;\n\t/** Shared clock for descriptor expiry and trust-key validity. */\n\treadonly now?: () => number;\n}\n\nexport interface NodeHttpPluginDistributionStackV1 extends NodeHttpPluginDistributionHostV1 {\n\treadonly distribution: PluginDistributionV1;\n}\n\ninterface ArtifactRecord {\n\treadonly path: string;\n\treadonly descriptor: PluginDistributionDescriptorV1;\n\treaders: number;\n}\n\ninterface RequestSignal {\n\treadonly signal: AbortSignal;\n\treadonly timedOut: () => boolean;\n\treadonly cleanup: () => void;\n}\n\nfunction cancelledRequestError(): Error {\n\tconst error = new Error(t(\"plugin request was cancelled\"));\n\terror.name = \"AbortError\";\n\treturn error;\n}\n\nfunction throwIfRequestCancelled(request: RequestSignal): void {\n\tif (request.timedOut()) throw new Error(t(\"plugin request timed out\"));\n\tif (request.signal.aborted) throw cancelledRequestError();\n}\n\nfunction boundedPositive(value: number | undefined, fallback: number, maximum: number, label: string): number {\n\tconst result = value ?? fallback;\n\tif (!Number.isSafeInteger(result) || result <= 0 || result > maximum)\n\t\tthrow new Error(t(\"{label} must be a positive integer at most {maximum}\", { label, maximum }));\n\treturn result;\n}\n\nfunction allowedOrigin(value: string): string {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new Error(t(\"allowed origin is invalid\"));\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password)\n\t\tthrow new Error(t(\"allowed origin must be an http(s) origin\"));\n\tif (parsed.pathname !== \"/\" || parsed.search !== \"\" || parsed.hash !== \"\")\n\t\tthrow new Error(t(\"allowed origin must not include a path or query\"));\n\treturn parsed.origin;\n}\n\nfunction requestUrl(value: string, origins: ReadonlySet<string>): URL {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new Error(t(\"plugin source URL is invalid\"));\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password)\n\t\tthrow new Error(t(\"plugin source URL must use http(s) without credentials\"));\n\tif (!origins.has(parsed.origin)) throw new Error(t(\"plugin source origin is not allowed\"));\n\treturn parsed;\n}\n\nfunction requestSignal(parent: AbortSignal | undefined, timeoutMs: number): RequestSignal {\n\tconst controller = new AbortController();\n\tlet didTimeout = false;\n\tconst abort = () => controller.abort(parent?.reason);\n\tif (parent?.aborted === true) abort();\n\telse parent?.addEventListener(\"abort\", abort, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\tdidTimeout = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\treturn {\n\t\tsignal: controller.signal,\n\t\ttimedOut: () => didTimeout,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tparent?.removeEventListener(\"abort\", abort);\n\t\t},\n\t};\n}\n\nfunction contentLength(response: Response): number | undefined {\n\tconst value = response.headers.get(\"content-length\");\n\tif (value === null) return undefined;\n\tif (!/^\\d+$/u.test(value)) throw new Error(t(\"plugin response content length is invalid\"));\n\tconst result = Number(value);\n\tif (!Number.isSafeInteger(result)) throw new Error(t(\"plugin response content length is invalid\"));\n\treturn result;\n}\n\nfunction contentType(response: Response): string | undefined {\n\tconst value = response.headers.get(\"content-type\");\n\tif (value === null) return undefined;\n\treturn value.split(\";\", 1)[0]?.trim().toLowerCase() || undefined;\n}\n\nfunction assertResponseMetadata(response: Response, descriptor: PluginDistributionDescriptorV1): void {\n\tconst length = contentLength(response);\n\tif (length !== descriptor.sizeBytes) throw new Error(t(\"plugin response size mismatch\"));\n\tconst mediaType = contentType(response);\n\tif (mediaType !== descriptor.mediaType.toLowerCase()) throw new Error(t(\"plugin response media type mismatch\"));\n}\n\nasync function cancelBody(response: Response): Promise<void> {\n\tif (response.body !== null) await response.body.cancel().catch(() => undefined);\n}\n\nfunction expectedDigest(value: string): { readonly algorithm: \"sha256\" | \"sha512\"; readonly hex: string } {\n\tconst prefixed = /^(sha256|sha512):([0-9a-f]+)$/iu.exec(value);\n\tif (prefixed !== null) {\n\t\tconst algorithm = prefixed[1]?.toLowerCase();\n\t\tconst hex = prefixed[2]?.toLowerCase();\n\t\tif ((algorithm === \"sha256\" && hex?.length === 64) || (algorithm === \"sha512\" && hex?.length === 128))\n\t\t\treturn { algorithm, hex };\n\t}\n\tif (/^[0-9a-f]{64}$/iu.test(value)) return { algorithm: \"sha256\", hex: value.toLowerCase() };\n\tif (/^[0-9a-f]{128}$/iu.test(value)) return { algorithm: \"sha512\", hex: value.toLowerCase() };\n\tthrow new Error(t(\"plugin artifact digest algorithm is unsupported\"));\n}\n\nfunction metadataFromDescriptor(descriptor: PluginDistributionDescriptorV1): PluginDistributionMetadataV1 {\n\treturn {\n\t\tversion: 1,\n\t\tsource: descriptor.source,\n\t\tpluginId: descriptor.pluginId,\n\t\tpluginVersion: descriptor.pluginVersion,\n\t\tmanifestDigest: descriptor.manifestDigest,\n\t\tartifactDigest: descriptor.artifactDigest,\n\t\texpiresAt: descriptor.expiresAt,\n\t\tsizeBytes: descriptor.sizeBytes,\n\t\tmediaType: descriptor.mediaType,\n\t};\n}\n\nfunction artifactMatchesDescriptor(\n\tartifact: PluginDistributionArtifactV1,\n\tdescriptor: PluginDistributionDescriptorV1,\n): boolean {\n\treturn (\n\t\tartifact.version === 1 &&\n\t\tartifact.pluginId === descriptor.pluginId &&\n\t\tartifact.pluginVersion === descriptor.pluginVersion &&\n\t\tartifact.manifestDigest === descriptor.manifestDigest &&\n\t\tartifact.artifactDigest === descriptor.artifactDigest &&\n\t\tartifact.sizeBytes === descriptor.sizeBytes &&\n\t\tartifact.mediaType === descriptor.mediaType &&\n\t\tartifact.source === descriptor.source &&\n\t\tartifact.expiresAt === descriptor.expiresAt\n\t);\n}\n\nasync function writeFully(file: Awaited<ReturnType<typeof open>>, chunk: Uint8Array): Promise<void> {\n\tlet offset = 0;\n\twhile (offset < chunk.byteLength) {\n\t\tconst result = await file.write(chunk, offset, chunk.byteLength - offset, null);\n\t\tif (result.bytesWritten <= 0) throw new Error(t(\"plugin artifact file write failed\"));\n\t\toffset += result.bytesWritten;\n\t}\n}\n\n/**\n * Node/undici distribution transport. It is a host adapter, not Core logic:\n * package bytes stay in a private artifact directory and are never returned by\n * the public distribution contract.\n */\nexport async function createNodeHttpPluginDistributionHostV1(\n\toptions: NodeHttpPluginDistributionHostOptionsV1,\n): Promise<NodeHttpPluginDistributionHostV1> {\n\tconst transport = options.fetch ?? globalThis.fetch;\n\tif (typeof transport !== \"function\") throw new Error(t(\"Node fetch is unavailable\"));\n\tif (!Array.isArray(options.allowedOrigins) || options.allowedOrigins.length === 0)\n\t\tthrow new Error(t(\"at least one allowed origin is required\"));\n\tconst origins = new Set(options.allowedOrigins.map(allowedOrigin));\n\tconst timeoutMs = boundedPositive(\n\t\toptions.requestTimeoutMs,\n\t\tDEFAULT_TIMEOUT_MS_V1,\n\t\tMAX_TIMEOUT_MS_V1,\n\t\t\"requestTimeoutMs\",\n\t);\n\tconst maxRedirects = options.maxRedirects ?? DEFAULT_REDIRECTS_V1;\n\tif (!Number.isSafeInteger(maxRedirects) || maxRedirects < 0 || maxRedirects > MAX_REDIRECTS_V1)\n\t\tthrow new Error(t(\"maxRedirects must be an integer between 0 and {max}\", { max: MAX_REDIRECTS_V1 }));\n\tconst userAgent = options.userAgent ?? \"agent-forge-plugin-distribution/1\";\n\tif (userAgent.length === 0 || userAgent.length > 256 || /[\\r\\n]/u.test(userAgent))\n\t\tthrow new Error(t(\"userAgent is invalid\"));\n\tconst configuredDirectory = options.artifactDirectory;\n\tif (configuredDirectory !== undefined && !isAbsolute(configuredDirectory))\n\t\tthrow new Error(t(\"artifactDirectory must be absolute\"));\n\tconst baseDirectoryPromise: Promise<string> =\n\t\tconfiguredDirectory === undefined\n\t\t\t? mkdtemp(join(tmpdir(), \"agent-forge-plugin-distribution-\"))\n\t\t\t: (async () => {\n\t\t\t\t\tawait mkdir(configuredDirectory, { recursive: true });\n\t\t\t\t\treturn await mkdtemp(join(configuredDirectory, \"agent-forge-plugin-distribution-\"));\n\t\t\t\t})();\n\tconst artifacts = new Map<string, ArtifactRecord>();\n\tconst activeOperations = new Set<AbortController>();\n\tlet operationsDrained: (() => void) | undefined;\n\tlet closePromise: Promise<void> | undefined;\n\tlet closed = false;\n\n\tconst assertOpen = (): void => {\n\t\tif (closed) throw new Error(t(\"plugin distribution host is closed\"));\n\t};\n\n\tconst beginOperation = (): AbortController => {\n\t\tassertOpen();\n\t\tconst controller = new AbortController();\n\t\tactiveOperations.add(controller);\n\t\treturn controller;\n\t};\n\n\tconst endOperation = (controller: AbortController): void => {\n\t\tactiveOperations.delete(controller);\n\t\tif (activeOperations.size === 0) {\n\t\t\toperationsDrained?.();\n\t\t\toperationsDrained = undefined;\n\t\t}\n\t};\n\n\tconst waitForOperations = async (): Promise<void> => {\n\t\tif (activeOperations.size === 0) return;\n\t\tawait new Promise<void>((resolve) => {\n\t\t\toperationsDrained = resolve;\n\t\t});\n\t};\n\n\tconst fetchResponse = async (\n\t\tvalue: string,\n\t\tmethod: \"HEAD\" | \"GET\",\n\t\tparentSignal: AbortSignal | undefined,\n\t\toperationSignal: AbortSignal,\n\t): Promise<{ readonly response: Response; readonly request: RequestSignal }> => {\n\t\tlet current = requestUrl(value, origins);\n\t\tfor (let redirect = 0; ; redirect += 1) {\n\t\t\tif (operationSignal.aborted) throw cancelledRequestError();\n\t\t\tassertOpen();\n\t\t\tconst request = requestSignal(\n\t\t\t\tAbortSignal.any([parentSignal, operationSignal].filter(Boolean) as AbortSignal[]),\n\t\t\t\ttimeoutMs,\n\t\t\t);\n\t\t\tlet response: Response;\n\t\t\ttry {\n\t\t\t\tresponse = await transport(current.toString(), {\n\t\t\t\t\tmethod,\n\t\t\t\t\theaders: { accept: \"*/*\", \"user-agent\": userAgent },\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\tsignal: request.signal,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\trequest.cleanup();\n\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (!REDIRECT_STATUS.has(response.status)) return { response, request };\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tawait cancelBody(response);\n\t\t\trequest.cleanup();\n\t\t\tif (location === null || redirect >= maxRedirects) throw new Error(t(\"plugin redirect limit exceeded\"));\n\t\t\tcurrent = requestUrl(new URL(location, current).toString(), origins);\n\t\t}\n\t};\n\n\tconst resolveMetadata = async (input: {\n\t\treadonly descriptor: PluginDistributionDescriptorV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginDistributionMetadataV1> => {\n\t\tconst operation = beginOperation();\n\t\ttry {\n\t\t\tconst { response, request } = await fetchResponse(\n\t\t\t\tinput.descriptor.source,\n\t\t\t\t\"HEAD\",\n\t\t\t\tinput.signal,\n\t\t\t\toperation.signal,\n\t\t\t);\n\t\t\ttry {\n\t\t\t\tif (response.status < 200 || response.status >= 300) throw new Error(t(\"plugin metadata request failed\"));\n\t\t\t\tassertResponseMetadata(response, input.descriptor);\n\t\t\t\treturn metadataFromDescriptor(input.descriptor);\n\t\t\t} finally {\n\t\t\t\tawait cancelBody(response);\n\t\t\t\trequest.cleanup();\n\t\t\t}\n\t\t} finally {\n\t\t\tendOperation(operation);\n\t\t}\n\t};\n\n\tconst acquireArtifact = async (input: {\n\t\treadonly descriptor: PluginDistributionDescriptorV1;\n\t\treadonly metadata: PluginDistributionMetadataV1;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<PluginDistributionArtifactHandleV1> => {\n\t\tconst operation = beginOperation();\n\t\tlet temporaryPath: string | undefined;\n\t\tlet finalPath: string | undefined;\n\t\tlet published = false;\n\t\ttry {\n\t\t\tconst digest = expectedDigest(input.descriptor.artifactDigest);\n\t\t\tconst { response, request } = await fetchResponse(\n\t\t\t\tinput.descriptor.source,\n\t\t\t\t\"GET\",\n\t\t\t\tinput.signal,\n\t\t\t\toperation.signal,\n\t\t\t);\n\t\t\tlet file: Awaited<ReturnType<typeof open>> | undefined;\n\t\t\ttry {\n\t\t\t\tif (response.status < 200 || response.status >= 300) throw new Error(t(\"plugin artifact request failed\"));\n\t\t\t\tassertResponseMetadata(response, input.descriptor);\n\t\t\t\tif (response.body === null) throw new Error(t(\"plugin artifact response has no body\"));\n\t\t\t\tconst directory = await baseDirectoryPromise;\n\t\t\t\ttemporaryPath = join(directory, `.partial-${randomUUID()}`);\n\t\t\t\tfinalPath = join(directory, `artifact-${randomUUID()}`);\n\t\t\t\tfile = await open(temporaryPath, \"wx\");\n\t\t\t\tconst reader = response.body.getReader();\n\t\t\t\tconst hash = createHash(digest.algorithm);\n\t\t\t\tlet total = 0;\n\t\t\t\ttry {\n\t\t\t\t\tfor (;;) {\n\t\t\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\t\t\tconst item = await reader.read();\n\t\t\t\t\t\tif (item.done) break;\n\t\t\t\t\t\tconst chunk = item.value;\n\t\t\t\t\t\ttotal += chunk.byteLength;\n\t\t\t\t\t\tif (total > input.descriptor.sizeBytes) throw new Error(t(\"plugin artifact exceeds its size limit\"));\n\t\t\t\t\t\thash.update(chunk);\n\t\t\t\t\t\tawait writeFully(file, chunk);\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\treader.releaseLock();\n\t\t\t\t}\n\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\tif (total !== input.descriptor.sizeBytes) throw new Error(t(\"plugin artifact size mismatch\"));\n\t\t\t\tif (hash.digest(\"hex\") !== digest.hex) throw new Error(t(\"plugin artifact digest mismatch\"));\n\t\t\t\tawait file.close();\n\t\t\t\tfile = undefined;\n\t\t\t\tawait rename(temporaryPath, finalPath);\n\t\t\t\tassertOpen();\n\t\t\t\tconst artifactRef = `artifact://node-http/${randomUUID()}`;\n\t\t\t\tartifacts.set(artifactRef, { path: finalPath, descriptor: input.descriptor, readers: 0 });\n\t\t\t\tpublished = true;\n\t\t\t\treturn {\n\t\t\t\t\tartifactRef,\n\t\t\t\t\tartifactDigest: input.descriptor.artifactDigest,\n\t\t\t\t\tsizeBytes: input.descriptor.sizeBytes,\n\t\t\t\t\tmediaType: input.descriptor.mediaType,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tthrowIfRequestCancelled(request);\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tif (file !== undefined) await file.close().catch(() => undefined);\n\t\t\t\tawait cancelBody(response);\n\t\t\t\trequest.cleanup();\n\t\t\t}\n\t\t} finally {\n\t\t\tif (temporaryPath !== undefined) await rm(temporaryPath, { force: true }).catch(() => undefined);\n\t\t\tif (!published && finalPath !== undefined) await rm(finalPath, { force: true }).catch(() => undefined);\n\t\t\tendOperation(operation);\n\t\t}\n\t};\n\n\tconst releaseArtifact = async (input: {\n\t\treadonly artifact: { readonly artifactRef: string };\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<void> => {\n\t\tassertOpen();\n\t\tif (input.signal?.aborted) throw new Error(t(\"plugin artifact release was cancelled\"));\n\t\tconst record = artifacts.get(input.artifact.artifactRef);\n\t\tif (record === undefined) throw new Error(t(\"plugin artifact reference is unknown\"));\n\t\tif (record.readers > 0) throw new Error(t(\"plugin artifact is still being read\"));\n\t\tawait rm(record.path, { force: false });\n\t\tartifacts.delete(input.artifact.artifactRef);\n\t};\n\n\tconst openArtifact = (input: {\n\t\treadonly artifact: PluginDistributionArtifactV1;\n\t\treadonly signal?: AbortSignal;\n\t}): AsyncIterable<Uint8Array> =>\n\t\t(async function* (): AsyncGenerator<Uint8Array> {\n\t\t\tconst operation = beginOperation();\n\t\t\tlet stream: ReturnType<typeof createReadStream> | undefined;\n\t\t\tlet acquiredRecord: ArtifactRecord | undefined;\n\t\t\tconst abort = () => stream?.destroy(new Error(\"plugin artifact read was cancelled\"));\n\t\t\ttry {\n\t\t\t\tif (input.signal?.aborted) throw new Error(t(\"plugin artifact read was cancelled\"));\n\t\t\t\tconst record = artifacts.get(input.artifact.artifactRef);\n\t\t\t\tif (record === undefined || !artifactMatchesDescriptor(input.artifact, record.descriptor))\n\t\t\t\t\tthrow new Error(t(\"plugin artifact reference is unknown\"));\n\t\t\t\trecord.readers += 1;\n\t\t\t\tacquiredRecord = record;\n\t\t\t\tstream = createReadStream(record.path, { highWaterMark: 64 * 1024 });\n\t\t\t\tinput.signal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\t\toperation.signal.addEventListener(\"abort\", abort, { once: true });\n\t\t\t\tfor await (const chunk of stream) {\n\t\t\t\t\tif (input.signal?.aborted || operation.signal.aborted)\n\t\t\t\t\t\tthrow new Error(t(\"plugin artifact read was cancelled\"));\n\t\t\t\t\tyield new Uint8Array(chunk);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tinput.signal?.removeEventListener(\"abort\", abort);\n\t\t\t\toperation.signal.removeEventListener(\"abort\", abort);\n\t\t\t\tstream?.destroy();\n\t\t\t\tif (acquiredRecord !== undefined && acquiredRecord.readers > 0) acquiredRecord.readers -= 1;\n\t\t\t\tendOperation(operation);\n\t\t\t}\n\t\t})();\n\n\treturn {\n\t\tversion: NODE_DISTRIBUTION_HOST_VERSION_V1,\n\t\thost: { resolveMetadata, acquireArtifact, releaseArtifact },\n\t\topenArtifact,\n\t\tclose: async () => {\n\t\t\tif (closePromise !== undefined) return await closePromise;\n\t\t\tclosed = true;\n\t\t\tfor (const operation of activeOperations) operation.abort();\n\t\t\tclosePromise = (async () => {\n\t\t\t\tawait waitForOperations();\n\t\t\t\tconst directory = await baseDirectoryPromise;\n\t\t\t\tawait Promise.all([...artifacts.values()].map((record) => rm(record.path, { force: true })));\n\t\t\t\tartifacts.clear();\n\t\t\t\tawait rm(directory, { recursive: true, force: true });\n\t\t\t})();\n\t\t\treturn await closePromise;\n\t\t},\n\t};\n}\n\n/**\n * Compose the real Node HTTP transport with the explicit Ed25519 trust root.\n * Distribution descriptors are verified before metadata or artifact access;\n * the returned host still keeps bytes behind its private reader.\n */\nexport async function createNodeHttpPluginDistributionStackV1(\n\toptions: NodeHttpPluginDistributionStackOptionsV1,\n): Promise<NodeHttpPluginDistributionStackV1> {\n\tconst { trustRoot, now: configuredNow, ...hostOptions } = options;\n\tconst host = await createNodeHttpPluginDistributionHostV1(hostOptions);\n\ttry {\n\t\tconst now = configuredNow ?? trustRoot.now ?? (() => Date.now());\n\t\tconst verifySignature = createNodePluginTrustRootV1({ ...trustRoot, now });\n\t\tconst distribution = createPluginDistributionV1({ host: host.host, verifySignature, now });\n\t\treturn Object.freeze({ ...host, distribution });\n\t} catch (error) {\n\t\tawait host.close().catch(() => undefined);\n\t\tthrow error;\n\t}\n}\n"]}