@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
@@ -27,6 +27,7 @@ export function createSessionController({
27
27
  confirmAction = window.confirm.bind(window),
28
28
  copyText = (value) => navigator.clipboard.writeText(value),
29
29
  }) {
30
+ let pagination;
30
31
  const titleOf = (session) =>
31
32
  textOf(session?.displayName || session?.title || session?.id);
32
33
  const byId = (sessionId) =>
@@ -34,7 +35,8 @@ export function createSessionController({
34
35
  const isPinned = (sessionId) => state.pinnedSessionIds.includes(sessionId);
35
36
  const sidebar = createSessionSidebarController({
36
37
  state, preferences, selectedEnvironmentId, showToast: shell?.showToast,
37
- render: onSidebarChange ?? render, getFilteredSessions: filtered,
38
+ render: () => { (onSidebarChange ?? render)(); void pagination?.load(); }, getFilteredSessions: filtered,
39
+ getPageInfo: () => pagination?.info(),
38
40
  });
39
41
 
40
42
  function filtered() {
@@ -51,11 +53,14 @@ export function createSessionController({
51
53
  }
52
54
 
53
55
  function render() {
56
+ const scrollTop = dom.sessionsList.scrollTop;
54
57
  sessionActionsMenu.reset();
55
58
  dom.sessionsList.innerHTML = "";
56
59
  const sessions = filtered();
57
- dom.sessionsCount.textContent = String(sessions.length);
60
+ dom.sessionsCount.textContent = String(pagination?.info().total ?? sessions.length);
58
61
  sidebar.renderSections({ root: dom.sessionsList, sessions, createSessionItem, renderGroups });
62
+ pagination?.renderFooter();
63
+ dom.sessionsList.scrollTop = scrollTop;
59
64
  }
60
65
 
61
66
  function createSessionItem(session, sessionIndex) {
@@ -229,6 +234,7 @@ export function createSessionController({
229
234
  : [sessionId, ...state.pinnedSessionIds];
230
235
  preferences.savePinnedSessions(state.pinnedSessionIds);
231
236
  render();
237
+ void pagination?.load();
232
238
  }
233
239
 
234
240
  async function copyFilename(sessionId) {
@@ -310,6 +316,8 @@ export function createSessionController({
310
316
  }
311
317
 
312
318
  return {
319
+ setPagination: (value) => { pagination = value; },
320
+ paginationQuery: sidebar.paginationQuery,
313
321
  archiveSession: (sessionId) => sidebar.archiveSession(sessionId),
314
322
  applyReadState,
315
323
  applyTitle,
@@ -0,0 +1,71 @@
1
+ import { mergeSessionListReadState } from "../lib/session-read-state.js";
2
+
3
+ export function createSessionListPagination({ state, dom, client, sessions, selectedEnvironmentId, renderSessions, onSessionListState }) {
4
+ let revision = 0;
5
+ let pending = false;
6
+ let nextCursor = null;
7
+ let pageInfo = {};
8
+ let queryKey = "";
9
+ let errorMessage = "";
10
+ const query = () => ({ ...sessions.paginationQuery?.(), query: state.sessionQuery || "" });
11
+ function invalidate() {
12
+ state.sessionOverview = undefined;
13
+ revision += 1; pending = false; nextCursor = null; pageInfo = {}; queryKey = ""; errorMessage = "";
14
+ }
15
+ function isCurrent(environmentId, version, key) {
16
+ if (version !== revision) return false;
17
+ if (environmentId !== selectedEnvironmentId()) return false;
18
+ return key === JSON.stringify(query());
19
+ }
20
+ async function load(more = false) {
21
+ const input = query();
22
+ const key = JSON.stringify(input);
23
+ if (more && (pending || !nextCursor || key !== queryKey)) return state.sessions;
24
+ if (!more) nextCursor = null;
25
+ const environmentId = selectedEnvironmentId();
26
+ const version = ++revision;
27
+ const cursor = more ? nextCursor : null;
28
+ pending = true; errorMessage = ""; queryKey = key;
29
+ onSessionListState({ status: "loading", sessions: state.sessions });
30
+ renderSessions();
31
+ try {
32
+ const payload = await client.listSessions(environmentId, { ...input, cursor });
33
+ if (!isCurrent(environmentId, version, key)) return [];
34
+ const incoming = Array.isArray(payload.sessions) ? payload.sessions : [];
35
+ const merged = more ? [...state.sessions, ...incoming] : incoming;
36
+ state.sessions = mergeSessionListReadState([...new Map(merged.map((session) => [session.id, session])).values()], state.sessions);
37
+ nextCursor = payload.nextCursor || null;
38
+ pageInfo = { total: payload.total, archivedCount: payload.archivedCount };
39
+ if (payload.overview) state.sessionOverview = payload.overview;
40
+ onSessionListState({ status: "ready", sessions: state.sessions });
41
+ return state.sessions;
42
+ } catch (error) {
43
+ if (!isCurrent(environmentId, version, key)) return [];
44
+ errorMessage = error instanceof Error ? error.message : String(error);
45
+ onSessionListState({ status: "error", sessions: state.sessions, error: errorMessage });
46
+ return [];
47
+ } finally {
48
+ if (version === revision) { pending = false; renderSessions(); }
49
+ }
50
+ }
51
+ function renderFooter() {
52
+ const root = dom.sessionsList;
53
+ if (!root?.ownerDocument) return;
54
+ if (!pending && !nextCursor && !errorMessage) return;
55
+ const button = root.ownerDocument.createElement("button");
56
+ button.type = "button";
57
+ button.className = "session-archive-toggle";
58
+ button.disabled = pending;
59
+ button.textContent = pending ? "Loading conversations…" : errorMessage ? "Could not load conversations — retry" : "Load more conversations";
60
+ button.addEventListener("click", () => void load(Boolean(nextCursor)));
61
+ root.appendChild(button);
62
+ }
63
+ dom.sessionsList?.addEventListener?.("scroll", () => {
64
+ const root = dom.sessionsList;
65
+ if (root.scrollHeight - root.scrollTop - root.clientHeight > 100) return;
66
+ if (!errorMessage) void load(true);
67
+ }, { passive: true });
68
+ const controller = { load, invalidate, renderFooter, info: () => pageInfo };
69
+ sessions.setPagination?.(controller);
70
+ return controller;
71
+ }
@@ -6,7 +6,7 @@ import { renderSessionSidebarSections } from "../components/session-sidebar-sect
6
6
  import { filterSessionsByArchiveState } from "../lib/session-archive-visibility.js";
7
7
 
8
8
  export function createSessionSidebarController({
9
- state, preferences, selectedEnvironmentId = () => "", render, showToast, getFilteredSessions,
9
+ state, preferences, selectedEnvironmentId = () => "", render, showToast, getFilteredSessions, getPageInfo = () => undefined,
10
10
  }) {
11
11
  let showingArchived = false;
12
12
  let environmentId = selectedEnvironmentId();
@@ -67,8 +67,10 @@ export function createSessionSidebarController({
67
67
  return;
68
68
  }
69
69
  const saved = savedPreferences();
70
+ const rankedIds = new Set(saved.orderedSessionIds);
71
+ const unrankedIds = orderedSessions().map((session) => session.id).filter((id) => !rankedIds.has(id));
70
72
  saved.orderedSessionIds = moveSidebarSession(
71
- orderedSessions().map((session) => session.id), sourceId, targetId, placement,
73
+ [...unrankedIds, ...saved.orderedSessionIds], sourceId, targetId, placement,
72
74
  );
73
75
  if (saveSidebar(saved)) render();
74
76
  }
@@ -143,7 +145,7 @@ export function createSessionSidebarController({
143
145
  const saved = savedPreferences();
144
146
  renderSessionSidebarSections({
145
147
  ...options,
146
- archivedCount: filterSessionsByArchiveState(state.sessions, saved.archivedSessionIds, true).length,
148
+ archivedCount: getPageInfo()?.archivedCount ?? filterSessionsByArchiveState(state.sessions, saved.archivedSessionIds, true).length,
147
149
  showingArchived,
148
150
  onToggleArchived: () => {
149
151
  showingArchived = !showingArchived;
@@ -155,5 +157,5 @@ export function createSessionSidebarController({
155
157
  });
156
158
  }
157
159
 
158
- return { archiveSession, bindItem, renderSections, visibleSessions, isArchiveView: () => showingArchived };
160
+ return { paginationQuery: () => ({ ...savedPreferences(), archived: showingArchived, pinnedSessionIds: state.pinnedSessionIds }), archiveSession, bindItem, renderSections, visibleSessions, isArchiveView: () => showingArchived };
159
161
  }
@@ -125,6 +125,7 @@ export function createSparkChatReading({
125
125
  documentRoot.addEventListener("visibilitychange", scheduleRead);
126
126
  viewport.addEventListener("focus", scheduleRead);
127
127
  return {
128
+ preservePosition() { follow = false; top = dom.messagesList.scrollTop; },
128
129
  afterRender,
129
130
  onLayoutChange() {
130
131
  if (!isOpen()) return;
@@ -1,15 +1,20 @@
1
1
  import { normalizeConversationMessage } from "./conversation-session-controller.js";
2
2
  import { rememberRequestLifecycle, sameConversationMessage } from "../lib/request-lifecycle-view.js";
3
3
 
4
- export function mergeSparkSnapshotMessages(snapshot, current) {
4
+ export function mergeSparkSnapshotMessages(snapshot, current, hasNewer = false) {
5
5
  const canonical = (snapshot.messages || []).map(normalizeConversationMessage);
6
+ if (hasNewer) return current.map((message) => canonical.find((entry) => sameConversationMessage(message, entry)) || message);
6
7
  const activeRequestIds = new Set((snapshot.requests || []).filter((request) => request.status === "streaming").map((request) => request.requestId));
7
8
  const unsettled = current.filter((message) => {
8
9
  if (!message.streaming) return false;
9
10
  if (activeRequestIds.has(message.requestId)) return true;
10
11
  return !canonical.some((entry) => sameConversationMessage(message, entry));
11
12
  });
12
- return [...canonical, ...unsettled];
13
+ if (snapshot.newerCursor === undefined) return [...canonical, ...unsettled];
14
+ const settled = current.filter((message) => !message.streaming);
15
+ const firstIndex = canonical.length ? settled.findIndex((message) => sameConversationMessage(message, canonical[0])) : -1;
16
+ const older = firstIndex >= 0 ? settled.slice(0, firstIndex) : [];
17
+ return [...older, ...canonical, ...unsettled];
13
18
  }
14
19
 
15
20
  function needsRequestLifecycleHydration(snapshot, state) {
@@ -64,6 +69,18 @@ export function createSparkChatSync({
64
69
  if (environmentId !== getEnvironmentId()) return false;
65
70
  return readRevision === revision;
66
71
  }
72
+ function canRetainTargetWindow(sessionId) {
73
+ if (!initialized || state.currentSessionId !== sessionId) return false;
74
+ return conversation.session.history?.hasNewer() === true;
75
+ }
76
+ async function hydrateConversation(result) {
77
+ if (!canRetainTargetWindow(result.sessionId)) {
78
+ await conversation.session.openSession(result.sessionId, { snapshot: { ...result.snapshot, readState: result.readState } });
79
+ return true;
80
+ }
81
+ state.messages = mergeSparkSnapshotMessages(result.snapshot, state.messages, true);
82
+ return conversation.session.rehydrateRequests(result.snapshot.requests || []);
83
+ }
67
84
  async function drain() {
68
85
  if (!canRefresh()) return;
69
86
  queued = false;
@@ -98,13 +115,15 @@ export function createSparkChatSync({
98
115
  onReadState(result.readState);
99
116
  const snapshot = result.snapshot;
100
117
  if (shouldHydrateSparkConversation(initialized, rehydrate, snapshot, state)) {
101
- initialized = false; hydrating = true;
102
- await conversation.session.openSession(result.sessionId);
118
+ hydrating = true;
119
+ const restored = await hydrateConversation(result);
103
120
  hydrating = false;
121
+ if (!restored) return;
104
122
  if (!isCurrentRead(environmentId, readRevision)) return;
105
123
  initialized = true;
106
124
  } else {
107
- state.messages = mergeSparkSnapshotMessages(snapshot, state.messages);
125
+ conversation.session.history?.refresh(snapshot);
126
+ state.messages = mergeSparkSnapshotMessages(snapshot, state.messages, conversation.session.history?.hasNewer());
108
127
  for (const request of snapshot.requests || []) rememberRequestLifecycle(state, request.lifecycle);
109
128
  for (const message of state.messages) {
110
129
  if (message.role !== "assistant" || !message.requestId) continue;
@@ -37,7 +37,7 @@ export function createWorkspaceRouteController({
37
37
  session: getSessionId(),
38
38
  automationRun: automations?.chatRunId() || "",
39
39
  category: configurationCategoryForWorkspace(shell.activeWorkspace()),
40
- tab: shell.activeOperationsTab(),
40
+ tab: shell.activeWorkspace() === "plugins" ? configuration.activePluginTab?.() || "installed" : shell.activeOperationsTab(),
41
41
  job: schedules.selectedJobId(),
42
42
  automation: automations?.selectedAutomationId() || "",
43
43
  run: automations?.selectedRunId() || "",
@@ -136,24 +136,24 @@ export function createWorkspaceRouteController({
136
136
  return true;
137
137
  }
138
138
  if (route.session === getSessionId()) return true;
139
- const sessions = await loadSessions();
139
+ await loadSessions();
140
140
  if (!routeActivationIsCurrent()) return false;
141
141
  if (environmentId !== getEnvironmentId()) return false;
142
- if (!routeSessionIsListed(route, sessions)) {
143
- shell.showToast(
144
- "This conversation is unavailable in the selected environment.",
145
- "failed",
146
- );
142
+ let routeCommitted = false;
143
+ try {
144
+ await openSession(route.session, {
145
+ isRouteCurrent: routeActivationIsCurrent,
146
+ commitRouteNavigation: () => {
147
+ routeCommitted = commitLinkedConversationRoute();
148
+ return routeCommitted;
149
+ },
150
+ });
151
+ } catch (error) {
152
+ if (error.code !== "session_not_found") throw error;
153
+ if (!routeActivationIsCurrent()) return false;
154
+ shell.showToast("This conversation is unavailable in the selected environment.", "failed");
147
155
  return false;
148
156
  }
149
- let routeCommitted = false;
150
- await openSession(route.session, {
151
- isRouteCurrent: routeActivationIsCurrent,
152
- commitRouteNavigation: () => {
153
- routeCommitted = commitLinkedConversationRoute();
154
- return routeCommitted;
155
- },
156
- });
157
157
  if (!routeCommitted) return false;
158
158
  if (!routeActivationIsCurrent()) return false;
159
159
  if (environmentId !== getEnvironmentId()) return false;
@@ -223,6 +223,9 @@ export function createWorkspaceRouteController({
223
223
  if (route.workspace === "config") {
224
224
  shell.activateOperationsTab(route.tab || "runtime");
225
225
  }
226
+ if (route.workspace === "plugins") {
227
+ return configuration.openPluginRoute?.(route) ?? true;
228
+ }
226
229
  if (route.workspace === "schedules") {
227
230
  return await schedules.openJob(route.job || "");
228
231
  }
@@ -251,6 +254,9 @@ export function createWorkspaceRouteController({
251
254
  route.job = "";
252
255
  route.automation = "";
253
256
  route.run = "";
257
+ route.pluginSource = "";
258
+ route.pluginRef = "";
259
+ route.pluginPath = "";
254
260
  }
255
261
  await applyRoute(route, { initial: true });
256
262
  } catch (error) {
@@ -346,10 +352,6 @@ function routeChangesEnvironment(route, selectedEnvironment) {
346
352
  return route.environment !== selectedEnvironment;
347
353
  }
348
354
 
349
- function routeSessionIsListed(route, sessions) {
350
- return sessions.some((session) => session.id === route.session);
351
- }
352
-
353
355
  function initialRouteWasSuperseded(initial, pendingHistory) {
354
356
  if (!initial) return false;
355
357
  return Boolean(pendingHistory);
@@ -34,7 +34,7 @@ export function createDashboardFeature({
34
34
  render: (snapshot) => {
35
35
  const sessions = filterSessionsByArchiveState(snapshot.sessions,
36
36
  preferences?.loadSessionSidebar?.(selectedEnvironmentId())?.archivedSessionIds);
37
- view?.render({ ...snapshot, sessions, composerAvailable: isComposerAvailable() });
37
+ view?.render({ ...snapshot, sessions, sessionOverview: state.sessionOverview, composerAvailable: isComposerAvailable() });
38
38
  },
39
39
  });
40
40
  view = createDashboardWorkspace({
@@ -52,7 +52,7 @@ export function createDashboardFeature({
52
52
  openConversation: async (sessionId, requestId) => {
53
53
  if (!shell.activateWorkspace("chat")) return;
54
54
  try {
55
- await openSession(sessionId);
55
+ await openSession(sessionId, { page: { targetRequestId: requestId } });
56
56
  if (state.currentSessionId !== sessionId) return;
57
57
  if (!requestId) return;
58
58
  requestAnimationFrame(() => {
@@ -25,7 +25,10 @@
25
25
  </section>
26
26
  <div id="app" class="app-shell" data-startup-pending aria-busy="true" inert>
27
27
  <nav class="workspace-rail" aria-label="Workspace navigation">
28
- <div class="workspace-brand"><img src="/favicon.svg" width="28" height="28" alt="ABot" /></div>
28
+ <div class="workspace-brand">
29
+ <img src="/favicon.svg" width="28" height="28" alt="ABot" />
30
+ <a class="product-site-link" href="https://abot-ai.com/" target="_blank" rel="noopener noreferrer" aria-label="abot-ai.com — ABot website (opens in a new tab)">abot-ai.com <span aria-hidden="true">↗</span></a>
31
+ </div>
29
32
  <button
30
33
  id="sessionsToggleButton"
31
34
  class="rail-button rail-history-button"
@@ -314,6 +317,7 @@
314
317
  id="messagesList"
315
318
  class="messages-list"
316
319
  aria-label="Conversation messages"
320
+ tabindex="0"
317
321
  ></section>
318
322
  <div
319
323
  id="messageStatusRegion"
@@ -639,7 +643,7 @@
639
643
  >
640
644
  <header class="workspace-page-header config-workspace-header">
641
645
  <div class="workspace-page-heading config-workspace-heading">
642
- <p class="eyebrow">Runtime workspace</p>
646
+ <a class="product-site-link" href="https://abot-ai.com/" target="_blank" rel="noopener noreferrer" aria-label="abot-ai.com — ABot website (opens in a new tab)">abot-ai.com <span aria-hidden="true">↗</span></a>
643
647
  <h2 id="configWorkspaceTitle">System</h2>
644
648
  </div>
645
649
  <div class="toolbar-actions">
@@ -0,0 +1,49 @@
1
+ import { isApprovalPresentation, mergeConversationMessage, sameConversationMessage } from "./request-lifecycle-view.js";
2
+
3
+ function isRequestResponse(message) {
4
+ if (message.role !== "assistant") return false;
5
+ if (!message.requestId) return false;
6
+ return !isApprovalPresentation(message);
7
+ }
8
+
9
+ function indexConversationMessages(messages) {
10
+ const byId = new Map(messages.map((message) => [message.id, message]));
11
+ const byRequest = new Map();
12
+ for (const message of messages) {
13
+ if (!isRequestResponse(message)) continue;
14
+ const candidates = byRequest.get(message.requestId) || [];
15
+ candidates.push(message);
16
+ byRequest.set(message.requestId, candidates);
17
+ }
18
+ return (incoming) => {
19
+ if (!incoming) return undefined;
20
+ const exact = byId.get(incoming.id);
21
+ if (exact) return exact;
22
+ return byRequest.get(incoming.requestId)?.find((message) => sameConversationMessage(message, incoming));
23
+ };
24
+ }
25
+
26
+ /** Keep the contiguous loaded history before rows received from the live stream. */
27
+ export function mergeHistoryPage(state, incoming, direction, windowEnd) {
28
+ const current = state.messages;
29
+ const findCurrent = indexConversationMessages(current);
30
+ const replaced = new Set();
31
+ const page = incoming.map((message) => {
32
+ const existing = findCurrent(message);
33
+ if (!existing) return message;
34
+ replaced.add(existing);
35
+ return mergeConversationMessage(existing, message);
36
+ });
37
+ const retained = (messages) => messages.filter((message) => !replaced.has(message));
38
+ if (direction === "older") {
39
+ state.messages = [...page, ...retained(current)];
40
+ } else {
41
+ const end = current.indexOf(findCurrent(windowEnd));
42
+ const split = end < 0 ? current.length : end + 1;
43
+ state.messages = [...retained(current.slice(0, split)), ...page, ...retained(current.slice(split))];
44
+ }
45
+ for (const message of state.messages) {
46
+ if (!isRequestResponse(message)) continue;
47
+ state.requestMessages?.set(message.requestId, message.id);
48
+ }
49
+ }
@@ -71,6 +71,14 @@ export function sameConversationMessage(existing, incoming) {
71
71
  return !existing.persistedMessageId || !incoming.persistedMessageId;
72
72
  }
73
73
 
74
+ export function mergeConversationMessage(existing, incoming) {
75
+ return {
76
+ ...existing, ...incoming,
77
+ text: incoming.text || existing.text,
78
+ thinkingText: incoming.thinkingText || existing.thinkingText,
79
+ };
80
+ }
81
+
74
82
  export function removeStreamingPlaceholder(state, requestId) {
75
83
  state.messages = state.messages.filter((message) => {
76
84
  if (message.requestId !== requestId || message.role !== "assistant")
@@ -8,6 +8,9 @@ export interface WorkspaceRoute {
8
8
  job: string;
9
9
  automation: string;
10
10
  run: string;
11
+ pluginSource?: string;
12
+ pluginRef?: string;
13
+ pluginPath?: string;
11
14
  }
12
15
 
13
16
  export function readWorkspaceRoute(
@@ -39,6 +39,7 @@ export function readWorkspaceRoute(location) {
39
39
  job: routeParameter(parameters, "job"),
40
40
  automation: routeParameter(parameters, "automation"),
41
41
  run: routeParameter(parameters, "run"),
42
+ ...(workspace === "plugins" && parameters.has("pluginSource") ? { pluginSource: routeParameter(parameters, "pluginSource"), pluginRef: routeParameter(parameters, "pluginRef"), pluginPath: routeParameter(parameters, "pluginPath") } : {}),
42
43
  };
43
44
  }
44
45
 
@@ -53,6 +54,9 @@ export function workspaceRouteUrl(route) {
53
54
  parameters.set("automationRun", route.automationRun);
54
55
  else if (workspace === "chat" && route.session)
55
56
  parameters.set("session", route.session);
57
+ if (workspace === "plugins") {
58
+ if (route.tab === "discover") parameters.set("tab", "discover");
59
+ }
56
60
  if (workspace === "config") {
57
61
  if (route.tab) parameters.set("tab", route.tab);
58
62
  }
@@ -39,7 +39,6 @@ export function createPassiveLearningFeature({
39
39
  home = createPassiveLearningHome({
40
40
  actions,
41
41
  openLearning,
42
- openComputerAccess,
43
42
  openSetup: () => {
44
43
  if (openLearning() === false) return;
45
44
  if (learningRoot) selectLearningView(learningRoot, "settings");
@@ -17,6 +17,7 @@ export function createRuntimeOnboardingFeature({
17
17
  const usesBridgeBackend = () => state.config?.backend === "bridge";
18
18
  let selectedGuide = null;
19
19
  let bindings = {};
20
+ shell?.runtimeAvailabilityChanged(state.runtimeAvailability);
20
21
 
21
22
  function createConfiguredGuide() {
22
23
  const common = {
@@ -52,6 +53,7 @@ export function createRuntimeOnboardingFeature({
52
53
  loadHostConnection: () => runtimeClient.getSystemHostConnection(),
53
54
  connectLocalHost: () => runtimeClient.connectLocalSystemHost(),
54
55
  createHostPairing: () => runtimeClient.createSystemHostPairing(),
56
+ requestHostStoreConnection: () => runtimeClient.requestSystemHostStoreConnection(),
55
57
  requestHostPermissions: (input) => runtimeClient.requestSystemHostPermissions(input),
56
58
  downloadHostSetup: (platform) =>
57
59
  runtimeClient.downloadSystemHostSetup(platform),
@@ -87,6 +89,7 @@ export function createRuntimeOnboardingFeature({
87
89
  };
88
90
  const controller = createRuntimeOnboardingController({
89
91
  state,
92
+ getEnvironmentId: selectedEnvironmentId,
90
93
  guide,
91
94
  reloadModels: () =>
92
95
  usesBridgeBackend() ? reloadCatalog() : reloadModels(),
@@ -32,7 +32,7 @@ export function createSchedulesFeature({
32
32
  if (!shell.activateWorkspace("chat")) return;
33
33
  if (!sessionId) return;
34
34
  try {
35
- await openSession(sessionId);
35
+ await openSession(sessionId, { page: { targetRequestId: requestId } });
36
36
  if (!requestId) return;
37
37
  requestAnimationFrame(() => {
38
38
  const messages = [
@@ -1,8 +1,10 @@
1
+ import { createPluginConfigurationRequests } from "./plugin-configuration.js";
1
2
  /** Configuration transport; credentials are sent once and never retained here. */
2
3
  export function createConfigurationRequests({ requestApi, environmentQuery }) {
3
4
  const scoped = (path, environmentId) =>
4
5
  path + "?environment=" + environmentQuery(environmentId);
5
6
  return {
7
+ ...createPluginConfigurationRequests({ requestApi, environmentQuery }),
6
8
  getRuntimeSetup(environmentId) {
7
9
  return requestApi(scoped("/runtime/setup", environmentId));
8
10
  },
@@ -42,6 +44,24 @@ export function createConfigurationRequests({ requestApi, environmentQuery }) {
42
44
  body: JSON.stringify(input),
43
45
  });
44
46
  },
47
+ inspectRuntimePlugin(input, environmentId) {
48
+ return requestApi(scoped("/runtime/plugins/inspect", environmentId), {
49
+ method: "POST",
50
+ body: JSON.stringify(input),
51
+ });
52
+ },
53
+ installRuntimePlugin(input, environmentId) {
54
+ return requestApi(scoped("/runtime/plugins/install", environmentId), {
55
+ method: "POST",
56
+ body: JSON.stringify(input),
57
+ });
58
+ },
59
+ removeRuntimePlugin(input, environmentId) {
60
+ return requestApi(scoped("/runtime/plugins/remove", environmentId), {
61
+ method: "POST",
62
+ body: JSON.stringify(input),
63
+ });
64
+ },
45
65
  applyRuntimeConfiguration(environmentId) {
46
66
  return requestApi(scoped("/runtime/config/apply", environmentId), {
47
67
  method: "POST",
@@ -0,0 +1,19 @@
1
+ /** Plugin configuration transport never retains entered credentials. */
2
+ export function createPluginConfigurationRequests({
3
+ requestApi,
4
+ environmentQuery,
5
+ }) {
6
+ const path = (pluginId, environmentId) =>
7
+ `/runtime/plugins/configuration/${encodeURIComponent(pluginId)}?environment=${environmentQuery(environmentId)}`;
8
+ return {
9
+ getPluginConfiguration(pluginId, environmentId) {
10
+ return requestApi(path(pluginId, environmentId));
11
+ },
12
+ savePluginConfiguration(pluginId, input, environmentId) {
13
+ return requestApi(path(pluginId, environmentId), {
14
+ method: "PUT",
15
+ body: JSON.stringify(input),
16
+ });
17
+ },
18
+ };
19
+ }
@@ -1,16 +1,16 @@
1
1
  export function createSparkChatRequests({ requestApi, getEnvironmentId, getConfig }) {
2
2
  const supportsSparkChat = () => getConfig()?.backend === "runtime";
3
- function path(environmentId) {
3
+ function path(environmentId, paged = false) {
4
4
  if (!supportsSparkChat()) throw new Error("SPARK chat is unavailable with this backend.");
5
- return `/runtime/spark/chat?${new URLSearchParams({ environment: environmentId })}`;
5
+ return `/runtime/spark/chat?${new URLSearchParams({ environment: environmentId, ...(paged ? { page: "1" } : {}) })}`;
6
6
  }
7
7
  return {
8
8
  supportsSparkChat,
9
9
  loadSparkChat(environmentId = getEnvironmentId()) {
10
- return requestApi(path(environmentId));
10
+ return requestApi(path(environmentId, true));
11
11
  },
12
12
  configureSparkChat(input, environmentId = getEnvironmentId()) {
13
- return requestApi(path(environmentId), {
13
+ return requestApi(path(environmentId, true), {
14
14
  method: "PUT", body: JSON.stringify(input),
15
15
  });
16
16
  },
@@ -18,6 +18,8 @@ export function createSystemHostRequests({ requestApi, getConfig, getEnvironment
18
18
  requestSystemHost("/permissions", { method: "POST", body: JSON.stringify(input) }),
19
19
  connectLocalSystemHost: () =>
20
20
  requestSystemHost("/connect-local", { method: "POST", body: "{}" }),
21
+ requestSystemHostStoreConnection: () =>
22
+ requestSystemHost("/store-connect", { method: "POST", body: "{}" }),
21
23
  downloadSystemHostSetup: (platform, options = {}) =>
22
24
  requestSystemHost("/setup", {
23
25
  method: "POST",
@@ -101,6 +101,7 @@ export declare function createRuntimeWebClient(options: {
101
101
  getSystemHostConnection(): Promise<Record<string, unknown>>;
102
102
  requestSystemHostPermissions(input: Record<string, unknown>): Promise<Record<string, unknown>>;
103
103
  connectLocalSystemHost(): Promise<Record<string, unknown>>;
104
+ requestSystemHostStoreConnection(): Promise<Record<string, unknown>>;
104
105
  downloadSystemHostSetup(
105
106
  platform: "windows" | "macos" | "linux",
106
107
  options?: { purpose?: "learning" },
@@ -128,6 +129,9 @@ export declare function createRuntimeWebClient(options: {
128
129
  environmentId?: string,
129
130
  ): Promise<Record<string, unknown>>;
130
131
  getRuntimePlugins(environmentId?: string): Promise<Record<string, unknown>>;
132
+ inspectRuntimePlugin(input: Record<string, unknown>, environmentId?: string): Promise<Record<string, unknown>>;
133
+ installRuntimePlugin(input: Record<string, unknown>, environmentId?: string): Promise<Record<string, unknown>>;
134
+ removeRuntimePlugin(input: { pluginId: string }, environmentId?: string): Promise<Record<string, unknown>>;
131
135
  setRuntimePlugin(
132
136
  input: { pluginId: string; capabilityId?: string; enabled: boolean },
133
137
  environmentId?: string,
@@ -217,10 +221,11 @@ export declare function createRuntimeWebClient(options: {
217
221
  file: Blob;
218
222
  }): Promise<Record<string, unknown>>;
219
223
  loadWebConfig(): Promise<Record<string, unknown>>;
220
- listSessions(environmentId?: string): Promise<Record<string, unknown>>;
224
+ listSessions(environmentId?: string, page?: Record<string, unknown>): Promise<Record<string, unknown>>;
221
225
  loadSession(
222
226
  sessionId: string,
223
227
  environmentId?: string,
228
+ page?: Record<string, unknown>,
224
229
  ): Promise<Record<string, unknown>>;
225
230
  markSessionRead(options: {
226
231
  sessionId: string;
@@ -168,17 +168,26 @@ export function createRuntimeWebClient({
168
168
  return request("/web-config", "Web configuration");
169
169
  },
170
170
 
171
- listSessions(environmentId = getEnvironmentId()) {
171
+ listSessions(environmentId = getEnvironmentId(), page) {
172
+ if (page && getConfig()?.backend === "runtime") return requestApi(
173
+ `/chat/sessions/page?environment=${environmentQuery(environmentId)}`,
174
+ { method: "POST", body: JSON.stringify(page) },
175
+ );
172
176
  return requestApi(
173
177
  `/chat/sessions?environment=${environmentQuery(environmentId)}`,
174
178
  );
175
179
  },
176
180
 
177
- loadSession(sessionId, environmentId = getEnvironmentId()) {
181
+ loadSession(sessionId, environmentId = getEnvironmentId(), page = {}) {
182
+ const query = new URLSearchParams({ environment: environmentId });
183
+ if (getConfig()?.backend === "runtime") {
184
+ query.set("page", "1");
185
+ for (const [key, value] of Object.entries(page)) if (value != null) query.set(key, String(value));
186
+ }
178
187
  return requestApi(
179
188
  `/chat/sessions/${encodeURIComponent(
180
189
  sessionId,
181
- )}/messages?environment=${environmentQuery(environmentId)}`,
190
+ )}/messages?${query}`,
182
191
  );
183
192
  },
184
193