@abot-ai/runtime 1.6.0 → 1.7.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 (380) hide show
  1. package/README.md +2 -0
  2. package/dist/src/bridge/request-steering.js +60 -15
  3. package/dist/src/capabilities/normal-invocation/contracts.d.ts +3 -0
  4. package/dist/src/capabilities/normal-invocation/output-channels.d.ts +10 -0
  5. package/dist/src/capabilities/normal-invocation/output-channels.js +29 -0
  6. package/dist/src/capabilities/normal-invocation/validator.js +4 -2
  7. package/dist/src/capabilities/tool-types.d.ts +1 -1
  8. package/dist/src/cli/host-companion-bundle.mjs +7570 -6781
  9. package/dist/src/cli/host-companion-entry.js +5 -22
  10. package/dist/src/cli/host-companion-input.d.ts +3 -0
  11. package/dist/src/cli/host-companion-input.js +21 -0
  12. package/dist/src/cli/host-companion-lifecycle.d.ts +11 -0
  13. package/dist/src/cli/host-companion-lifecycle.js +32 -0
  14. package/dist/src/cli/host-companion-setup-target.d.ts +4 -0
  15. package/dist/src/cli/host-companion-setup-target.js +17 -0
  16. package/dist/src/cli/host-companion-startup.d.ts +2 -0
  17. package/dist/src/cli/host-companion-startup.js +7 -2
  18. package/dist/src/cli/host-companion.d.ts +6 -0
  19. package/dist/src/cli/host-companion.js +30 -27
  20. package/dist/src/cli/windows-companion-store-entry.d.ts +9 -0
  21. package/dist/src/cli/windows-companion-store-entry.js +67 -0
  22. package/dist/src/computer-access/command-output-capture.d.ts +37 -0
  23. package/dist/src/computer-access/command-output-capture.js +136 -0
  24. package/dist/src/computer-access/command-output-retention.d.ts +5 -0
  25. package/dist/src/computer-access/command-output-retention.js +90 -0
  26. package/dist/src/computer-access/command-output.d.ts +7 -0
  27. package/dist/src/computer-access/command-output.js +1 -0
  28. package/dist/src/computer-access/commands.d.ts +1 -0
  29. package/dist/src/computer-access/commands.js +1 -1
  30. package/dist/src/computer-access/companion/command-output-protocol.d.ts +12 -0
  31. package/dist/src/computer-access/companion/command-output-protocol.js +28 -0
  32. package/dist/src/computer-access/companion/command-output.d.ts +13 -0
  33. package/dist/src/computer-access/companion/command-output.js +110 -0
  34. package/dist/src/computer-access/companion/install-link-macos.d.ts +7 -0
  35. package/dist/src/computer-access/companion/install-link-macos.js +48 -0
  36. package/dist/src/computer-access/companion/install-link-registration.d.ts +4 -0
  37. package/dist/src/computer-access/companion/install-link-registration.js +184 -0
  38. package/dist/src/computer-access/companion/install-link-windows.d.ts +4 -0
  39. package/dist/src/computer-access/companion/install-link-windows.js +65 -0
  40. package/dist/src/computer-access/companion/install-link.d.ts +9 -0
  41. package/dist/src/computer-access/companion/install-link.js +54 -0
  42. package/dist/src/computer-access/companion/native-messages.js +3 -0
  43. package/dist/src/computer-access/companion/native-session.d.ts +1 -0
  44. package/dist/src/computer-access/companion/native-session.js +14 -2
  45. package/dist/src/computer-access/companion/native-supervisor.js +1 -0
  46. package/dist/src/computer-access/companion/notification-windows.d.ts +1 -1
  47. package/dist/src/computer-access/companion/notification-windows.js +8 -3
  48. package/dist/src/computer-access/companion/protocol.d.ts +1 -1
  49. package/dist/src/computer-access/companion/protocol.js +6 -0
  50. package/dist/src/computer-access/companion/release-version.d.ts +1 -1
  51. package/dist/src/computer-access/companion/release-version.js +1 -1
  52. package/dist/src/computer-access/companion/windows-store/connection-error.d.ts +7 -0
  53. package/dist/src/computer-access/companion/windows-store/connection-error.js +19 -0
  54. package/dist/src/computer-access/companion/windows-store/connection-link.d.ts +13 -0
  55. package/dist/src/computer-access/companion/windows-store/connection-link.js +109 -0
  56. package/dist/src/computer-access/companion/windows-store/identity.d.ts +13 -0
  57. package/dist/src/computer-access/companion/windows-store/identity.js +13 -0
  58. package/dist/src/computer-access/companion/windows-store/lifecycle.d.ts +5 -0
  59. package/dist/src/computer-access/companion/windows-store/lifecycle.js +90 -0
  60. package/dist/src/computer-access/contracts.d.ts +1 -1
  61. package/dist/src/computer-access/handlers.d.ts +2 -1
  62. package/dist/src/computer-access/handlers.js +5 -1
  63. package/dist/src/computer-access/process-capture.d.ts +6 -0
  64. package/dist/src/computer-access/process-capture.js +1 -0
  65. package/dist/src/computer-access/process-result.d.ts +2 -0
  66. package/dist/src/computer-access/process-result.js +14 -6
  67. package/dist/src/computer-access/process-runner.d.ts +2 -1
  68. package/dist/src/computer-access/process-runner.js +21 -13
  69. package/dist/src/model-gateway/server/configuration.d.ts +2 -0
  70. package/dist/src/model-gateway/server/configuration.js +73 -21
  71. package/dist/src/plugin-contract/install-source.d.ts +13 -0
  72. package/dist/src/plugin-contract/install-source.js +99 -0
  73. package/dist/src/plugin-contract/manifest.d.ts +2 -1
  74. package/dist/src/plugin-sdk/computer-access.d.ts +8 -0
  75. package/dist/src/plugin-sdk/computer-access.js +5 -0
  76. package/dist/src/runtime/adapters/in-memory-session-store.js +6 -16
  77. package/dist/src/runtime/admin/config-control.js +2 -1
  78. package/dist/src/runtime/automations/catalog.d.ts +3 -0
  79. package/dist/src/runtime/automations/catalog.js +1 -0
  80. package/dist/src/runtime/automations/model-dependency-projection.d.ts +2 -0
  81. package/dist/src/runtime/automations/service.d.ts +2 -0
  82. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.d.ts +10 -5
  83. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.js +8 -7
  84. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.d.ts +2 -2
  85. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.js +2 -2
  86. package/dist/src/runtime/capabilities/automation-builder/tool-contract.d.ts +2 -2
  87. package/dist/src/runtime/capabilities/automations/authoring-catalog.js +1 -1
  88. package/dist/src/runtime/capabilities/automations/authoring-preparation.d.ts +11 -5
  89. package/dist/src/runtime/capabilities/automations/tool-module.js +1 -1
  90. package/dist/src/runtime/capabilities/request-permission-catalog.d.ts +3 -1
  91. package/dist/src/runtime/capabilities/request-permission-catalog.js +21 -2
  92. package/dist/src/runtime/capabilities/request-permission-tool-registry.d.ts +2 -1
  93. package/dist/src/runtime/capabilities/request-permission-tool-registry.js +18 -10
  94. package/dist/src/runtime/capabilities/request-runtime-tool-registry.d.ts +2 -0
  95. package/dist/src/runtime/capabilities/request-runtime-tool-registry.js +1 -1
  96. package/dist/src/runtime/capabilities/scheduling/create-operations.d.ts +6 -0
  97. package/dist/src/runtime/config/builders.js +6 -5
  98. package/dist/src/runtime/config/effective-model-config-validation.js +4 -35
  99. package/dist/src/runtime/config/fields.js +15 -0
  100. package/dist/src/runtime/config/model-context-capacity.d.ts +20 -0
  101. package/dist/src/runtime/config/model-context-capacity.js +55 -0
  102. package/dist/src/runtime/config/model-execution-policy.d.ts +5 -1
  103. package/dist/src/runtime/config/model-execution-policy.js +16 -0
  104. package/dist/src/runtime/config/model-plugin-config.d.ts +8 -0
  105. package/dist/src/runtime/config/model-plugin-config.js +40 -0
  106. package/dist/src/runtime/config/schema.js +5 -1
  107. package/dist/src/runtime/config/validation/model-profile-validation.js +2 -0
  108. package/dist/src/runtime/config/validation/runtime-config-validation-contract.d.ts +3 -1
  109. package/dist/src/runtime/config/validation/runtime-config-validation-contract.js +3 -1
  110. package/dist/src/runtime/config/validation/runtime-root-section-validation.js +11 -4
  111. package/dist/src/runtime/config/validation/web-ui-config-validation.js +3 -2
  112. package/dist/src/runtime/config/web-ui.d.ts +5 -0
  113. package/dist/src/runtime/config/web-ui.js +5 -0
  114. package/dist/src/runtime/config.js +2 -0
  115. package/dist/src/runtime/local-application.d.ts +2 -0
  116. package/dist/src/runtime/local-host/app-owner.js +50 -6
  117. package/dist/src/runtime/local-host/app-request-control.d.ts +3 -1
  118. package/dist/src/runtime/local-host/app-request-control.js +91 -11
  119. package/dist/src/runtime/local-host/client-requests.js +32 -5
  120. package/dist/src/runtime/local-host/client-services.d.ts +2 -0
  121. package/dist/src/runtime/local-host/local-request-diagnostics.d.ts +9 -0
  122. package/dist/src/runtime/local-host/local-request-diagnostics.js +47 -0
  123. package/dist/src/runtime/local-host/saved-approvals.js +23 -2
  124. package/dist/src/runtime/model/model-selection.js +4 -1
  125. package/dist/src/runtime/observability/request-control-diagnostics.d.ts +6 -0
  126. package/dist/src/runtime/observability/request-control-diagnostics.js +52 -0
  127. package/dist/src/runtime/plugins/configuration-context.d.ts +9 -0
  128. package/dist/src/runtime/plugins/configuration-context.js +42 -0
  129. package/dist/src/runtime/plugins/configuration-settings.d.ts +2 -0
  130. package/dist/src/runtime/plugins/configuration-settings.js +26 -0
  131. package/dist/src/runtime/plugins/configuration-store.d.ts +23 -0
  132. package/dist/src/runtime/plugins/configuration-store.js +100 -0
  133. package/dist/src/runtime/plugins/configuration-write.d.ts +5 -0
  134. package/dist/src/runtime/plugins/configuration-write.js +58 -0
  135. package/dist/src/runtime/plugins/installation/archive.d.ts +2 -0
  136. package/dist/src/runtime/plugins/installation/archive.js +107 -0
  137. package/dist/src/runtime/plugins/installation/github-download.d.ts +9 -0
  138. package/dist/src/runtime/plugins/installation/github-download.js +72 -0
  139. package/dist/src/runtime/plugins/installation/installed-package.d.ts +9 -0
  140. package/dist/src/runtime/plugins/installation/installed-package.js +66 -0
  141. package/dist/src/runtime/plugins/installation/package.d.ts +45 -0
  142. package/dist/src/runtime/plugins/installation/package.js +79 -0
  143. package/dist/src/runtime/plugins/installation/portable-path.d.ts +2 -0
  144. package/dist/src/runtime/plugins/installation/portable-path.js +10 -0
  145. package/dist/src/runtime/plugins/installation/publication.d.ts +10 -0
  146. package/dist/src/runtime/plugins/installation/publication.js +17 -0
  147. package/dist/src/runtime/plugins/installation/service.d.ts +41 -0
  148. package/dist/src/runtime/plugins/installation/service.js +80 -0
  149. package/dist/src/runtime/plugins/loader.js +15 -29
  150. package/dist/src/runtime/plugins/manifest-projection.js +1 -0
  151. package/dist/src/runtime/plugins/manifest-validator.js +3 -0
  152. package/dist/src/runtime/plugins/module-cache.d.ts +2 -0
  153. package/dist/src/runtime/plugins/module-cache.js +19 -0
  154. package/dist/src/runtime/plugins/selection.d.ts +2 -0
  155. package/dist/src/runtime/plugins/selection.js +16 -11
  156. package/dist/src/runtime/ports.d.ts +6 -4
  157. package/dist/src/runtime/request/dependencies.d.ts +2 -1
  158. package/dist/src/runtime/request/execution-payload-compacted-evidence.d.ts +1 -1
  159. package/dist/src/runtime/request/handler.js +8 -0
  160. package/dist/src/runtime/request/prepared-execution.js +6 -1
  161. package/dist/src/runtime/request/request-steering.d.ts +4 -0
  162. package/dist/src/runtime/request/request-steering.js +37 -12
  163. package/dist/src/runtime/request/worker-capability-composition.d.ts +2 -0
  164. package/dist/src/runtime/request/worker-capability-composition.js +4 -1
  165. package/dist/src/runtime/scheduler/journal-index-state.d.ts +1 -1
  166. package/dist/src/sessions/assistant-initiative-message.d.ts +3 -0
  167. package/dist/src/sessions/assistant-initiative-message.js +12 -0
  168. package/dist/src/sessions/assistant-initiative.d.ts +2 -2
  169. package/dist/src/sessions/assistant-initiative.js +1 -7
  170. package/dist/src/sessions/durable-session-commit.d.ts +2 -1
  171. package/dist/src/sessions/durable-session-commit.js +6 -1
  172. package/dist/src/sessions/metadata/projection.d.ts +15 -0
  173. package/dist/src/sessions/metadata/projection.js +55 -0
  174. package/dist/src/sessions/metadata/publication.d.ts +12 -0
  175. package/dist/src/sessions/metadata/publication.js +78 -0
  176. package/dist/src/sessions/metadata/source-receipt.d.ts +5 -0
  177. package/dist/src/sessions/metadata/source-receipt.js +42 -0
  178. package/dist/src/sessions/metadata/store.d.ts +7 -0
  179. package/dist/src/sessions/metadata/store.js +119 -0
  180. package/dist/src/sessions/record/projection.d.ts +3 -1
  181. package/dist/src/sessions/record/projection.js +26 -18
  182. package/dist/src/sessions/request-lifecycle/service.js +3 -3
  183. package/dist/src/sessions/session-service.d.ts +2 -4
  184. package/dist/src/sessions/session-service.js +4 -16
  185. package/dist/src/sessions/session-store.d.ts +2 -1
  186. package/dist/src/sessions/session-store.js +9 -3
  187. package/dist/src/sessions/snapshot.d.ts +17 -0
  188. package/dist/src/sessions/snapshot.js +105 -0
  189. package/dist/src/sessions/types.d.ts +2 -0
  190. package/dist/src/shared/tool-selection.d.ts +2 -0
  191. package/dist/src/shared/tool-selection.js +7 -0
  192. package/dist/src/web-ui/app/ARCHITECTURE.md +14 -0
  193. package/dist/src/web-ui/app/app.js +6 -3
  194. package/dist/src/web-ui/app/components/config-workspace/config-model.js +2 -0
  195. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +130 -0
  196. package/dist/src/web-ui/app/components/config-workspace/model-plugin-selection.js +180 -0
  197. package/dist/src/web-ui/app/components/config-workspace/model-plugin-view-state.js +114 -0
  198. package/dist/src/web-ui/app/components/config-workspace/model-rendering.js +3 -0
  199. package/dist/src/web-ui/app/components/config-workspace/model-summary.js +39 -0
  200. package/dist/src/web-ui/app/components/config-workspace/summary-rendering.js +30 -0
  201. package/dist/src/web-ui/app/components/config-workspace/workspace-events.js +37 -0
  202. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +2 -0
  203. package/dist/src/web-ui/app/components/config-workspace/workspace-persistence.js +9 -1
  204. package/dist/src/web-ui/app/components/config-workspace/workspace-view.js +23 -67
  205. package/dist/src/web-ui/app/components/config-workspace.js +11 -2
  206. package/dist/src/web-ui/app/components/conversation-view.js +36 -5
  207. package/dist/src/web-ui/app/components/dashboard/recent-conversations.js +2 -1
  208. package/dist/src/web-ui/app/components/dashboard/workspace.js +2 -1
  209. package/dist/src/web-ui/app/components/operations-summary.js +105 -0
  210. package/dist/src/web-ui/app/components/passive-learning/home.js +1 -9
  211. package/dist/src/web-ui/app/components/plugins/configuration-draft.js +34 -0
  212. package/dist/src/web-ui/app/components/plugins/configuration-editor.js +147 -0
  213. package/dist/src/web-ui/app/components/plugins/configuration-fields.js +103 -0
  214. package/dist/src/web-ui/app/components/plugins/configuration-retained-secrets.js +20 -0
  215. package/dist/src/web-ui/app/components/plugins/configuration-settings.js +108 -0
  216. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +37 -0
  217. package/dist/src/web-ui/app/components/plugins/installation.js +212 -0
  218. package/dist/src/web-ui/app/components/plugins/manager.js +160 -6
  219. package/dist/src/web-ui/app/components/plugins/removal.js +130 -0
  220. package/dist/src/web-ui/app/components/plugins/rendering.js +14 -2
  221. package/dist/src/web-ui/app/components/plugins/summary.js +54 -0
  222. package/dist/src/web-ui/app/components/plugins/tabs.js +31 -0
  223. package/dist/src/web-ui/app/components/plugins/view-state.js +3 -1
  224. package/dist/src/web-ui/app/components/runtime-setup/connection-form.js +5 -2
  225. package/dist/src/web-ui/app/components/runtime-setup/connection-state.js +9 -1
  226. package/dist/src/web-ui/app/components/runtime-setup/context-window-feedback.js +71 -0
  227. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +2 -0
  228. package/dist/src/web-ui/app/components/runtime-setup-guide.js +15 -3
  229. package/dist/src/web-ui/app/components/spark-chat/empty-state.js +1 -0
  230. package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -0
  231. package/dist/src/web-ui/app/components/system-host/connection-card.js +35 -0
  232. package/dist/src/web-ui/app/components/system-host/macos-setup.js +1 -1
  233. package/dist/src/web-ui/app/components/system-host/manager.js +45 -12
  234. package/dist/src/web-ui/app/components/system-host/rendering.js +111 -106
  235. package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +293 -0
  236. package/dist/src/web-ui/app/components/workspace-shell.js +6 -0
  237. package/dist/src/web-ui/app/computer-access-feature.js +22 -5
  238. package/dist/src/web-ui/app/configuration-feature.js +35 -2
  239. package/dist/src/web-ui/app/controllers/app-event-bindings.js +4 -1
  240. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.d.ts +1 -0
  241. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.js +7 -3
  242. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +88 -0
  243. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +9 -3
  244. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +52 -144
  245. package/dist/src/web-ui/app/controllers/history-pagination.js +111 -0
  246. package/dist/src/web-ui/app/controllers/operations-controller.d.ts +12 -0
  247. package/dist/src/web-ui/app/controllers/operations-controller.js +28 -21
  248. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.d.ts +1 -0
  249. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.js +11 -0
  250. package/dist/src/web-ui/app/controllers/session-controller.js +10 -2
  251. package/dist/src/web-ui/app/controllers/session-list-pagination.js +71 -0
  252. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +6 -4
  253. package/dist/src/web-ui/app/controllers/spark-chat-reading.js +1 -0
  254. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +24 -5
  255. package/dist/src/web-ui/app/controllers/workspace-route-controller.js +21 -19
  256. package/dist/src/web-ui/app/dashboard-feature.js +2 -2
  257. package/dist/src/web-ui/app/index.html +6 -2
  258. package/dist/src/web-ui/app/lib/history-page-messages.js +49 -0
  259. package/dist/src/web-ui/app/lib/request-lifecycle-view.js +8 -0
  260. package/dist/src/web-ui/app/lib/workspace-route.d.ts +3 -0
  261. package/dist/src/web-ui/app/lib/workspace-route.js +4 -0
  262. package/dist/src/web-ui/app/passive-learning-feature.js +0 -1
  263. package/dist/src/web-ui/app/runtime-onboarding-feature.js +3 -0
  264. package/dist/src/web-ui/app/schedules-feature.js +1 -1
  265. package/dist/src/web-ui/app/services/runtime-web-client/configuration.js +20 -0
  266. package/dist/src/web-ui/app/services/runtime-web-client/plugin-configuration.js +19 -0
  267. package/dist/src/web-ui/app/services/runtime-web-client/spark-chat.js +4 -4
  268. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  269. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +6 -1
  270. package/dist/src/web-ui/app/services/runtime-web-client.js +12 -3
  271. package/dist/src/web-ui/app/spark-chat-feature.js +76 -19
  272. package/dist/src/web-ui/app/styles/11-product-links.css +30 -0
  273. package/dist/src/web-ui/app/styles/41-plugin-configuration.css +79 -0
  274. package/dist/src/web-ui/app/styles/41-plugin-discovery.css +132 -0
  275. package/dist/src/web-ui/app/styles/41-plugin-management.css +6 -0
  276. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +173 -0
  277. package/dist/src/web-ui/app/styles/46-system-host.css +61 -107
  278. package/dist/src/web-ui/app/styles/47-config-controls.css +13 -1
  279. package/dist/src/web-ui/app/styles/54-spark-chat.css +33 -1
  280. package/dist/src/web-ui/app/styles.css +4 -0
  281. package/dist/src/web-ui/local-runtime/api-router.js +11 -6
  282. package/dist/src/web-ui/local-runtime/approval-request-attachment.js +14 -5
  283. package/dist/src/web-ui/local-runtime/configuration-activation-source.d.ts +1 -1
  284. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +9 -3
  285. package/dist/src/web-ui/local-runtime/contracts.d.ts +4 -3
  286. package/dist/src/web-ui/local-runtime/environment-registry.d.ts +5 -1
  287. package/dist/src/web-ui/local-runtime/environment-registry.js +53 -11
  288. package/dist/src/web-ui/local-runtime/history-pagination.d.ts +16 -0
  289. package/dist/src/web-ui/local-runtime/history-pagination.js +20 -0
  290. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.d.ts +16 -0
  291. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.js +68 -0
  292. package/dist/src/web-ui/local-runtime/plugin-installation-routes.d.ts +16 -0
  293. package/dist/src/web-ui/local-runtime/plugin-installation-routes.js +96 -0
  294. package/dist/src/web-ui/local-runtime/plugin-management-routes.d.ts +8 -1
  295. package/dist/src/web-ui/local-runtime/plugin-management-routes.js +17 -0
  296. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.d.ts +7 -0
  297. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.js +17 -0
  298. package/dist/src/web-ui/local-runtime/plugin-removal-routes.d.ts +18 -0
  299. package/dist/src/web-ui/local-runtime/plugin-removal-routes.js +60 -0
  300. package/dist/src/web-ui/local-runtime/realtime-controller.js +41 -2
  301. package/dist/src/web-ui/local-runtime/request-cancellation-route.js +28 -1
  302. package/dist/src/web-ui/local-runtime/request-control-observation.d.ts +19 -0
  303. package/dist/src/web-ui/local-runtime/request-control-observation.js +80 -0
  304. package/dist/src/web-ui/local-runtime/request-execution.js +69 -37
  305. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +20 -0
  306. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +44 -0
  307. package/dist/src/web-ui/local-runtime/runtime-setup-routes.js +2 -0
  308. package/dist/src/web-ui/local-runtime/runtime-setup-validation.js +9 -2
  309. package/dist/src/web-ui/local-runtime/session-routes.d.ts +1 -0
  310. package/dist/src/web-ui/local-runtime/session-routes.js +16 -4
  311. package/dist/src/web-ui/local-runtime/spark-chat-routes.js +4 -3
  312. package/dist/src/web-ui/plugin-capability-selection.js +4 -1
  313. package/dist/src/web-ui/plugin-configuration-input.d.ts +12 -0
  314. package/dist/src/web-ui/plugin-configuration-input.js +68 -0
  315. package/dist/src/web-ui/plugin-configuration-retained-secrets.d.ts +9 -0
  316. package/dist/src/web-ui/plugin-configuration-retained-secrets.js +48 -0
  317. package/dist/src/web-ui/plugin-configuration-service.d.ts +52 -0
  318. package/dist/src/web-ui/plugin-configuration-service.js +66 -0
  319. package/dist/src/web-ui/plugin-configuration-view.d.ts +25 -0
  320. package/dist/src/web-ui/plugin-configuration-view.js +45 -0
  321. package/dist/src/web-ui/plugin-disabled-selection.d.ts +7 -0
  322. package/dist/src/web-ui/plugin-disabled-selection.js +17 -0
  323. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  324. package/dist/src/web-ui/plugin-management-catalog.js +11 -1
  325. package/dist/src/web-ui/plugin-management-selection.js +22 -9
  326. package/dist/src/web-ui/plugin-management-service.d.ts +5 -1
  327. package/dist/src/web-ui/plugin-management-service.js +11 -7
  328. package/dist/src/web-ui/plugin-removal-error.d.ts +7 -0
  329. package/dist/src/web-ui/plugin-removal-error.js +16 -0
  330. package/dist/src/web-ui/plugin-removal-service.d.ts +30 -0
  331. package/dist/src/web-ui/plugin-removal-service.js +109 -0
  332. package/dist/src/web-ui/runtime-setup-gateway.d.ts +6 -2
  333. package/dist/src/web-ui/runtime-setup-gateway.js +30 -10
  334. package/dist/src/web-ui/server.js +6 -2
  335. package/dist/src/web-ui/session-read-state/overview.d.ts +42 -0
  336. package/dist/src/web-ui/session-read-state/overview.js +16 -0
  337. package/dist/src/web-ui/session-read-state/pagination.d.ts +15 -0
  338. package/dist/src/web-ui/session-read-state/pagination.js +42 -0
  339. package/dist/src/web-ui/session-read-state/projection.d.ts +4 -3
  340. package/dist/src/web-ui/session-read-state/service.d.ts +213 -20
  341. package/dist/src/web-ui/session-read-state/service.js +25 -23
  342. package/dist/src/web-ui/session-read-state/visible-messages.d.ts +3 -3
  343. package/dist/src/web-ui/system-host-setup/companion-linux.js +1 -1
  344. package/dist/src/web-ui/system-host-setup/installer-contract.d.ts +1 -1
  345. package/dist/src/web-ui/system-host-setup/installer-contract.js +2 -2
  346. package/dist/src/web-ui/system-host-setup/installers.js +0 -7
  347. package/dist/src/web-ui/system-host-setup/local-connection.d.ts +4 -1
  348. package/dist/src/web-ui/system-host-setup/local-connection.js +10 -17
  349. package/dist/src/web-ui/system-host-setup/routes.d.ts +2 -0
  350. package/dist/src/web-ui/system-host-setup/routes.js +32 -9
  351. package/dist/src/web-ui/system-host-setup/setup-mutation.d.ts +9 -0
  352. package/dist/src/web-ui/system-host-setup/setup-mutation.js +27 -0
  353. package/dist/src/web-ui/system-host-setup/windows-store-route.d.ts +13 -0
  354. package/dist/src/web-ui/system-host-setup/windows-store-route.js +68 -0
  355. package/docs/configuration.md +46 -0
  356. package/docs/installation.md +45 -24
  357. package/docs/plugins.md +165 -2
  358. package/docs/projects-and-full-plus.md +2 -6
  359. package/docs/runtime-library.md +0 -1
  360. package/docs/windows-companion-store.md +127 -0
  361. package/package.json +3 -3
  362. package/plugins/document-reader/plugin.json +1 -0
  363. package/plugins/exec/plugin.json +3 -0
  364. package/plugins/filesystem/plugin.json +2 -0
  365. package/plugins/local-search/plugin.json +1 -0
  366. package/plugins/system/README.md +43 -3
  367. package/plugins/system/plugin.json +5 -0
  368. package/plugins/system/source/companion-command-output.ts +82 -0
  369. package/plugins/system/source/host-dispatch.ts +4 -0
  370. package/plugins/system/source/index.ts +11 -5
  371. package/plugins/system/source/local-command-output.ts +61 -0
  372. package/plugins/system/source/request-system-modules.ts +2 -0
  373. package/plugins/system/src/index.cjs +474 -39
  374. package/plugins/web/README.md +2 -2
  375. package/plugins/web/plugin.json +4 -0
  376. package/runtime.config.schema.json +25 -1
  377. package/src/runtime/README.md +12 -2
  378. package/dist/src/web-ui/system-host-setup/companion-windows.d.ts +0 -2
  379. package/dist/src/web-ui/system-host-setup/companion-windows.js +0 -108
  380. package/docs/publishing.md +0 -167
