@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,293 @@
1
+ import { escapeHtml } from "../../lib/text-format.js";
2
+ import { renderConnectionCard, renderComputerMetadata } from "./connection-card.js";
3
+
4
+ const companionStoreUrl = "https://apps.microsoft.com/detail/9PK2FDQQLQS9";
5
+
6
+ export function windowsStoreSetupIsAvailable(snapshot) {
7
+ const readiness = snapshot?.readiness;
8
+ if (readiness?.ready === true) return false;
9
+ if (!readiness?.platforms?.includes("windows")) return false;
10
+ if (readiness.restartRequired === true) return false;
11
+ return ["setup_required", "companion"].includes(readiness.route);
12
+ }
13
+
14
+ export function windowsStorePanelIsAvailable(snapshot) {
15
+ if (windowsStoreSetupIsAvailable(snapshot)) return true;
16
+ if (snapshot?.readiness?.restartRequired === true) return false;
17
+ if (snapshot?.readiness?.route !== "companion") return false;
18
+ if (snapshot.readiness.ready !== true) return false;
19
+ return snapshot.identity?.os === "windows";
20
+ }
21
+
22
+ function windowsCompanionCanReconnect(snapshot) {
23
+ if (!windowsStoreSetupIsAvailable(snapshot)) return false;
24
+ if (snapshot?.paired !== true) return false;
25
+ return snapshot.connected === false;
26
+ }
27
+
28
+ function hasConfirmedUnpairedConnection(snapshot) {
29
+ if (snapshot?.ok === false) return false;
30
+ if (snapshot?.paired !== false) return false;
31
+ return snapshot.connected === false;
32
+ }
33
+
34
+ function storeInvitationIsCurrent(invitation) {
35
+ if (!invitation) return false;
36
+ return Date.parse(invitation.expiresAt) > Date.now();
37
+ }
38
+
39
+ function storeRepairConfirmationIsCurrent(snapshot, attempt) {
40
+ if (!windowsCompanionCanReconnect(snapshot)) return false;
41
+ return attempt?.phase === "confirm-repair";
42
+ }
43
+
44
+ function storeConnectionStage(snapshot, invitation, attempt) {
45
+ if (snapshot?.readiness?.ready === true) return "ready";
46
+ if (attempt?.phase === "repairing") return "repairing";
47
+ if (storeRepairConfirmationIsCurrent(snapshot, attempt)) return "confirm-repair";
48
+ if (windowsCompanionCanReconnect(snapshot)) return "reconnect";
49
+ if (attempt?.expiresAt && Date.parse(attempt.expiresAt) <= Date.now()) return "expired";
50
+ if (attempt?.phase === "preparing") return "preparing";
51
+ if (attempt?.phase === "waiting") return "waiting";
52
+ if (storeInvitationIsCurrent(invitation)) return "open";
53
+ if (attempt?.phase === "expired") return "expired";
54
+ return "start";
55
+ }
56
+
57
+ function connectionButton(label, disabled, secondary = false) {
58
+ return `<button type="button" class="system-host-card-${secondary ? "secondary" : "primary"}" data-system-host-store-connect ${disabled ? "disabled" : ""}>${label}</button>`;
59
+ }
60
+
61
+ function companionLaunchLink(invitation, secondary = false) {
62
+ return `<a class="system-host-card-${secondary ? "secondary" : "primary"}" href="${escapeHtml(invitation.launchUrl)}" data-system-host-store-launch rel="noreferrer">${secondary ? "Open Companion again" : "Open Companion"}</a>`;
63
+ }
64
+
65
+ function connectionStageContent(stage, snapshot, invitation, disabled) {
66
+ if (stage === "ready") return {
67
+ status: "Connected", step: "Your computer is ready", copy: "You can use computer tools from your ABot chat.",
68
+ };
69
+ if (stage === "reconnect") return {
70
+ status: "Offline", step: "Your computer is offline", copy: `Open Companion on ${snapshot?.identity?.name || "your computer"} to reconnect.`,
71
+ action: `<a class="system-host-card-primary" href="abot-companion://open" data-system-host-store-open-existing rel="noreferrer">Open Companion</a><button type="button" class="system-host-card-secondary" data-system-host-store-repair ${disabled ? "disabled" : ""}>Set up again</button>`,
72
+ help: "Removed the connection in Companion? Choose Set up again.",
73
+ };
74
+ if (stage === "confirm-repair") return {
75
+ status: "Confirm reset", step: "Set up this computer again?", copy: "The previous connection will be removed. You’ll approve a new connection in Companion.",
76
+ action: `<button type="button" class="system-host-card-primary" data-system-host-store-repair-confirm ${disabled ? "disabled" : ""}>Continue</button><button type="button" class="system-host-card-secondary" data-system-host-store-repair-cancel ${disabled ? "disabled" : ""}>Cancel</button>`,
77
+ help: "Your conversations and saved insights will be kept.",
78
+ };
79
+ if (stage === "repairing") return {
80
+ status: "Preparing", step: "Setting up this computer again", copy: "Removing the previous connection before preparing your new connection…",
81
+ action: '<button type="button" class="system-host-card-primary" disabled>Preparing connection…</button>',
82
+ };
83
+ if (stage === "preparing") return {
84
+ status: "Preparing", step: "Connect your Windows computer", copy: "Preparing your connection…",
85
+ action: connectionButton("Preparing connection…", true),
86
+ };
87
+ if (stage === "open") return {
88
+ status: "Waiting for you", step: "Approve the connection in Companion", copy: "Open the app and check the ABot address. This page will confirm when your computer is connected.",
89
+ action: companionLaunchLink(invitation),
90
+ help: "Your browser may ask permission to open the app.",
91
+ };
92
+ if (stage === "waiting") return {
93
+ status: "Waiting for approval", step: "Approve the connection in Companion", copy: "Check the ABot address and approve the connection in the app. This page will confirm when your computer is connected.",
94
+ help: "If Companion did not open, use the option below.",
95
+ action: storeInvitationIsCurrent(invitation)
96
+ ? companionLaunchLink(invitation, true)
97
+ : connectionButton("Start connection again", disabled, true),
98
+ };
99
+ if (stage === "expired") return {
100
+ status: "Expired", step: "Connection link expired", copy: "Connect again to get a fresh invitation.",
101
+ action: connectionButton("Connect again", disabled),
102
+ };
103
+ const update = snapshot?.readiness?.companionUpdateRequired === true;
104
+ return {
105
+ status: update ? "Update needed" : "Not connected",
106
+ step: update ? "Update Companion" : "Connect your Windows computer",
107
+ copy: update ? "Update Companion from Microsoft Store, then return here to reconnect."
108
+ : "Companion lets ABot work with files, apps and desktop tools on this computer.",
109
+ action: `<a class="system-host-card-primary" href="${companionStoreUrl}" target="_blank" rel="noopener noreferrer"><svg class="system-host-store-icon" width="18" height="18" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M4 7h16v14H4ZM8 7V5a4 4 0 0 1 8 0v2" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M8 10h3v3H8Zm5 0h3v3h-3Zm-5 5h3v3H8Zm5 0h3v3h-3Z" fill="currentColor"/></svg><span>${update ? "Update in Microsoft Store" : "Install from Microsoft Store"}</span></a>${connectionButton(update ? "I already updated it" : "I already have it", disabled, true)}`,
110
+ help: update ? "Your saved connection is kept during an update." : "Install once from Microsoft Store, then return here to connect.",
111
+ };
112
+ }
113
+
114
+ function storeConnectionDisplayContent(stage, snapshot, invitation, disabled, statusUnavailable) {
115
+ if (statusUnavailable) return {
116
+ status: "Status unavailable", step: "Check your computer connection",
117
+ copy: "The current connection status could not be checked. Refresh to try again.",
118
+ };
119
+ if (disabled && stage === "ready") return {
120
+ status: "Checking", step: "Checking your computer connection",
121
+ copy: "Waiting for the current connection status…",
122
+ };
123
+ return connectionStageContent(stage, snapshot, invitation, disabled);
124
+ }
125
+
126
+ function shouldRenderReadyWindowsSummary(compact, ready, error, message, otherSetup) {
127
+ if (!compact || !ready) return false;
128
+ if (error || message || otherSetup) return false;
129
+ return true;
130
+ }
131
+
132
+ export function renderWindowsStoreSetup({ snapshot, invitation, attempt, disabled, statusUnavailable, error, message, compact, otherSetup = "" }) {
133
+ if (!windowsStorePanelIsAvailable(snapshot)) return "";
134
+ const stage = storeConnectionStage(snapshot, invitation, attempt);
135
+ const content = storeConnectionDisplayContent(stage, snapshot, invitation, disabled, statusUnavailable);
136
+ const ready = stage === "ready" && !statusUnavailable && !disabled;
137
+ const summary = shouldRenderReadyWindowsSummary(compact, ready, error, message, otherSetup);
138
+ const refresh = statusUnavailable || error ? '<button type="button" class="system-host-card-secondary" data-system-host-refresh' + (disabled ? " disabled" : "") + '>Refresh status</button>' : "";
139
+ return renderConnectionCard({
140
+ title: content.step, status: content.status, ready, disabled,
141
+ compact: summary,
142
+ description: content.copy, actions: content.action, help: content.help, error, message,
143
+ metadata: ["ready", "reconnect"].includes(stage) ? renderComputerMetadata(snapshot, disabled) : "",
144
+ details: summary ? "" : (ready ? '<p class="system-host-card-access-note">Computer actions follow your permission settings. Spark collection is managed separately.</p>' : "") + refresh + otherSetup,
145
+ attributes: `data-system-host-store-setup data-system-host-store-stage="${stage}"`,
146
+ });
147
+ }
148
+
149
+ function readStoreInvitation(receipt) {
150
+ if (!storeInvitationIsCurrent(receipt)) throw new Error("store_invitation_expired");
151
+ const launch = new URL(receipt.launchUrl);
152
+ if (launch.protocol !== "abot-companion:") throw new Error("store_invitation_invalid");
153
+ if (launch.hostname !== "connect") throw new Error("store_invitation_invalid");
154
+ if (launch.username || launch.password || launch.port || launch.hash) throw new Error("store_invitation_invalid");
155
+ if (launch.pathname !== "" && launch.pathname !== "/") throw new Error("store_invitation_invalid");
156
+ if (!/^[A-Za-z0-9_-]+$/.test(launch.searchParams.get("invitation") || "")) throw new Error("store_invitation_invalid");
157
+ if (receipt.storeUrl !== companionStoreUrl) throw new Error("store_invitation_invalid");
158
+ return { launchUrl: launch.href, expiresAt: receipt.expiresAt };
159
+ }
160
+
161
+ /** The invitation exists only on the active surface, until readiness or expiry. */
162
+ export function createWindowsStoreConnectionActions({
163
+ state,
164
+ requestStoreConnection,
165
+ revokeConnection,
166
+ receiveUnpairedConnection,
167
+ canInstallOnPlatform,
168
+ beginRequest,
169
+ finishRequest,
170
+ isCurrentResponse,
171
+ getSurfaceRevision,
172
+ getEnvironmentId = () => "",
173
+ isVisible,
174
+ notify,
175
+ scheduleExpiration = setTimeout,
176
+ cancelExpiration = clearTimeout,
177
+ }) {
178
+ let expirationTimer;
179
+ function clear({ preserveWaiting = false } = {}) {
180
+ if (expirationTimer !== undefined) cancelExpiration(expirationTimer);
181
+ expirationTimer = undefined;
182
+ if (state.windowsStoreInvitation) state.message = "";
183
+ state.windowsStoreInvitation = null;
184
+ if (preserveWaiting && state.windowsStoreAttempt?.phase === "waiting") return;
185
+ state.windowsStoreAttempt = null;
186
+ }
187
+ function canApplyStoreResponse(operation, surface, environment) {
188
+ if (!isCurrentResponse(operation)) return false;
189
+ if (surface !== getSurfaceRevision()) return false;
190
+ if (environment !== getEnvironmentId()) return false;
191
+ return isVisible();
192
+ }
193
+ function receiveStoreInvitation(receipt) {
194
+ state.windowsStoreInvitation = readStoreInvitation(receipt);
195
+ state.windowsStoreAttempt = { phase: "open", expiresAt: receipt.expiresAt };
196
+ state.downloaded = null;
197
+ state.manualMac = null;
198
+ state.message = "";
199
+ expirationTimer = scheduleExpiration(() => {
200
+ clear();
201
+ state.windowsStoreAttempt = { phase: "expired" };
202
+ notify();
203
+ }, Date.parse(receipt.expiresAt) - Date.now());
204
+ }
205
+ async function connectWindowsStore() {
206
+ if (typeof requestStoreConnection !== "function") return false;
207
+ if (!canInstallOnPlatform("windows")) return false;
208
+ if (!windowsStoreSetupIsAvailable(state.snapshot)) return false;
209
+ if (windowsCompanionCanReconnect(state.snapshot)) return false;
210
+ if (storeInvitationIsCurrent(state.windowsStoreInvitation)) return false;
211
+ clear();
212
+ const operation = beginRequest();
213
+ const surface = getSurfaceRevision();
214
+ const environment = getEnvironmentId();
215
+ state.windowsStoreAttempt = { phase: "preparing" };
216
+ notify();
217
+ try {
218
+ const receipt = await requestStoreConnection();
219
+ if (!canApplyStoreResponse(operation, surface, environment)) return false;
220
+ receiveStoreInvitation(receipt);
221
+ return true;
222
+ } catch {
223
+ if (!canApplyStoreResponse(operation, surface, environment)) return false;
224
+ clear();
225
+ state.actionError = "The Companion connection link could not be created. Refresh status and try again.";
226
+ return false;
227
+ } finally {
228
+ finishRequest(operation);
229
+ }
230
+ }
231
+ function canRepairWindowsPairing() {
232
+ if (!canInstallOnPlatform("windows")) return false;
233
+ return windowsCompanionCanReconnect(state.snapshot);
234
+ }
235
+ function beginWindowsStoreRepair() {
236
+ if (!canRepairWindowsPairing()) return false;
237
+ clear();
238
+ state.windowsStoreAttempt = { phase: "confirm-repair" };
239
+ state.actionError = "";
240
+ notify();
241
+ return true;
242
+ }
243
+ function cancelWindowsStoreRepair() {
244
+ if (state.busy) return false;
245
+ if (state.windowsStoreAttempt?.phase !== "confirm-repair") return false;
246
+ clear();
247
+ notify();
248
+ return true;
249
+ }
250
+ async function confirmWindowsStoreRepair() {
251
+ if (!canRepairWindowsPairing()) return false;
252
+ if (state.windowsStoreAttempt?.phase !== "confirm-repair") return false;
253
+ if (typeof revokeConnection !== "function" || typeof requestStoreConnection !== "function") return false;
254
+ const operation = beginRequest();
255
+ const surface = getSurfaceRevision();
256
+ const environment = getEnvironmentId();
257
+ state.windowsStoreAttempt = { phase: "repairing" };
258
+ notify();
259
+ let revoked = false;
260
+ try {
261
+ const snapshot = await revokeConnection();
262
+ if (!canApplyStoreResponse(operation, surface, environment)) return false;
263
+ if (!hasConfirmedUnpairedConnection(snapshot)) throw new Error("unpair_not_confirmed");
264
+ receiveUnpairedConnection(snapshot);
265
+ revoked = true;
266
+ if (!windowsStoreSetupIsAvailable(snapshot)) throw new Error("store_setup_unavailable");
267
+ state.windowsStoreAttempt = { phase: "preparing" };
268
+ state.message = "";
269
+ notify();
270
+ const receipt = await requestStoreConnection();
271
+ if (!canApplyStoreResponse(operation, surface, environment)) return false;
272
+ receiveStoreInvitation(receipt);
273
+ return true;
274
+ } catch {
275
+ if (!canApplyStoreResponse(operation, surface, environment)) return false;
276
+ clear();
277
+ state.message = "";
278
+ state.actionError = revoked
279
+ ? "The previous pairing was removed, but a new connection link could not be created. Connect again to continue."
280
+ : "The previous pairing could not be removed. No new connection was created. Refresh status and try again.";
281
+ return false;
282
+ } finally {
283
+ finishRequest(operation);
284
+ }
285
+ }
286
+ function markLaunchRequested() {
287
+ if (!storeInvitationIsCurrent(state.windowsStoreInvitation)) return;
288
+ state.windowsStoreAttempt = { phase: "waiting", expiresAt: state.windowsStoreInvitation.expiresAt };
289
+ // Leave the anchor intact until the browser has dispatched its native protocol.
290
+ setTimeout(notify, 0);
291
+ }
292
+ return { connectWindowsStore, beginWindowsStoreRepair, cancelWindowsStoreRepair, confirmWindowsStoreRepair, markLaunchRequested, clear };
293
+ }
@@ -29,6 +29,7 @@ export function createWorkspaceShell({
29
29
  };
30
30
  let navigationRevision = 0;
31
31
  const workspaceListeners = new Set();
32
+ const runtimeAvailabilityListeners = new Set();
32
33
  const workspaceGuards = new Set();
33
34
  function notifyWorkspaceListeners(workspace) {
34
35
  onWorkspaceChange(workspace);
@@ -406,6 +407,7 @@ export function createWorkspaceShell({
406
407
  workspaceAccess.update(availability);
407
408
  if (!workspaceAccess.isAvailable(shellState.workspace))
408
409
  activateWorkspace("home", { focus: false });
410
+ for (const listener of runtimeAvailabilityListeners) listener();
409
411
  }
410
412
 
411
413
  function load() {
@@ -421,6 +423,10 @@ export function createWorkspaceShell({
421
423
  runtimeAvailabilityChanged,
422
424
  workspaceUnavailableMessage: workspaceAccess.unavailableMessage,
423
425
  navigationRevision: () => navigationRevision,
426
+ subscribeRuntimeAvailabilityChange(listener) {
427
+ runtimeAvailabilityListeners.add(listener);
428
+ return () => runtimeAvailabilityListeners.delete(listener);
429
+ },
424
430
  subscribeWorkspaceChange(listener) {
425
431
  workspaceListeners.add(listener);
426
432
  return () => workspaceListeners.delete(listener);
@@ -1,11 +1,12 @@
1
1
  import { createSystemHostConnectionManager } from "./components/system-host/manager.js";
2
2
  import { createSystemHostSetupNotice } from "./components/system-host/setup-notice.js";
3
3
 
4
- /** One connection owner, always first on Home and shared with the chat notice. */
4
+ /** One connection owner for configured Home and its shared chat notice. */
5
5
  export function createComputerAccessFeature({
6
6
  dom,
7
7
  runtimeClient,
8
8
  getEnvironmentId = () => "",
9
+ isComputerAccessAvailable = () => true,
9
10
  onChange = () => {},
10
11
  }) {
11
12
  const documentRoot = dom.homeDashboardRoot?.ownerDocument;
@@ -18,6 +19,7 @@ export function createComputerAccessFeature({
18
19
  loadConnection: () => runtimeClient.getSystemHostConnection(),
19
20
  connectLocal: () => runtimeClient.connectLocalSystemHost(),
20
21
  createPairing: () => runtimeClient.createSystemHostPairing(),
22
+ requestStoreConnection: () => runtimeClient.requestSystemHostStoreConnection(),
21
23
  requestPermissions: (input) => runtimeClient.requestSystemHostPermissions(input),
22
24
  downloadSetup: (platform) =>
23
25
  runtimeClient.downloadSystemHostSetup(platform),
@@ -30,6 +32,7 @@ export function createComputerAccessFeature({
30
32
  });
31
33
 
32
34
  function open() {
35
+ if (!isComputerAccessAvailable()) return false;
33
36
  dom.homeWorkspaceButton?.click();
34
37
  if (dom.homeWorkspacePanel?.hidden !== false || !root) return false;
35
38
  connection.openManagement();
@@ -38,16 +41,29 @@ export function createComputerAccessFeature({
38
41
  return true;
39
42
  }
40
43
 
44
+ function runtimeAvailabilityChanged() {
45
+ const ready = isComputerAccessAvailable();
46
+ if (root) root.hidden = !ready;
47
+ connection.setActive(ready);
48
+ notice?.render();
49
+ }
50
+
51
+ function load(background) {
52
+ if (!isComputerAccessAvailable()) return Promise.resolve(false);
53
+ return connection.load(background);
54
+ }
55
+
41
56
  notice = createSystemHostSetupNotice({
42
57
  container: dom.chatPanel?.querySelector(".composer-dock"),
43
58
  conversationRegion: dom.messagesList,
44
59
  getConnectionState: () => connection.state,
45
- supportsConnection: () => runtimeClient.supportsSystemHostConnection(),
46
- refreshConnection: () => connection.load(true),
60
+ supportsConnection: () => isComputerAccessAvailable() && runtimeClient.supportsSystemHostConnection(),
61
+ refreshConnection: () => load(true),
47
62
  onOpen: open,
48
63
  });
49
64
  if (root) {
50
65
  root.className = "home-computer-access";
66
+ root.hidden = !isComputerAccessAvailable();
51
67
  root.setAttribute("tabindex", "-1");
52
68
  root.setAttribute("aria-label", "Computer access");
53
69
  dom.homeDashboardRoot.parentElement?.insertBefore(
@@ -55,13 +71,14 @@ export function createComputerAccessFeature({
55
71
  dom.homeDashboardRoot,
56
72
  );
57
73
  connection.mount(root);
58
- connection.setActive(true);
74
+ runtimeAvailabilityChanged();
59
75
  }
60
76
  dom.environmentSelect?.addEventListener("change", connection.environmentChanged);
61
77
  return {
62
78
  state: connection.state,
63
- load: connection.load,
79
+ load,
64
80
  open,
81
+ runtimeAvailabilityChanged,
65
82
  dispose() {
66
83
  dom.environmentSelect?.removeEventListener("change", connection.environmentChanged);
67
84
  notice.dispose();
@@ -15,11 +15,13 @@ export function createConfigurationFeature({
15
15
  runtimeClient,
16
16
  selectedEnvironmentId,
17
17
  recordControlEvent,
18
+ getOperationsSummary,
18
19
  onNavigationChange = () => {},
19
20
  onConfigurationApplied = async () => {},
20
21
  onConfigurationSettled = () => true,
21
22
  getLearningSnapshot = () => null,
22
23
  isRuntimeReady = () => true,
24
+ isComputerAccessAvailable = () => true,
23
25
  }) {
24
26
  let configWorkspace;
25
27
  let activation;
@@ -72,9 +74,26 @@ export function createConfigurationFeature({
72
74
  });
73
75
 
74
76
  const pluginManager = createPluginManager({
77
+ onSummaryChange: () => configWorkspace?.syncSummary(),
75
78
  getEnvironmentId: selectedEnvironmentId,
79
+ loadConfiguration: (id, environment) =>
80
+ runtimeClient.getPluginConfiguration(id, environment),
81
+ saveConfiguration: (id, input, environment) =>
82
+ runtimeClient.savePluginConfiguration(id, input, environment),
76
83
  onConfigurationSaved: () => activation?.markPending(),
84
+ onConfigurationSettled,
77
85
  loadPlugins: () => runtimeClient.getRuntimePlugins(),
86
+ inspectPlugin: (input, environment) =>
87
+ runtimeClient.inspectRuntimePlugin(input, environment),
88
+ removePlugin: (input, environment) =>
89
+ runtimeClient.removeRuntimePlugin(input, environment),
90
+ onConfigurationApplied: async () => {
91
+ activation?.markApplied();
92
+ await onConfigurationApplied();
93
+ },
94
+ installPlugin: (input, environment) =>
95
+ runtimeClient.installRuntimePlugin(input, environment),
96
+ onNavigationChange,
78
97
  setPlugin: (input) => runtimeClient.setRuntimePlugin(input),
79
98
  beginRuntimeMutation: (subject) =>
80
99
  configWorkspace?.beginExternalRuntimeMutation(subject) ?? false,
@@ -90,6 +109,7 @@ export function createConfigurationFeature({
90
109
  dom,
91
110
  runtimeClient,
92
111
  getEnvironmentId: selectedEnvironmentId,
112
+ isComputerAccessAvailable,
93
113
  onChange: () => homeSetupSuggestion?.render(),
94
114
  });
95
115
  homeSetupSuggestion = createHomeGuidance({
@@ -99,7 +119,7 @@ export function createConfigurationFeature({
99
119
  getEnvironmentId: selectedEnvironmentId,
100
120
  getLearningSnapshot,
101
121
  isRuntimeReady,
102
- // Computer access is permanently visible above the Home suggestions.
122
+ // Configured Home owns computer access above the suggestions.
103
123
  getConnectionState: () => null,
104
124
  supportsConnection: () => false,
105
125
  refreshConnection: () => {},
@@ -115,6 +135,7 @@ export function createConfigurationFeature({
115
135
  },
116
136
  });
117
137
  configWorkspace = createConfigWorkspace({
138
+ getOperationsSummary,
118
139
  onNavigationChange,
119
140
  onRemoveModel: (model) => {
120
141
  if (modelSetup?.isOpen()) return;
@@ -127,6 +148,8 @@ export function createConfigurationFeature({
127
148
  },
128
149
  loadDashboard: () =>
129
150
  runtimeClient.loadConfigDashboard(selectedEnvironmentId()),
151
+ loadModelPlugins: () =>
152
+ runtimeClient.getRuntimePlugins(selectedEnvironmentId()),
130
153
  saveFile: async ({ kind, id, config, expectedRevision }) => {
131
154
  const result = await runtimeClient.saveConfigFile({
132
155
  environmentId: selectedEnvironmentId(),
@@ -231,15 +254,25 @@ export function createConfigurationFeature({
231
254
  const prepareDiscardChanges = configWorkspace.prepareDiscardChanges;
232
255
  return {
233
256
  ...configWorkspace,
257
+ activePluginTab: pluginManager.activeTab,
258
+ openPluginRoute: pluginManager.openRoute,
234
259
  openComputerSetup: computerAccess.open,
235
260
  refreshComputerAccess: computerAccess.load,
236
- renderHomeGuidance: () => homeSetupSuggestion.render(),
261
+ renderHomeGuidance: () => {
262
+ computerAccess.runtimeAvailabilityChanged();
263
+ homeSetupSuggestion.render();
264
+ },
237
265
  showActivityMemories: () => {
238
266
  memoryWorkspace.activate("memories");
239
267
  void longTermMemoryController.setOriginFilter("passive_observation");
240
268
  longTermMemoryManager.focus();
241
269
  },
242
270
  prepareDiscardChanges: (...args) => {
271
+ if (pluginManager.hasConfigurationDraft()) {
272
+ dom.configStatus.textContent =
273
+ "Finish or cancel plugin configuration before leaving.";
274
+ return null;
275
+ }
243
276
  if (modelSetup.isOpen()) {
244
277
  dom.configStatus.textContent =
245
278
  "Finish or cancel model setup before leaving configuration.";
@@ -115,9 +115,12 @@ export function createAppEventBindings({
115
115
  }
116
116
 
117
117
  function bind() {
118
+ let searchTimer;
118
119
  dom.sessionSearchInput.addEventListener("input", () => {
119
120
  state.sessionQuery = dom.sessionSearchInput.value;
120
121
  actions.renderSessions();
122
+ clearTimeout(searchTimer);
123
+ searchTimer = setTimeout(() => void actions.loadSessions(), 200);
121
124
  });
122
125
  dom.refreshSessionsButton.addEventListener(
123
126
  "click",
@@ -153,7 +156,7 @@ export function createAppEventBindings({
153
156
  void changeEnvironment(dom.environmentSelect.value, {
154
157
  notifyEnvironmentChange: false,
155
158
  });
156
- });
159
+ }, true);
157
160
  dom.agentPickerButton.addEventListener("click", (event) => {
158
161
  event.stopPropagation();
159
162
  state.agentPickerOpen = !state.agentPickerOpen;
@@ -20,4 +20,5 @@ export declare function createConversationReadStateController(
20
20
  options: ConversationReadStateControllerOptions,
21
21
  ): {
22
22
  markCurrentSessionReadSoon(): void;
23
+ markDisplayedMessagesReadSoon(messages: ConversationSessionState["messages"]): void;
23
24
  };
@@ -66,14 +66,14 @@ export function createConversationReadStateController({
66
66
  }
67
67
  }
68
68
 
69
- function markCurrentSessionReadSoon() {
69
+ function markDisplayedMessagesReadSoon(messages) {
70
70
  const scope = {
71
71
  environmentId: selectedEnvironmentId(),
72
72
  sessionId: state.currentSessionId,
73
73
  viewVersion: state.sessionViewVersion,
74
74
  };
75
75
  if (!canMarkConversationRead(scope)) return;
76
- const boundary = displayedAssistantReadBoundary(state.messages);
76
+ const boundary = displayedAssistantReadBoundary(messages);
77
77
  if (!boundary) return;
78
78
  scheduleTask(() => {
79
79
  if (!canMarkConversationRead(scope)) return;
@@ -81,5 +81,9 @@ export function createConversationReadStateController({
81
81
  });
82
82
  }
83
83
 
84
- return { markCurrentSessionReadSoon };
84
+ function markCurrentSessionReadSoon() {
85
+ markDisplayedMessagesReadSoon(state.messages);
86
+ }
87
+
88
+ return { markCurrentSessionReadSoon, markDisplayedMessagesReadSoon };
85
89
  }
@@ -0,0 +1,88 @@
1
+ import { isStoppedRequest, restoreStoppedResponses } from "../lib/request-stop-state.js";
2
+ import { isApprovalPresentation, rememberRequestLifecycle } from "../lib/request-lifecycle-view.js";
3
+ import { textOf } from "../lib/text-format.js";
4
+ import { canRestoreSnapshotQueue } from "./history-pagination.js";
5
+
6
+ function isBindableResponse(message) {
7
+ if (message.role !== "assistant" || !message.requestId) return false;
8
+ return !isApprovalPresentation(message);
9
+ }
10
+ function isStreamingRequest(request) {
11
+ if (!request.requestId) return false;
12
+ return request.status === "streaming";
13
+ }
14
+ function isQueuedTerminalRequest(request, queued) {
15
+ if (textOf(request.requestId) !== queued?.waitForRequestId) return false;
16
+ return request.status === "completed" || request.status === "failed";
17
+ }
18
+ function requestsForEventRestoration(requests, streamingRequestIds, appendEvents) {
19
+ if (!appendEvents) return requests;
20
+ // Existing live rows already contain received tokens. Resume their events only after lastSeq.
21
+ return requests.map((request) => streamingRequestIds.has(request.requestId) ? { ...request, events: [] } : request);
22
+ }
23
+
24
+ /** Shared snapshot lifecycle restoration; the caller owns the visible history window. */
25
+ export function createConversationRequestHydration({
26
+ state, client, selectedEnvironmentId, sessionQueue, applyConversationChrome, renderSessions,
27
+ updateComposerSendState, reportQueueFailure, activeAssistantForRequest, restoreSessionEventState,
28
+ subscribeSession, subscribeRequest, replayRequestEvents, resumeRequest, recoverBlockedQueue, drainQueuedMessage, renderMessages,
29
+ }) {
30
+ function isCurrentHydration(scope, viewVersion) {
31
+ if (scope.environmentId !== selectedEnvironmentId()) return false;
32
+ if (scope.sessionId !== state.currentSessionId) return false;
33
+ return viewVersion === state.sessionViewVersion;
34
+ }
35
+ async function restore(requests, { appendEvents = false } = {}) {
36
+ const scope = { environmentId: selectedEnvironmentId(), sessionId: state.currentSessionId };
37
+ const viewVersion = state.sessionViewVersion;
38
+ for (const message of state.messages) {
39
+ if (!isBindableResponse(message)) continue;
40
+ state.requestMessages.set(message.requestId, message.id);
41
+ }
42
+ for (const request of requests) rememberRequestLifecycle(state, request.lifecycle);
43
+ applyConversationChrome();
44
+ renderSessions();
45
+ const streamingRequestIds = new Set(requests
46
+ .filter(isStreamingRequest)
47
+ .map((request) => textOf(request.requestId)));
48
+ if (streamingRequestIds.size === 1) {
49
+ const [streamingRequestId] = streamingRequestIds;
50
+ try { sessionQueue.rebindBlocked(scope, streamingRequestId); }
51
+ catch (error) {
52
+ reportQueueFailure(scope, `The active request was restored, but the remaining Send next queue is paused: ${error instanceof Error ? error.message : String(error)}`);
53
+ }
54
+ }
55
+ state.activeRequestId = [...streamingRequestIds][0] || "";
56
+ updateComposerSendState();
57
+ for (const requestId of streamingRequestIds) activeAssistantForRequest(requestId);
58
+ restoreStoppedResponses(state.messages, requests);
59
+ restoreSessionEventState(requestsForEventRestoration(requests, streamingRequestIds, appendEvents), streamingRequestIds, appendEvents);
60
+ for (const requestId of streamingRequestIds) {
61
+ subscribeRequest(requestId);
62
+ await replayRequestEvents(requestId, viewVersion);
63
+ if (!isCurrentHydration(scope, viewVersion)) return false;
64
+ resumeRequest(requestId);
65
+ }
66
+ if (state.activeRequestId) { renderMessages(); return true; }
67
+ recoverBlockedQueue(scope);
68
+ const queued = sessionQueue.peek(scope);
69
+ const terminal = requests.find((request) => isQueuedTerminalRequest(request, queued));
70
+ if (terminal) await drainQueuedMessage({ ...scope, terminalRequestId: terminal.requestId, cancelled: isStoppedRequest(terminal) });
71
+ if (!isCurrentHydration(scope, viewVersion)) return false;
72
+ renderMessages();
73
+ return true;
74
+ }
75
+ async function rehydrate(requests) {
76
+ const scope = { environmentId: selectedEnvironmentId(), sessionId: state.currentSessionId };
77
+ const viewVersion = state.sessionViewVersion;
78
+ const waitingRequestId = sessionQueue.peek(scope)?.waitForRequestId;
79
+ if (!canRestoreSnapshotQueue({ requests }, waitingRequestId)) {
80
+ const snapshot = await client.loadSession(scope.sessionId, scope.environmentId, { waitingRequestId });
81
+ if (!isCurrentHydration(scope, viewVersion)) return false;
82
+ requests = snapshot.requests || [];
83
+ }
84
+ subscribeSession(scope.sessionId);
85
+ return restore(requests, { appendEvents: true });
86
+ }
87
+ return { restore, rehydrate };
88
+ }