@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,108 @@
1
+ import { escapeAttribute, escapeHtml } from "../../lib/text-format.js";
2
+
3
+ function renderSetting(name, value, fallback, index, overridden) {
4
+ const attribute = `data-plugin-setting="${index}" data-plugin-setting-overridden="${overridden}"`;
5
+ if (typeof fallback === "boolean")
6
+ return `<label class="plugin-setting-checkbox"><input type="checkbox" ${attribute} ${value ? "checked" : ""}><span>${escapeHtml(name)}</span></label>`;
7
+ if (typeof fallback === "number")
8
+ return `<label><span>${escapeHtml(name)}</span><input type="number" step="any" ${attribute} value="${escapeAttribute(String(value))}" required></label>`;
9
+ if (typeof fallback === "string")
10
+ return `<label><span>${escapeHtml(name)}</span><input type="text" ${attribute} value="${escapeAttribute(String(value))}" autocomplete="off"></label>`;
11
+ return `<label><span>${escapeHtml(name)} <small>JSON</small></span><textarea ${attribute} rows="4" spellcheck="false">${escapeHtml(JSON.stringify(value, null, 2))}</textarea></label>`;
12
+ }
13
+
14
+ export function renderPluginSettings(configuration) {
15
+ return Object.entries(configuration.defaults || {})
16
+ .map(([name, fallback], index) => {
17
+ const overridden = (configuration.settingOverrides || []).includes(name);
18
+ return `<div class="plugin-setting-field">
19
+ ${renderSetting(name, configuration.settings[name], fallback, index, overridden)}
20
+ <div class="plugin-setting-source"><small data-plugin-setting-origin="${index}">${overridden ? "Local value" : "Plugin default"}</small><button type="button" data-plugin-setting-default="${index}" data-plugin-setting-default-value="${escapeAttribute(JSON.stringify(fallback))}" aria-label="${escapeAttribute(`Use plugin default for ${name}`)}">Use plugin default</button></div>
21
+ </div>`;
22
+ })
23
+ .join("");
24
+ }
25
+
26
+ function markPluginSettingSource(root, input, overridden) {
27
+ input.dataset.pluginSettingOverridden = String(overridden);
28
+ const status = root.querySelector(
29
+ `[data-plugin-setting-origin="${input.dataset.pluginSetting}"]`,
30
+ );
31
+ if (status)
32
+ status.textContent = overridden ? "Local value" : "Plugin default";
33
+ }
34
+
35
+ function restorePluginSettingDefault(input, fallback) {
36
+ if (typeof fallback === "boolean") {
37
+ input.checked = fallback;
38
+ return;
39
+ }
40
+ if (typeof fallback === "object") {
41
+ input.value = JSON.stringify(fallback, null, 2);
42
+ return;
43
+ }
44
+ input.value = String(fallback);
45
+ }
46
+
47
+ export function bindPluginSettingFields(root, onChange) {
48
+ for (const input of root.querySelectorAll("[data-plugin-setting]")) {
49
+ input.addEventListener("input", () =>
50
+ markPluginSettingSource(root, input, true),
51
+ );
52
+ }
53
+ for (const button of root.querySelectorAll("[data-plugin-setting-default]")) {
54
+ button.addEventListener("click", () => {
55
+ const input = root.querySelector(
56
+ `[data-plugin-setting="${button.dataset.pluginSettingDefault}"]`,
57
+ );
58
+ if (!input) return;
59
+ const usesPluginDefault =
60
+ input.dataset.pluginSettingOverridden === "false";
61
+ if (usesPluginDefault) return;
62
+ const fallback = JSON.parse(button.dataset.pluginSettingDefaultValue);
63
+ restorePluginSettingDefault(input, fallback);
64
+ markPluginSettingSource(root, input, false);
65
+ onChange();
66
+ });
67
+ }
68
+ }
69
+
70
+ function readSetting(input, fallback, name) {
71
+ if (typeof fallback === "boolean") return input.checked;
72
+ if (typeof fallback === "string") return input.value;
73
+ if (typeof fallback === "number") {
74
+ if (!input.value.trim() || !Number.isFinite(Number(input.value)))
75
+ throw new Error(`Enter a number for ${name}.`);
76
+ return Number(input.value);
77
+ }
78
+ try {
79
+ return JSON.parse(input.value);
80
+ } catch {
81
+ throw new Error(`Enter valid JSON for ${name}.`);
82
+ }
83
+ }
84
+
85
+ function hasPluginSettingOverride(input, configuration, name) {
86
+ const edited = input?.dataset?.pluginSettingOverridden;
87
+ if (edited !== undefined) return edited === "true";
88
+ return (configuration.settingOverrides || []).includes(name);
89
+ }
90
+
91
+ export function readPluginSettingOverrides(root, configuration) {
92
+ return Object.fromEntries(
93
+ Object.entries(configuration.defaults || {}).flatMap(
94
+ ([name, fallback], index) => {
95
+ const input = root?.querySelector(`[data-plugin-setting="${index}"]`);
96
+ if (!hasPluginSettingOverride(input, configuration, name)) return [];
97
+ return [
98
+ [
99
+ name,
100
+ input
101
+ ? readSetting(input, fallback, name)
102
+ : configuration.settings[name],
103
+ ],
104
+ ];
105
+ },
106
+ ),
107
+ );
108
+ }
@@ -0,0 +1,37 @@
1
+ import { renderPluginConfigurationFields } from "./configuration-fields.js";
2
+ import { escapeAttribute, escapeHtml } from "../../lib/text-format.js";
3
+
4
+ function renderPluginReview(review, busy) {
5
+ if (!review) return "";
6
+ const installButton = `<button type="button" class="primary-button" data-plugin-install-confirm ${busy ? "disabled" : ""}>${busy ? "Installing…" : "Install and enable"}</button>`;
7
+ return `<section class="plugin-install-review" aria-label="Plugin installation review">
8
+ <header class="plugin-install-heading"><div><h3>${escapeHtml(review.id)} ${review.version ? `<small>v${escapeHtml(review.version)}</small>` : ""}</h3><p>Not installed yet.</p></div>${installButton}</header>
9
+ <p>${escapeHtml(review.description)}</p>
10
+ <dl><dt>Source</dt><dd>${escapeHtml(review.source.repository)}</dd><dt>Commit</dt><dd><code>${escapeHtml(review.source.ref)}</code></dd></dl>
11
+ <ul class="plugin-install-capabilities">${review.capabilities.map((capability) => `<li><strong>${escapeHtml(capability.id)}</strong><p>${escapeHtml(capability.description)}</p><span>${capability.operations.map((operation) => escapeHtml(`${operation.name} · ${operation.effect}`)).join(" / ")}</span></li>`).join("")}</ul>
12
+ ${renderPluginConfigurationFields(review.configuration, busy)}
13
+ <p class="plugin-install-trust">This plugin contains code that runs with the Runtime's access. Install it only if you trust its publisher. Installation does not run a build or setup script.</p>
14
+ ${installButton}
15
+ <button type="button" data-plugin-review-cancel ${busy ? "disabled" : ""}>Cancel review</button>
16
+ </section>`;
17
+ }
18
+
19
+ export function renderPluginDiscovery(state) {
20
+ return `<section class="plugin-discovery" aria-label="Discover plugins" aria-busy="${state.busy}">
21
+ <article class="plugin-marketplace-card"><h2>More tools. More possibilities.</h2>
22
+ <p>Discover plugins shared by the community and extend what your agent can do.</p>
23
+ <a href="https://abot-ai.com/marketplace/" target="_blank" rel="noopener noreferrer">Browse Marketplace ↗</a>
24
+ </article>
25
+ <section class="plugin-source-card"><h2>Install from GitHub</h2>
26
+ <p>Paste a public repository link. With Computer Access, an Install in ABot link opens this review directly.</p>
27
+ <form data-plugin-source-form>
28
+ <label><span>Repository URL</span><input name="repository" type="url" autocomplete="off" placeholder="https://github.com/owner/plugin" value="${escapeAttribute(state.source.repository)}" required ${state.busy ? "disabled" : ""}></label>
29
+ <div class="plugin-source-options"><label><span>Revision <small>(optional)</small></span><input name="ref" autocomplete="off" placeholder="Branch, tag or commit" value="${escapeAttribute(state.source.ref || "")}" ${state.busy ? "disabled" : ""}></label>
30
+ <label><span>Plugin folder <small>(optional)</small></span><input name="path" autocomplete="off" placeholder="Repository root" value="${escapeAttribute(state.source.path || "")}" ${state.busy ? "disabled" : ""}></label></div>
31
+ <button type="submit" ${state.busy ? "disabled" : ""}>${state.busy ? "Working…" : "Review plugin"}</button>
32
+ </form>
33
+ <p data-plugin-install-status class="${state.error ? "error-text" : ""}" role="${state.error ? "alert" : "status"}" aria-live="polite">${escapeHtml(state.error || state.message)}</p>
34
+ ${renderPluginReview(state.review, state.busy)}
35
+ </section>
36
+ </section>`;
37
+ }
@@ -0,0 +1,212 @@
1
+ import { createPluginConfigurationDraft } from "./configuration-draft.js";
2
+ import {
3
+ bindPluginConfigurationFields,
4
+ clearPluginSecretInputs,
5
+ readPluginConfigurationFields,
6
+ } from "./configuration-fields.js";
7
+ /** The review is tied to exact bytes and the currently selected environment. */
8
+ export function createPluginInstallation({
9
+ inspectPlugin,
10
+ installPlugin,
11
+ getEnvironmentId,
12
+ beginRuntimeMutation,
13
+ endRuntimeMutation,
14
+ refreshRuntimeConfig,
15
+ onConfigurationSaved,
16
+ onInstalled,
17
+ render,
18
+ }) {
19
+ const state = {
20
+ source: { repository: "", ref: "", path: "" },
21
+ review: null,
22
+ installedPluginId: null,
23
+ dirty: false,
24
+ busy: false,
25
+ error: "",
26
+ message: "",
27
+ };
28
+ const draft = createPluginConfigurationDraft();
29
+ let generation = 0;
30
+ let mountedRoot = null;
31
+ let environment = getEnvironmentId();
32
+
33
+ function resetEnvironment() {
34
+ if (environment === getEnvironmentId()) return;
35
+ environment = getEnvironmentId();
36
+ generation += 1;
37
+ state.dirty = false;
38
+ state.review = null;
39
+ state.installedPluginId = null;
40
+ state.busy = false;
41
+ state.error = "";
42
+ state.message = "";
43
+ }
44
+
45
+ function isCurrentInstallationRequest(request, selected) {
46
+ return request === generation && selected === getEnvironmentId();
47
+ }
48
+
49
+ async function inspect(source = state.source) {
50
+ resetEnvironment();
51
+ if (state.busy || !inspectPlugin) return false;
52
+ state.source = { ...source };
53
+ state.dirty = false;
54
+ state.review = null;
55
+ state.installedPluginId = null;
56
+ state.error = "";
57
+ state.message = "";
58
+ state.busy = true;
59
+ const request = ++generation;
60
+ const selected = environment;
61
+ render();
62
+ try {
63
+ const result = await inspectPlugin(state.source, selected);
64
+ if (!isCurrentInstallationRequest(request, selected)) return false;
65
+ state.review = result.review;
66
+ return true;
67
+ } catch (error) {
68
+ if (isCurrentInstallationRequest(request, selected))
69
+ state.error = error.message || String(error);
70
+ return false;
71
+ } finally {
72
+ if (isCurrentInstallationRequest(request, selected)) {
73
+ state.busy = false;
74
+ render();
75
+ }
76
+ }
77
+ }
78
+
79
+ async function install(fields) {
80
+ resetEnvironment();
81
+ if (state.busy || !state.review || !installPlugin) return false;
82
+ let configuration;
83
+ try {
84
+ if (state.review.configuration)
85
+ configuration = readPluginConfigurationFields(
86
+ fields,
87
+ state.review.configuration,
88
+ true,
89
+ );
90
+ } catch (error) {
91
+ state.error = error.message;
92
+ const status = mountedRoot?.querySelector("[data-plugin-install-status]");
93
+ if (status) status.textContent = state.error;
94
+ return false;
95
+ }
96
+ if (!beginRuntimeMutation("plugin installation")) return false;
97
+ if (configuration) {
98
+ state.review.configuration.settings = {
99
+ ...state.review.configuration.defaults,
100
+ ...configuration.settings,
101
+ };
102
+ state.review.configuration.settingOverrides = Object.keys(
103
+ configuration.settings,
104
+ );
105
+ }
106
+ clearPluginSecretInputs(fields);
107
+ const review = state.review;
108
+ const selected = environment;
109
+ const request = ++generation;
110
+ state.busy = true;
111
+ state.error = "";
112
+ let installed = false;
113
+ render();
114
+ try {
115
+ const result = await installPlugin(
116
+ {
117
+ source: review.source,
118
+ digest: review.digest,
119
+ ...(configuration ? { configuration } : {}),
120
+ },
121
+ selected,
122
+ );
123
+ installed = true;
124
+ if (!isCurrentInstallationRequest(request, selected)) return false;
125
+ state.dirty = false;
126
+ state.review = null;
127
+ state.installedPluginId = review.id;
128
+ state.message = `${review.id} installed. Apply changes to make it available.`;
129
+ onInstalled(result);
130
+ onConfigurationSaved();
131
+ const refreshed = await refreshRuntimeConfig(
132
+ "Plugin installed; refresh required",
133
+ );
134
+ if (!isCurrentInstallationRequest(request, selected)) return false;
135
+ if (!refreshed)
136
+ state.message =
137
+ "Plugin installed. Refresh configuration before applying changes.";
138
+ return true;
139
+ } catch (error) {
140
+ if (isCurrentInstallationRequest(request, selected))
141
+ state.error =
142
+ (installed
143
+ ? "Plugin installed; configuration refresh failed: "
144
+ : "") + (error.message || String(error));
145
+ return false;
146
+ } finally {
147
+ configuration = undefined;
148
+ endRuntimeMutation();
149
+ if (isCurrentInstallationRequest(request, selected)) {
150
+ state.busy = false;
151
+ render();
152
+ }
153
+ }
154
+ }
155
+
156
+ function bind(root) {
157
+ mountedRoot = root;
158
+ draft.restore(root, state.review, state.busy);
159
+ const form = root.querySelector("[data-plugin-source-form]");
160
+ form?.addEventListener("submit", (event) => {
161
+ event.preventDefault();
162
+ void inspect({
163
+ repository: form.elements.repository.value.trim(),
164
+ ref: form.elements.ref.value.trim(),
165
+ path: form.elements.path.value.trim(),
166
+ });
167
+ });
168
+ form?.addEventListener("input", () => {
169
+ state.source = {
170
+ repository: form.elements.repository.value,
171
+ ref: form.elements.ref.value,
172
+ path: form.elements.path.value,
173
+ };
174
+ if (!state.review) return;
175
+ draft.clear();
176
+ state.dirty = false;
177
+ state.review = null;
178
+ root.querySelector(".plugin-install-review")?.remove();
179
+ });
180
+ const fields = root.querySelector("[data-plugin-configuration-fields]");
181
+ bindPluginConfigurationFields(fields, () => {
182
+ state.dirty = true;
183
+ });
184
+ root
185
+ .querySelector("[data-plugin-review-cancel]")
186
+ ?.addEventListener("click", () => {
187
+ clearPluginSecretInputs(fields);
188
+ state.review = null;
189
+ state.dirty = false;
190
+ state.error = "";
191
+ render();
192
+ });
193
+ for (const button of root.querySelectorAll("[data-plugin-install-confirm]"))
194
+ button.addEventListener("click", () => void install(fields));
195
+ }
196
+
197
+ function markApplied() {
198
+ resetEnvironment();
199
+ if (state.message)
200
+ state.message = "Plugin installation applied to this environment.";
201
+ }
202
+
203
+ return {
204
+ state,
205
+ bind,
206
+ inspect,
207
+ install,
208
+ resetEnvironment,
209
+ markApplied,
210
+ captureFields: (root) => draft.capture(root, state.review, state.busy),
211
+ };
212
+ }
@@ -1,8 +1,22 @@
1
+ import { createPluginConfigurationEditor } from "./configuration-editor.js";
2
+ import { createPluginRemoval } from "./removal.js";
1
3
  import { renderPluginManager } from "./rendering.js";