@@ -0,0 +1,25 @@
1
+ import { type PluginConfigurationDeclaration } from "../runtime/plugins/configuration-context.js";
2
+ import type { PluginConfigurationSnapshot, PluginLocalConfiguration } from "../runtime/plugins/configuration-store.js";
3
+ export declare function pluginConfigurationRevision(pluginId: string, declaration: PluginConfigurationDeclaration, store: PluginConfigurationSnapshot): string;
4
+ /** Password values never enter browser projections, including installation review. */
5
+ export declare function projectPluginConfiguration(pluginId: string, declaration: PluginConfigurationDeclaration, store: PluginConfigurationSnapshot): {
6
+ pluginId: string;
7
+ revision: string;
8
+ scope: "installation";
9
+ defaults: Readonly<Record<string, unknown>>;
10
+ settings: Record<string, unknown>;
11
+ settingOverrides: string[];
12
+ retainedSecrets: {
13
+ name: string;
14
+ env: string;
15
+ configured: boolean;
16
+ }[];
17
+ secrets: {
18
+ name: string;
19
+ env: string;
20
+ required: boolean;
21
+ configured: boolean;
22
+ locallyConfigured: boolean;
23
+ }[];
24
+ };
25
+ export declare function hasConfigurablePluginValues(declaration: PluginConfigurationDeclaration, local?: PluginLocalConfiguration): boolean;
@@ -0,0 +1,45 @@
1
+ import { retainedPluginSecrets } from "./plugin-configuration-retained-secrets.js";
2
+ import { createHmac, randomBytes } from "node:crypto";
3
+ import { configuredPluginSecret, effectivePluginSettings, } from "../runtime/plugins/configuration-context.js";
4
+ // Tokens stay stable within this Web process; a restart requires reloading forms.
5
+ // The private key prevents browser-visible revisions from verifying secret guesses.
6
+ const configurationRevisionKey = randomBytes(32);
7
+ export function pluginConfigurationRevision(pluginId, declaration, store) {
8
+ return createHmac("sha256", configurationRevisionKey)
9
+ .update(JSON.stringify([
10
+ pluginId,
11
+ declaration.settings?.defaults ?? {},
12
+ declaration.secrets ?? {},
13
+ store.revision,
14
+ ]))
15
+ .digest("hex");
16
+ }
17
+ /** Password values never enter browser projections, including installation review. */
18
+ export function projectPluginConfiguration(pluginId, declaration, store) {
19
+ const local = Object.hasOwn(store.plugins, pluginId)
20
+ ? store.plugins[pluginId]
21
+ : undefined;
22
+ return {
23
+ pluginId,
24
+ revision: pluginConfigurationRevision(pluginId, declaration, store),
25
+ scope: "installation",
26
+ defaults: declaration.settings?.defaults ?? {},
27
+ settings: effectivePluginSettings(declaration, local),
28
+ settingOverrides: Object.keys(declaration.settings?.defaults ?? {}).filter((name) => !!local && Object.hasOwn(local.settings, name)),
29
+ retainedSecrets: retainedPluginSecrets(declaration, local),
30
+ secrets: Object.entries(declaration.secrets ?? {}).map(([name, secret]) => ({
31
+ name,
32
+ env: secret.env,
33
+ required: secret.required,
34
+ configured: Boolean(configuredPluginSecret(name, secret, local)),
35
+ locallyConfigured: local?.secrets[name]?.env === secret.env,
36
+ })),
37
+ };
38
+ }
39
+ export function hasConfigurablePluginValues(declaration, local) {
40
+ if (Object.keys(declaration.settings?.defaults ?? {}).length > 0)
41
+ return true;
42
+ if (Object.keys(declaration.secrets ?? {}).length > 0)
43
+ return true;
44
+ return retainedPluginSecrets(declaration, local).length > 0;
45
+ }
@@ -0,0 +1,7 @@
1
+ import type { RuntimePluginConfig } from "../runtime/ports.js";
2
+ /** Update only the exact plugin-ID block; leave all tool policy untouched. */
3
+ export declare function updatePluginDisabledIds(params: {
4
+ current: RuntimePluginConfig;
5
+ pluginId: string;
6
+ enabled: boolean;
7
+ }): RuntimePluginConfig;
@@ -0,0 +1,17 @@
1
+ /** Update only the exact plugin-ID block; leave all tool policy untouched. */
2
+ export function updatePluginDisabledIds(params) {
3
+ const { current, pluginId, enabled } = params;
4
+ const disabledPluginIds = current.disabledPluginIds ?? [];
5
+ if (enabled) {
6
+ const { disabledPluginIds: _disabled, ...settings } = current;
7
+ const remaining = disabledPluginIds.filter((id) => id.trim() !== pluginId);
8
+ return {
9
+ ...settings,
10
+ ...(remaining.length ? { disabledPluginIds: remaining } : {}),
11
+ };
12
+ }
13
+ const alreadyDisabled = disabledPluginIds.some((id) => id.trim() === pluginId);
14
+ if (alreadyDisabled)
15
+ return current;
16
+ return { ...current, disabledPluginIds: [...disabledPluginIds, pluginId] };
17
+ }
@@ -15,6 +15,8 @@ export type RuntimePluginSnapshot = {
15
15
  description?: string;
16
16
  version?: string;
17
17
  pluginEnabled: boolean;
18
+ removable: boolean;
19
+ configurable: boolean;
18
20
  capabilities: RuntimePluginCapabilitySnapshot[];
19
21
  capabilityCount: number;
20
22
  selectedCapabilityCount: number;
@@ -23,4 +25,4 @@ export type RuntimePluginSnapshot = {
23
25
  }>;
24
26
  application: "restart_required";
25
27
  };
26
- export declare function projectPluginSnapshot(manifests: readonly DiscoveredAgentPluginManifest[], config: RuntimePluginConfig): RuntimePluginSnapshot;
28
+ export declare function projectPluginSnapshot(manifests: readonly DiscoveredAgentPluginManifest[], config: RuntimePluginConfig, consumerRoot?: string): RuntimePluginSnapshot;
@@ -1,3 +1,6 @@
1
+ import { readPluginConfigurationStore } from "../runtime/plugins/configuration-store.js";
2
+ import { hasConfigurablePluginValues } from "./plugin-configuration-view.js";
3
+ import { installedPluginPackage } from "../runtime/plugins/installation/installed-package.js";
1
4
  import { ABOT_RUNTIME_EXTENSION } from "../plugin-contract/manifest.js";
2
5
  import { isPluginToolSelected, normalizePluginSelection, } from "../runtime/plugins/selection.js";
3
6
  import { capabilityPolicyBlockReason, pluginParentBlockReason, } from "./plugin-capability-selection.js";
@@ -30,8 +33,11 @@ function projectPluginCapabilities(plugin, selection) {
30
33
  };
31
34
  });
32
35
  }
33
- export function projectPluginSnapshot(manifests, config) {
36
+ export function projectPluginSnapshot(manifests, config, consumerRoot) {
34
37
  const selection = normalizePluginSelection(config);
38
+ const local = consumerRoot
39
+ ? readPluginConfigurationStore(consumerRoot).plugins
40
+ : {};
35
41
  return {
36
42
  selection,
37
43
  plugins: manifests.map((plugin) => {
@@ -41,6 +47,10 @@ export function projectPluginSnapshot(manifests, config) {
41
47
  const selectedCapabilityCount = capabilities.filter((capability) => capability.enabled).length;
42
48
  return {
43
49
  id: manifest.name,
50
+ configurable: hasConfigurablePluginValues(manifest.extensions[ABOT_RUNTIME_EXTENSION], Object.hasOwn(local, manifest.name)
51
+ ? local[manifest.name]
52
+ : undefined),
53
+ removable: !!consumerRoot && !!installedPluginPackage(consumerRoot, plugin),
44
54
  ...(manifest.description ? { description: manifest.description } : {}),
45
55
  ...(manifest.version ? { version: manifest.version } : {}),
46
56
  pluginEnabled: pluginParentBlockReason(manifest.name, selection) === undefined,
@@ -1,6 +1,7 @@
1
1
  import { ABOT_RUNTIME_EXTENSION } from "../plugin-contract/manifest.js";
2
+ import { updatePluginDisabledIds } from "./plugin-disabled-selection.js";
2
3
  import { updatePluginCapabilitySelection } from "./plugin-capability-selection.js";
3
- import { isPluginToolSelected, normalizePluginSelection, } from "../runtime/plugins/selection.js";
4
+ import { isPluginToolSelected, isPluginDisabledById, normalizePluginSelection, } from "../runtime/plugins/selection.js";
4
5
  export function updatePluginSelection(params) {
5
6
  if (params.capabilityId !== undefined) {
6
7
  return updatePluginCapabilitySelection({
@@ -9,14 +10,14 @@ export function updatePluginSelection(params) {
9
10
  });
10
11
  }
11
12
  const { current, pluginId } = params;
12
- if (!params.enabled) {
13
- const deny = [...(current.deny ?? [])];
14
- if (!deny.some((id) => id.trim() === pluginId))
15
- deny.push(pluginId);
16
- return { ...current, deny };
17
- }
13
+ const selection = updatePluginDisabledIds(params);
14
+ if (!params.enabled)
15
+ return selection;
16
+ const wasDisabledById = isPluginDisabledById(pluginId, normalizePluginSelection(current));
17
+ if (wasDisabledById)
18
+ return selection;
18
19
  const deny = current.deny?.filter((id) => id.trim() !== pluginId);
19
- const next = { ...current, ...(deny ? { deny } : {}) };
20
+ const next = { ...selection, ...(deny ? { deny } : {}) };
20
21
  if (hasAllowedPluginCapability(params))
21
22
  return next;
22
23
  return { ...next, allow: [...(current.allow ?? []), pluginId] };
@@ -26,6 +27,7 @@ function hasAllowedPluginCapability(params) {
26
27
  ...params.current,
27
28
  enabled: true,
28
29
  deny: [],
30
+ disabledPluginIds: [],
29
31
  });
30
32
  return params.capabilityIds.some((toolName) => isPluginToolSelected({ pluginId: params.pluginId, toolName, selection }));
31
33
  }
@@ -48,12 +50,14 @@ function selectorMatchesOtherCapability(params) {
48
50
  return params.changedEntries.some((entry) => isPluginToolSelected({
49
51
  pluginId: params.pluginId,
50
52
  toolName: params.toolName,
51
- selection: { enabled: true, allow: [entry], deny: [] },
53
+ selection: normalizePluginSelection({ allow: [entry] }),
52
54
  }));
53
55
  }
54
56
  export function pluginSelectionEscapesRequestedScope(params) {
55
57
  const before = normalizePluginSelection(params.before);
56
58
  const after = normalizePluginSelection(params.after);
59
+ if (hasUnrequestedPluginDisableChange(params, before, after))
60
+ return true;
57
61
  const changedEntries = changedSelectionEntries(before, after);
58
62
  return params.manifests.some((plugin) => {
59
63
  const pluginId = plugin.manifest.name;
@@ -69,3 +73,12 @@ export function pluginSelectionEscapesRequestedScope(params) {
69
73
  });
70
74
  });
71
75
  }
76
+ function hasUnrequestedPluginDisableChange(params, before, after) {
77
+ const changedIds = [
78
+ ...before.disabledPluginIds.filter((id) => !after.disabledPluginIds.includes(id)),
79
+ ...after.disabledPluginIds.filter((id) => !before.disabledPluginIds.includes(id)),
80
+ ];
81
+ if (params.capabilityId !== undefined)
82
+ return changedIds.length > 0;
83
+ return changedIds.some((id) => id !== params.pluginId);
84
+ }
@@ -1,8 +1,10 @@
1
+ import { type ConfigFileTransaction } from "../runtime/adapters/config-file-transaction.js";
1
2
  import { type RuntimePluginSnapshot } from "./plugin-management-catalog.js";
2
3
  export type { RuntimePluginSnapshot } from "./plugin-management-catalog.js";
3
4
  export type PluginManagementOptions = {
4
5
  rootDir: string;
5
6
  configPath?: string;
7
+ requireMutationIdle?: () => void;
6
8
  };
7
9
  export declare class PluginManagementError extends Error {
8
10
  readonly code: string;
@@ -10,7 +12,7 @@ export declare class PluginManagementError extends Error {
10
12
  constructor(code: string, message: string, statusCode?: number);
11
13
  }
12
14
  export declare function getRuntimePluginSnapshot(options: PluginManagementOptions): RuntimePluginSnapshot;
13
- export declare function setRuntimePluginEnabled(options: PluginManagementOptions, input: unknown): Promise<{
15
+ export declare function setRuntimePluginEnabled(options: PluginManagementOptions, input: unknown, transaction?: ConfigFileTransaction): Promise<{
14
16
  backupPath?: string | undefined;
15
17
  restartRequired: boolean;
16
18
  selection: import("../runtime/plugins/selection.js").PluginSelection;
@@ -19,6 +21,8 @@ export declare function setRuntimePluginEnabled(options: PluginManagementOptions
19
21
  description?: string;
20
22
  version?: string;
21
23
  pluginEnabled: boolean;
24
+ removable: boolean;
25
+ configurable: boolean;
22
26
  capabilities: import("./plugin-management-catalog.js").RuntimePluginCapabilitySnapshot[];
23
27
  capabilityCount: number;
24
28
  selectedCapabilityCount: number;
@@ -1,5 +1,5 @@
1
1
  import { realpathSync } from "node:fs";
2
- import { ConfigFileConflictError, withConfigFileTransaction, } from "../runtime/adapters/config-file-transaction.js";
2
+ import { ConfigFileConflictError, } from "../runtime/adapters/config-file-transaction.js";
3
3
  import { inspectRuntimeConfigFileWithMeta } from "../runtime/config/loader.js";
4
4
  import { isRecord } from "../runtime/config/utils.js";
5
5
  import { validatePluginConfig } from "../runtime/config/validation/runtime-root-section-validation.js";
@@ -8,6 +8,7 @@ import { discoverConfiguredRuntimePluginManifests } from "../runtime/plugins/con
8
8
  import { normalizePluginSelection } from "../runtime/plugins/selection.js";
9
9
  import { capabilityPolicyBlockReason } from "./plugin-capability-selection.js";
10
10
  import { projectPluginSnapshot, } from "./plugin-management-catalog.js";
11
+ import { withConfigDashboardRootTransaction } from "./config-dashboard-save-transaction.js";
11
12
  import { saveConfigDashboardFile } from "./config-dashboard-backend.js";
12
13
  import { pluginSelectionEscapesRequestedScope, updatePluginSelection, } from "./plugin-management-selection.js";
13
14
  export class PluginManagementError extends Error {
@@ -34,7 +35,7 @@ function readPluginSelection(value) {
34
35
  }
35
36
  export function getRuntimePluginSnapshot(options) {
36
37
  const source = inspectRuntimeConfigFileWithMeta(options.rootDir, options.configPath);
37
- return projectPluginSnapshot(discoverConfiguredRuntimePluginManifests(options.rootDir), readPluginSelection(source.config.plugins));
38
+ return projectPluginSnapshot(discoverConfiguredRuntimePluginManifests(options.rootDir), readPluginSelection(source.config.plugins), options.rootDir);
38
39
  }
39
40
  function isPluginSelectionIdentifier(value) {
40
41
  if (typeof value !== "string")
@@ -93,16 +94,17 @@ function configuredPluginSource(options) {
93
94
  }
94
95
  return source;
95
96
  }
96
- export async function setRuntimePluginEnabled(options, input) {
97
+ export async function setRuntimePluginEnabled(options, input, transaction) {
97
98
  const toggle = parsePluginToggle(input);
98
99
  const source = configuredPluginSource(options);
99
100
  const configPath = realpathSync(source.path);
100
101
  const canonicalOptions = {
101
102
  rootDir: realpathSync(options.rootDir),
102
103
  configPath,
104
+ requireMutationIdle: options.requireMutationIdle,
103
105
  };
104
106
  try {
105
- return await withConfigFileTransaction(configPath, (transaction) => savePluginSelection(canonicalOptions, toggle, transaction));
107
+ return await withConfigDashboardRootTransaction(configPath, transaction, (transaction) => savePluginSelection(canonicalOptions, toggle, transaction));
106
108
  }
107
109
  catch (error) {
108
110
  if (error instanceof ConfigFileConflictError)
@@ -119,13 +121,14 @@ async function savePluginSelection(options, toggle, transaction) {
119
121
  const current = readPluginSelection(source.config.plugins);
120
122
  const capabilityId = toggle.capabilityId;
121
123
  requireCapabilityUpdateAllowed(plugin, toggle, current);
122
- const next = updatePluginSelection({
124
+ const selectionInput = {
123
125
  current,
124
126
  ...(capabilityId ? { capabilityId } : {}),
125
127
  pluginId: toggle.pluginId,
126
128
  capabilityIds: Object.keys(plugin.manifest.extensions[ABOT_RUNTIME_EXTENSION].capabilities),
127
129
  enabled: toggle.enabled,
128
- });
130
+ };
131
+ const next = updatePluginSelection(selectionInput);
129
132
  const escapesRequestedScope = pluginSelectionEscapesRequestedScope({
130
133
  manifests,
131
134
  pluginId: toggle.pluginId,
@@ -136,6 +139,7 @@ async function savePluginSelection(options, toggle, transaction) {
136
139
  if (escapesRequestedScope) {
137
140
  throw new PluginManagementError("plugin_selection_conflict", "This selection would also change other capabilities. Review the selection in Advanced settings.", 409);
138
141
  }
142
+ options.requireMutationIdle?.();
139
143
  const result = await saveConfigDashboardFile({
140
144
  ...options,
141
145
  kind: "runtime",
@@ -143,7 +147,7 @@ async function savePluginSelection(options, toggle, transaction) {
143
147
  transaction,
144
148
  });
145
149
  return {
146
- ...projectPluginSnapshot(manifests, next),
150
+ ...projectPluginSnapshot(manifests, next, options.rootDir),
147
151
  restartRequired: true,
148
152
  ...(result.backupPath ? { backupPath: result.backupPath } : {}),
149
153
  };
@@ -0,0 +1,7 @@
1
+ import { PluginManagementError } from "./plugin-management-service.js";
2
+ import type { RuntimeSetupActivation } from "./local-runtime/runtime-setup-input.js";
3
+ /** Keep confirmed activation evidence when the later file removal fails. */
4
+ export declare class PluginRemovalActivationError extends PluginManagementError {
5
+ readonly activation: RuntimeSetupActivation;
6
+ constructor(error: unknown, activation: RuntimeSetupActivation);
7
+ }
@@ -0,0 +1,16 @@
1
+ import { ConfigFileConflictError } from "../runtime/adapters/config-file-transaction.js";
2
+ import { PluginManagementError } from "./plugin-management-service.js";
3
+ /** Keep confirmed activation evidence when the later file removal fails. */
4
+ export class PluginRemovalActivationError extends PluginManagementError {
5
+ activation;
6
+ constructor(error, activation) {
7
+ const known = error instanceof PluginManagementError ||
8
+ error instanceof ConfigFileConflictError;
9
+ const status = error instanceof PluginManagementError ? error.statusCode : 500;
10
+ super(known ? error.code : "plugin_removal_failed", known
11
+ ? error.message
12
+ : "Plugin removal could not complete. Refresh plugins before trying again.", error instanceof ConfigFileConflictError ? 409 : status);
13
+ this.activation = activation;
14
+ this.cause = error;
15
+ }
16
+ }
@@ -0,0 +1,30 @@
1
+ import type { RuntimeSetupActivation } from "./local-runtime/runtime-setup-input.js";
2
+ import { type PluginManagementOptions } from "./plugin-management-service.js";
3
+ export type PluginRemovalRuntime = {
4
+ applyConfiguration: (expectedRevision: string) => Promise<RuntimeSetupActivation>;
5
+ requireInactive: (pluginId: string, capabilityIds: readonly string[]) => void;
6
+ };
7
+ /** Disable, activate at the owner, then remove while configuration writers are fenced. */
8
+ export declare function removeRuntimePlugin(options: PluginManagementOptions & PluginRemovalRuntime, input: unknown): Promise<{
9
+ removed: boolean;
10
+ activation: Readonly<{
11
+ status: "ready" | "restart_required";
12
+ message?: string;
13
+ }>;
14
+ message: string;
15
+ selection: import("../runtime/plugins/selection.js").PluginSelection;
16
+ plugins: Array<{
17
+ id: string;
18
+ description?: string;
19
+ version?: string;
20
+ pluginEnabled: boolean;
21
+ removable: boolean;
22
+ configurable: boolean;
23
+ capabilities: import("./plugin-management-catalog.js").RuntimePluginCapabilitySnapshot[];
24
+ capabilityCount: number;
25
+ selectedCapabilityCount: number;
26
+ state: "enabled" | "partial" | "disabled";
27
+ blockedByGlobalPolicy: boolean;
28
+ }>;
29
+ application: "restart_required";
30
+ }>;
@@ -0,0 +1,109 @@
1
+ import { realpathSync, renameSync } from "node:fs";
2
+ import { mkdtemp, rm, rmdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { ABOT_RUNTIME_EXTENSION } from "../plugin-contract/manifest.js";
5
+ import { withConfigFileTransaction } from "../runtime/adapters/config-file-transaction.js";
6
+ import { withFileLock } from "../runtime/adapters/long-term-memory/file-lock.js";
7
+ import { inspectRuntimeConfigFileWithMeta } from "../runtime/config/loader.js";
8
+ import { discoverConfiguredRuntimePluginManifests } from "../runtime/plugins/configured-manifests.js";
9
+ import { evictPluginModules } from "../runtime/plugins/module-cache.js";
10
+ import { installedPluginPackage, installedPluginPackageIdentity, } from "../runtime/plugins/installation/installed-package.js";
11
+ import { normalizePluginSelection, isPluginToolSelected, } from "../runtime/plugins/selection.js";
12
+ import { PluginRemovalActivationError } from "./plugin-removal-error.js";
13
+ import { getRuntimePluginSnapshot, PluginManagementError, setRuntimePluginEnabled, } from "./plugin-management-service.js";
14
+ function removablePackage(rootDir, pluginId, afterSave = false) {
15
+ const plugin = discoverConfiguredRuntimePluginManifests(rootDir).find((entry) => entry.manifest.name === pluginId);
16
+ const installed = plugin && installedPluginPackage(rootDir, plugin);
17
+ if (!plugin || !installed)
18
+ throw new PluginManagementError(afterSave ? "plugin_changed" : "plugin_not_removable", "Only plugins installed from GitHub in this Runtime can be removed.", 409);
19
+ return {
20
+ ...installed,
21
+ capabilityIds: Object.keys(plugin.manifest.extensions[ABOT_RUNTIME_EXTENSION].capabilities),
22
+ };
23
+ }
24
+ /** Disable, activate at the owner, then remove while configuration writers are fenced. */
25
+ export async function removeRuntimePlugin(options, input) {
26
+ const value = input;
27
+ if (!value ||
28
+ typeof value !== "object" ||
29
+ Object.keys(value).some((key) => key !== "pluginId") ||
30
+ typeof value.pluginId !== "string" ||
31
+ !value.pluginId.trim())
32
+ throw new PluginManagementError("invalid_plugin_removal", "Choose an installed plugin to remove.");
33
+ const pluginId = value.pluginId.trim();
34
+ const rootDir = realpathSync(options.rootDir);
35
+ const source = inspectRuntimeConfigFileWithMeta(rootDir, options.configPath);
36
+ if (!source.exists)
37
+ throw new PluginManagementError("runtime_setup_required", "Complete Runtime setup before removing plugins.", 409);
38
+ const configPath = realpathSync(source.path);
39
+ const canonical = {
40
+ rootDir,
41
+ configPath,
42
+ requireMutationIdle: options.requireMutationIdle,
43
+ };
44
+ return withFileLock(join(rootDir, ".abot-plugin-installation"), async () => {
45
+ const original = removablePackage(rootDir, pluginId);
46
+ const expectedRevision = await withConfigFileTransaction(configPath, async (transaction) => {
47
+ await setRuntimePluginEnabled(canonical, { pluginId, enabled: false }, transaction);
48
+ return transaction.snapshot.revision;
49
+ });
50
+ const activation = await options.applyConfiguration(expectedRevision);
51
+ if (activation.status !== "ready")
52
+ return {
53
+ ...getRuntimePluginSnapshot(canonical),
54
+ removed: false,
55
+ activation,
56
+ message: "Plugin disable saved. Files are still installed. " +
57
+ (activation.message ?? "Runtime application is required.") +
58
+ " Then choose Remove again.",
59
+ };
60
+ // Apply takes this same lock; acquire it only after activation has completed.
61
+ return withConfigFileTransaction(configPath, async (transaction) => {
62
+ if (transaction.snapshot.revision !== expectedRevision)
63
+ throw new PluginManagementError("config_changed", "Configuration changed after the plugin disable. Refresh and try Remove again.", 409);
64
+ const current = removablePackage(rootDir, pluginId, true);
65
+ if (current.identity !== original.identity)
66
+ throw new PluginManagementError("plugin_changed", "The installed plugin changed. Refresh and try again.", 409);
67
+ const saved = inspectRuntimeConfigFileWithMeta(rootDir, configPath);
68
+ const selection = normalizePluginSelection(saved.config.plugins);
69
+ if (current.capabilityIds.some((toolName) => isPluginToolSelected({ pluginId, toolName, selection })))
70
+ throw new PluginManagementError("plugin_selection_changed", "The plugin was enabled again. Refresh and try again.", 409);
71
+ const staging = await mkdtemp(join(rootDir, ".abot-plugin-removal-"));
72
+ try {
73
+ // No asynchronous gap between the loaded-owner check and moving the directory.
74
+ options.requireInactive(pluginId, current.capabilityIds);
75
+ const final = removablePackage(rootDir, pluginId, true);
76
+ if (final.identity !== original.identity)
77
+ throw new PluginManagementError("plugin_changed", "The installed plugin changed. Refresh and try again.", 409);
78
+ renameSync(final.path, join(staging, pluginId));
79
+ }
80
+ catch (error) {
81
+ // Remove only an empty staging directory; never erase an unexpectedly moved object.
82
+ await rmdir(staging).catch(() => undefined);
83
+ throw error;
84
+ }
85
+ if (installedPluginPackageIdentity(join(staging, pluginId)) !==
86
+ original.packageIdentity)
87
+ throw new PluginManagementError("plugin_changed", `The plugin directory changed during removal. Its files were preserved at ${staging}. Refresh before trying again.`, 409);
88
+ evictPluginModules(original.path);
89
+ // Preserve deny/allow selectors: deleting the last allow rule would enable other plugins.
90
+ let cleanupPending = false;
91
+ try {
92
+ await rm(staging, { recursive: true, force: true });
93
+ }
94
+ catch {
95
+ cleanupPending = true;
96
+ }
97
+ return {
98
+ ...getRuntimePluginSnapshot(canonical),
99
+ removed: true,
100
+ activation,
101
+ message: cleanupPending
102
+ ? `${pluginId} removed from Plugins. Some files could not be deleted from ${staging}.`
103
+ : `${pluginId} removed.`,
104
+ };
105
+ }).catch((error) => {
106
+ throw new PluginRemovalActivationError(error, activation);
107
+ });
108
+ });
109
+ }
@@ -3,6 +3,7 @@ import type { RuntimeSetupActivation } from "./local-runtime/runtime-setup-input
3
3
  export type RuntimeSetupGatewayRestorePoint = {
4
4
  restore(): Promise<void>;
5
5
  };
6
+ export type AppliedGatewayConfigurations = readonly (string | null)[];
6
7
  /** Owns only a gateway started by this Web/CLI process, never an external service. */
7
8
  export declare class RuntimeSetupGateway {
8
9
  private readonly options;
@@ -15,7 +16,10 @@ export declare class RuntimeSetupGateway {
15
16
  });
16
17
  private requireGatewayOpen;
17
18
  private configuredBinding;
18
- checkActivation(configPath?: string): Promise<RuntimeSetupActivation>;
19
+ captureConfiguration(configPath?: string): string | null;
20
+ private matchesAppliedConfiguration;
21
+ checkActivation(configPath?: string, applied?: AppliedGatewayConfigurations): Promise<RuntimeSetupActivation>;
22
+ private planActivation;
19
23
  private captureGatewayCheckpoint;
20
24
  /** Retains the old server's compiled handlers, without rereading saved config. */
21
25
  createRestorePoint(): RuntimeSetupGatewayRestorePoint;
@@ -24,6 +28,6 @@ export declare class RuntimeSetupGateway {
24
28
  private replaceOwnedGateway;
25
29
  private closeGatewayListener;
26
30
  private failAfterGatewayCleanup;
27
- activate(configPath?: string): Promise<RuntimeSetupActivation>;
31
+ activate(configPath?: string, applied?: AppliedGatewayConfigurations): Promise<RuntimeSetupActivation>;
28
32
  close(): Promise<void>;
29
33
  }
@@ -1,5 +1,6 @@
1
1
  import { isLoopbackGateway, hasGatewayListener, } from "./runtime-setup-gateway-address.js";
2
2
  import { createModelGatewayServer, } from "../model-gateway/server.js";
3
+ import { captureModelGatewayConfiguration } from "../model-gateway/server/configuration.js";
3
4
  import { loadRuntimeConfig } from "../runtime/config.js";
4
5
  import { closeHttpServerImmediately } from "../shared/http-server-shutdown.js";
5
6
  function listenGateway(server, port, host) {
@@ -35,7 +36,22 @@ export class RuntimeSetupGateway {
35
36
  const port = Number(url.port || "80");
36
37
  return { url, host, port };
37
38
  }
38
- async checkActivation(configPath) {
39
+ captureConfiguration(configPath) {
40
+ return captureModelGatewayConfiguration({ ...this.options, configPath });
41
+ }
42
+ matchesAppliedConfiguration(configPath, applied) {
43
+ if (this.owned)
44
+ return false;
45
+ if (!applied?.length)
46
+ return false;
47
+ const candidate = this.captureConfiguration(configPath);
48
+ return (candidate !== null && applied.every((previous) => previous === candidate));
49
+ }
50
+ async checkActivation(configPath, applied) {
51
+ const plan = await this.planActivation(configPath, applied);
52
+ return plan.status === "ready" ? { status: "ready" } : plan;
53
+ }
54
+ async planActivation(configPath, applied) {
39
55
  this.requireGatewayOpen();
40
56
  const { url, host, port } = this.configuredBinding(configPath);
41
57
  if (!isLoopbackGateway(url)) {
@@ -49,13 +65,14 @@ export class RuntimeSetupGateway {
49
65
  const ownedHost = ownsTargetPort ? ownAddress.address : undefined;
50
66
  const externalListener = await hasGatewayListener(port, host, ownedHost);
51
67
  this.requireGatewayOpen();
52
- if (externalListener) {
53
- return {
54
- status: "restart_required",
55
- message: "Configuration saved. An existing model gateway owns this address; restart that gateway to load its new configuration.",
56
- };
57
- }
58
- return { status: "ready" };
68
+ if (!externalListener)
69
+ return { status: "ready", retainExternal: false };
70
+ if (this.matchesAppliedConfiguration(configPath, applied))
71
+ return { status: "ready", retainExternal: true };
72
+ return {
73
+ status: "restart_required",
74
+ message: "Configuration saved. An existing model gateway owns this address; restart that gateway to load its new configuration.",
75
+ };
59
76
  }
60
77
  captureGatewayCheckpoint() {
61
78
  this.requireGatewayOpen();
@@ -135,15 +152,18 @@ export class RuntimeSetupGateway {
135
152
  this.owned = undefined;
136
153
  throw error;
137
154
  }
138
- activate(configPath) {
155
+ activate(configPath, applied) {
139
156
  return this.runGatewayTransition(async () => {
140
157
  const checkpoint = this.captureGatewayCheckpoint();
141
158
  this.checkpoint = undefined;
142
159
  try {
143
- const allowed = await this.checkActivation(configPath);
160
+ const allowed = await this.planActivation(configPath, applied);
144
161
  this.requireGatewayOpen();
145
162
  if (allowed.status !== "ready")
146
163
  return allowed;
164
+ // Unchanged requirements do not grant ownership of the external listener.
165
+ if (allowed.retainExternal)
166
+ return { status: "ready" };
147
167
  const { host, port } = this.configuredBinding(configPath);
148
168
  const server = createModelGatewayServer({
149
169
  ...this.options,
@@ -148,7 +148,8 @@ export function startWebUiServer(overrides = {}) {
148
148
  rootDir,
149
149
  providerAdapters: options.providerAdapters,
150
150
  });
151
- const activateSetup = overrides.onRuntimeSetup ?? ((path) => setupGateway.activate(path));
151
+ const activateSetup = overrides.onRuntimeSetup ??
152
+ ((path, applied) => setupGateway.activate(path, applied));
152
153
  const wss = new WebSocketServer({ noServer: true });
153
154
  const localRuntimeBackend = options.backend === "runtime"
154
155
  ? new LocalRuntimeWebBackend({
@@ -168,6 +169,9 @@ export function startWebUiServer(overrides = {}) {
168
169
  };
169
170
  },
170
171
  onRuntimeSetup: activateSetup,
172
+ captureRuntimeSetupConfiguration: overrides.onRuntimeSetup
173
+ ? undefined
174
+ : (path) => setupGateway.captureConfiguration(path),
171
175
  createRuntimeSetupRestorePoint: overrides.createRuntimeSetupRestorePoint ??
172
176
  (overrides.onRuntimeSetup
173
177
  ? undefined
@@ -175,7 +179,7 @@ export function startWebUiServer(overrides = {}) {
175
179
  checkRuntimeSetupActivation: overrides.checkRuntimeSetupActivation ??
176
180
  (overrides.onRuntimeSetup
177
181
  ? undefined
178
- : (path) => setupGateway.checkActivation(path)),
182
+ : (path, applied) => setupGateway.checkActivation(path, applied)),
179
183
  ...(options.providerAdapters
180
184
  ? { providerAdapters: options.providerAdapters }
181
185
  : {}),