2
4
  import { createPluginViewState } from "./view-state.js";
5
+ import { createPluginInstallation } from "./installation.js";
6
+ import { renderPluginTabs, bindPluginTabs } from "./tabs.js";
7
+ import { projectPluginSummary } from "./summary.js";
3
8
 
4
9
  export function createPluginManager({
5
10
  loadPlugins,
11
+ loadConfiguration,
12
+ saveConfiguration,
13
+ inspectPlugin,
14
+ installPlugin,
15
+ removePlugin,
16
+ confirmRemoval,
17
+ onConfigurationApplied = async () => {},
18
+ onConfigurationSettled = () => true,
19
+ onNavigationChange = () => {},
6
20
  getEnvironmentId = () => "",
7
21
  setPlugin,
8
22
  beginRuntimeMutation = () => true,
@@ -10,10 +24,12 @@ export function createPluginManager({
10
24
  endRuntimeMutation = () => {},
11
25
  recordControlEvent = () => {},
12
26
  onConfigurationSaved = () => {},
27
+ onSummaryChange = () => {},
13
28
  }) {
14
29
  const viewState = createPluginViewState();
15
30
  const state = {
16
31
  root: null,
32
+ activeTab: "installed",
17
33
  snapshot: null,
18
34
  busy: false,
19
35
  message: "",
@@ -23,13 +39,116 @@ export function createPluginManager({
23
39
  environmentId: getEnvironmentId(),
24
40
  };
25
41
 
42
+ const configurationEditor = createPluginConfigurationEditor({
43
+ loadConfiguration,
44
+ saveConfiguration,
45
+ getEnvironmentId,
46
+ beginRuntimeMutation,
47
+ endRuntimeMutation,
48
+ onConfigurationSaved,
49
+ onClosed: onConfigurationSettled,
50
+ });
51
+
52
+ const installation = createPluginInstallation({
53
+ inspectPlugin,
54
+ installPlugin,
55
+ getEnvironmentId,
56
+ beginRuntimeMutation,
57
+ endRuntimeMutation,
58
+ refreshRuntimeConfig,
59
+ onConfigurationSaved,
60
+ onInstalled: (snapshot) => {
61
+ state.snapshot = snapshot;
62
+ state.error = "";
63
+ state.message = "";
64
+ removal.state.message = "";
65
+ removal.state.error = "";
66
+ activateTab("installed", true);
67
+ },
68
+ render,
69
+ });
70
+
71
+ const removal = createPluginRemoval({
72
+ removePlugin,
73
+ confirmRemoval,
74
+ getEnvironmentId,
75
+ beginRuntimeMutation,
76
+ endRuntimeMutation,
77
+ refreshRuntimeConfig,
78
+ onConfigurationSaved,
79
+ onConfigurationApplied,
80
+ onConfigurationSettled,
81
+ render,
82
+ onSnapshot: (snapshot) => {
83
+ state.snapshot = snapshot;
84
+ },
85
+ });
86
+
87
+ async function remove(pluginId) {
88
+ if (state.busy || installation.state.busy || removal.state.busy)
89
+ return false;
90
+ if (
91
+ !state.snapshot?.plugins?.some(
92
+ (plugin) => plugin.id === pluginId && plugin.removable,
93
+ )
94
+ )
95
+ return false;
96
+ installation.state.installedPluginId = null;
97
+ state.message = "";
98
+ state.error = "";
99
+ return removal.remove(pluginId);
100
+ }
101
+
102
+ function activateTab(name, focus = false) {
103
+ if (!["installed", "discover"].includes(name)) return;
104
+ if (installation.state.dirty && name !== state.activeTab) return;
105
+ state.activeTab = name;
106
+ render();
107
+ if (focus)
108
+ state.root?.querySelector(`[data-plugin-tab="${name}"]`)?.focus();
109
+ onNavigationChange();
110
+ }
111
+
26
112
  function render({ capture = true } = {}) {
113
+ installation.resetEnvironment();
114
+ removal.resetEnvironment();
115
+ onSummaryChange();
27
116
  if (!state.root) return;
28
117
  if (capture) viewState.capture(state.root);
29
- state.root.innerHTML = renderPluginManager({
30
- ...state,
31
- openPluginIds: viewState.openPluginIds,
32
- });
118
+ installation.captureFields(state.root);
119
+ state.root.innerHTML = renderPluginTabs(
120
+ renderPluginManager({
121
+ ...state,
122
+ busy: state.busy || installation.state.busy || removal.state.busy,
123
+ canRemove: typeof removePlugin === "function",
124
+ canConfigure: typeof loadConfiguration === "function",
125
+ message:
126
+ removal.state.message ||
127
+ (installation.state.installedPluginId
128
+ ? installation.state.message
129
+ : state.message),
130
+ error:
131
+ state.error ||
132
+ removal.state.error ||
133
+ (installation.state.installedPluginId
134
+ ? installation.state.error
135
+ : ""),
136
+ openPluginIds: viewState.openPluginIds,
137
+ }),
138
+ installation.state,
139
+ state.activeTab,
140
+ );
141
+ for (const button of state.root.querySelectorAll("[data-plugin-configure]"))
142
+ button.addEventListener(
143
+ "click",
144
+ () =>
145
+ void configurationEditor.open(
146
+ button.dataset.pluginConfigure,
147
+ state.root,
148
+ ),
149
+ );
150
+ bindPluginTabs(state.root, activateTab);
151
+ installation.bind(state.root);
33
152
  viewState.bind(state.root, () => render({ capture: false }));
34
153
  state.root
35
154
  .querySelector("[data-plugin-refresh]")
@@ -53,7 +172,15 @@ export function createPluginManager({
53
172
  ),
54
173
  );
55
174
  }
56
- viewState.restore(state.root, state.busy);
175
+ for (const button of state.root.querySelectorAll("[data-plugin-remove]"))
176
+ button.addEventListener(
177
+ "click",
178
+ () => void remove(button.dataset.pluginRemove),
179
+ );
180
+ viewState.restore(
181
+ state.root,
182
+ state.busy || installation.state.busy || removal.state.busy,
183
+ );
57
184
  }
58
185
 
59
186
  function mount(root) {
@@ -104,6 +231,7 @@ export function createPluginManager({
104
231
  }
105
232
 
106
233
  function markApplied() {
234
+ installation.markApplied();
107
235
  state.message = "Plugin selection applied to this environment.";
108
236
  state.error = "";
109
237
  render();
@@ -124,7 +252,8 @@ export function createPluginManager({
124
252
  }
125
253
 
126
254
  async function toggle(pluginId, enabled, capabilityId) {
127
- if (state.busy) return false;
255
+ if (state.busy || installation.state.busy || removal.state.busy)
256
+ return false;
128
257
  if (!canChangePluginSelection(pluginId, capabilityId)) return false;
129
258
  if (!beginRuntimeMutation("plugin settings")) {
130
259
  render();
@@ -136,6 +265,9 @@ export function createPluginManager({
136
265
  state.busy = true;
137
266
  state.error = "";
138
267
  state.message = "";
268
+ installation.state.installedPluginId = null;
269
+ removal.state.message = "";
270
+ removal.state.error = "";
139
271
  let saved = false;
140
272
  render();
141
273
  try {
@@ -190,10 +322,32 @@ export function createPluginManager({
190
322
  }
191
323
 
192
324
  return {
325
+ summary: () =>
326
+ projectPluginSummary(
327
+ {
328
+ ...state,
329
+ busy: state.busy || installation.state.busy || removal.state.busy,
330
+ },
331
+ getEnvironmentId(),
332
+ ),
333
+ hasConfigurationDraft: () =>
334
+ configurationEditor.isOpen() || installation.state.dirty,
335
+ activeTab: () => state.activeTab,
336
+ openRoute: (route) => {
337
+ activateTab(route.pluginSource ? "discover" : route.tab || "installed");
338
+ if (!route.pluginSource) return true;
339
+ void installation.inspect({
340
+ repository: route.pluginSource,
341
+ ref: route.pluginRef || "",
342
+ path: route.pluginPath || "",
343
+ });
344
+ return true;
345
+ },
193
346
  load,
194
347
  markApplied,
195
348
  mount,
196
349
  toggle,
350
+ remove,
197
351
  toggleCapability: (pluginId, capabilityId, enabled) =>
198
352
  toggle(pluginId, enabled, capabilityId),
199
353
  };