@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
@@ -1,4 +1,4 @@
1
- import { isAssistantInitiativeMessage } from "../assistant-initiative.js";
1
+ import { isAssistantInitiativeMessage } from "../assistant-initiative-message.js";
2
2
  import { projectSessionRequestLifecycle } from "../request-lifecycle/projection.js";
3
3
  function getRequestEventCompactionKey(payload) {
4
4
  const type = typeof payload.type === "string" ? payload.type : "";
@@ -87,7 +87,7 @@ export function getRequestFinalState(request) {
87
87
  }
88
88
  return null;
89
89
  }
90
- function toMessageIdForUi(id) {
90
+ export function toMessageIdForUi(id) {
91
91
  const match = /^msg-(\d+)$/.exec(id);
92
92
  if (match) {
93
93
  return Number(match[1]);
@@ -143,7 +143,7 @@ function messageSource(message) {
143
143
  }
144
144
  return message.role === "user" ? "user" : "request";
145
145
  }
146
- export function toSnapshotMessage(sessionId, message, requests) {
146
+ export function toSnapshotMessage(sessionId, message, requests, resolveRequestId = createMessageRequestIdResolver(requests)) {
147
147
  return {
148
148
  ...(message.kind ? { kind: message.kind } : {}),
149
149
  ...(message.approvalRequest
@@ -155,7 +155,7 @@ export function toSnapshotMessage(sessionId, message, requests) {
155
155
  text: message.content,
156
156
  source: messageSource(message),
157
157
  createdAt: toEpochMs(message.createdAt),
158
- requestId: message.requestId ?? inferMessageRequestId(message, requests),
158
+ requestId: resolveRequestId(message),
159
159
  cronJobId: message.cronJobId ?? null,
160
160
  ...(message.initiative ? { initiative: message.initiative } : {}),
161
161
  ...(message.schedule ? { schedule: message.schedule } : {}),
@@ -166,22 +166,30 @@ export function toSnapshotMessage(sessionId, message, requests) {
166
166
  : {}),
167
167
  };
168
168
  }
169
- function inferMessageRequestId(message, requests) {
170
- if (isAssistantInitiativeMessage(message))
171
- return null;
172
- if (message.role !== "assistant") {
173
- return null;
174
- }
175
- for (let index = requests.length - 1; index >= 0; index -= 1) {
176
- const request = requests[index];
169
+ export function createMessageRequestIdResolver(requests) {
170
+ let completedOutputs;
171
+ return (message) => {
172
+ if (message.requestId != null)
173
+ return message.requestId;
174
+ if (isAssistantInitiativeMessage(message))
175
+ return null;
176
+ if (message.role !== "assistant")
177
+ return null;
178
+ completedOutputs ??= indexCompletedRequestOutputs(requests);
179
+ return completedOutputs.get(message.content) ?? null;
180
+ };
181
+ }
182
+ function indexCompletedRequestOutputs(requests) {
183
+ const outputs = new Map();
184
+ for (const request of requests) {
177
185
  const finalState = getRequestFinalState(request);
178
- if (finalState?.status === "completed" &&
179
- typeof finalState.output === "string" &&
180
- finalState.output === message.content) {
181
- return request.requestId;
182
- }
186
+ if (finalState?.status !== "completed")
187
+ continue;
188
+ if (typeof finalState.output !== "string")
189
+ continue;
190
+ outputs.set(finalState.output, request.requestId);
183
191
  }
184
- return null;
192
+ return outputs;
185
193
  }
186
194
  export function toSnapshotRequest(request) {
187
195
  return {
@@ -10,7 +10,7 @@ import { acceptedLifecycle, appendLifecycleEvent, lifecycleRequest, rejectLifecy
10
10
  /** Commands share SessionService's queue and file, never a parallel checkpoint store. */
11
11
  export function createSessionRequestLifecycle(dependencies) {
12
12
  const blobs = createSessionContinuationBlobs(dependencies.sessionsDir);
13
- async function mutate(sessionId, operation) {
13
+ async function mutate(sessionId, operation, metadataChange = "projection") {
14
14
  assertValidSessionId(sessionId);
15
15
  return dependencies.enqueue(sessionId, async () => {
16
16
  const session = await dependencies.read(sessionId);
@@ -24,7 +24,7 @@ export function createSessionRequestLifecycle(dependencies) {
24
24
  });
25
25
  if (!result.accepted || result.duplicate)
26
26
  return result;
27
- await saveDurableSessionFile(dependencies.sessionsDir, session);
27
+ await saveDurableSessionFile(dependencies.sessionsDir, session, undefined, metadataChange);
28
28
  await cleanupConsumedSessionContinuations(dependencies.sessionsDir, session, previousBlobs);
29
29
  return result;
30
30
  });
@@ -59,7 +59,7 @@ export function createSessionRequestLifecycle(dependencies) {
59
59
  return acceptedLifecycle(request, [
60
60
  appendLifecycleEvent(context, request, command.payload),
61
61
  ]);
62
- }),
62
+ }, "request-only"),
63
63
  async get(sessionId, requestId) {
64
64
  const request = await readRequest(sessionId, requestId);
65
65
  return request ? (projectSessionRequestLifecycle(request) ?? null) : null;
@@ -1,3 +1,4 @@
1
+ import { type SessionSnapshotOptions } from "./snapshot.js";
1
2
  import { type AutomationSessionHandle, type AutomationSessionOrigin } from "./automation-session-origin.js";
2
3
  import type { SessionRequestLifecycleStore } from "./request-lifecycle/contracts.js";
3
4
  import { type CreateAssistantConversationInput } from "./assistant-initiative.js";
@@ -31,10 +32,7 @@ export declare class SessionService {
31
32
  cursor?: string | null;
32
33
  }): Promise<SessionListResult>;
33
34
  getSessionById(sessionId: string): Promise<SessionRecord | null>;
34
- getSessionSnapshot(sessionId: string, options?: {
35
- afterMessageId?: string | number | null;
36
- includeRequests?: boolean;
37
- }): Promise<SessionSnapshot | null>;
35
+ getSessionSnapshot(sessionId: string, options?: SessionSnapshotOptions): Promise<SessionSnapshot | null>;
38
36
  getRequestReplayById(requestId: string, afterSeq?: number): Promise<SessionRequestReplay | null>;
39
37
  deleteSession(sessionId: string): Promise<boolean>;
40
38
  deleteSessionWithStats(sessionId: string): Promise<SessionDeleteResult>;
@@ -1,3 +1,4 @@
1
+ import { projectSessionSnapshot } from "./snapshot.js";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import { AutomationSessionLockedError, createAutomationSessionAccess, hasAutomationSessionOrigin, } from "./automation-session-origin.js";
3
4
  import { createAutomationSessionStore } from "./automation-session-store.js";
@@ -9,7 +10,7 @@ import { createAssistantConversationRecord, } from "./assistant-initiative.js";
9
10
  import { assertSessionProjectUnchanged, copySessionProject, } from "./project-binding.js";
10
11
  import { getDefaultSessionsDir } from "../runtime/config/layout.js";
11
12
  import { assertValidSessionArtifactPathInputs, upsertSessionArtifactPaths, } from "./artifact-paths.js";
12
- import { clientVisibleMessages, compactRequestEvents, filterMessagesAfter, getRequestFinalState, getSessionRequest, isSameMessageId, normalizeAfterSeq, normalizeCursor, normalizeLimit, normalizeSessionTitle, toClientReplayEvent, toEpochMs, toSessionListItem, toSnapshotMessage, toSnapshotRequest, } from "./record/projection.js";
13
+ import { compactRequestEvents, getRequestFinalState, getSessionRequest, isSameMessageId, normalizeAfterSeq, normalizeCursor, normalizeLimit, normalizeSessionTitle, toClientReplayEvent, toEpochMs, toSessionListItem, } from "./record/projection.js";
13
14
  import { assertValidRequestId, assertValidSessionId, createContextEntryId, defaultCreateMessageId, pruneSupersededContextEntries, } from "./record/rules.js";
14
15
  import { deleteSessionFile, ensureSessionsDir, loadAllSessionFiles, loadSessionFile, saveSessionFile, } from "./session-store.js";
15
16
  import { resolveSessionMemoryCheckpointCommit } from "./memory/rules.js";
@@ -115,20 +116,7 @@ export class SessionService {
115
116
  }
116
117
  async getSessionSnapshot(sessionId, options = {}) {
117
118
  const session = await this.getSessionById(sessionId);
118
- if (!session) {
119
- return null;
120
- }
121
- return {
122
- sessionId,
123
- ...(session.kind ? { kind: session.kind } : {}),
124
- ...(session.project ? { project: session.project } : {}),
125
- title: session.title,
126
- messages: filterMessagesAfter(clientVisibleMessages(session.messages), options.afterMessageId).map((message) => toSnapshotMessage(sessionId, message, session.requests ?? [])),
127
- requests: options.includeRequests === false
128
- ? []
129
- : (session.requests ?? []).map(toSnapshotRequest),
130
- nextCursor: null,
131
- };
119
+ return session ? projectSessionSnapshot(session, options) : null;
132
120
  }
133
121
  async getRequestReplayById(requestId, afterSeq = 0) {
134
122
  assertValidRequestId(requestId);
@@ -440,7 +428,7 @@ export class SessionService {
440
428
  request.status = "streaming";
441
429
  }
442
430
  session.updatedAt = timestamp;
443
- await saveSessionFile(this.sessionsDir, session);
431
+ await saveSessionFile(this.sessionsDir, session, undefined, "request-only");
444
432
  return session;
445
433
  });
446
434
  }
@@ -1,6 +1,7 @@
1
1
  import type { SessionRecord } from "./types.js";
2
+ import type { SessionMetadataChange } from "./metadata/source-receipt.js";
2
3
  export declare function ensureSessionsDir(sessionsDir: string): Promise<void>;
3
4
  export declare function loadSessionFile(sessionsDir: string, sessionId: string): Promise<SessionRecord | null>;
4
- export declare function saveSessionFile(sessionsDir: string, session: SessionRecord, assertCurrent?: () => void): Promise<void>;
5
+ export declare function saveSessionFile(sessionsDir: string, session: SessionRecord, assertCurrent?: () => void, metadataChange?: SessionMetadataChange): Promise<void>;
5
6
  export declare function deleteSessionFile(sessionsDir: string, sessionId: string): Promise<boolean>;
6
7
  export declare function loadAllSessionFiles(sessionsDir: string): Promise<SessionRecord[]>;
@@ -1,8 +1,9 @@
1
- import { mkdir, readdir, readFile, rename, rm, writeFile, } from "node:fs/promises";
1
+ import { mkdir, readdir, readFile, rename, rm, stat, writeFile, } from "node:fs/promises";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { join } from "node:path";
4
4
  import { saveDurableSessionFile, syncSessionDirectory, } from "./durable-session-commit.js";
5
5
  import { cleanupSessionContinuations } from "./request-lifecycle/continuation-cleanup.js";
6
+ import { currentSourceStamp, deleteSessionMetadata, sessionSourceStamp, updateSessionMetadata } from "./metadata/store.js";
6
7
  function getSessionFilePath(sessionsDir, sessionId) {
7
8
  return join(sessionsDir, `${sessionId}.json`);
8
9
  }
@@ -22,14 +23,17 @@ export async function loadSessionFile(sessionsDir, sessionId) {
22
23
  throw error;
23
24
  }
24
25
  }
25
- export async function saveSessionFile(sessionsDir, session, assertCurrent) {
26
+ export async function saveSessionFile(sessionsDir, session, assertCurrent, metadataChange = "projection") {
26
27
  if (session.requests?.some((request) => request.lifecycle)) {
27
- return saveDurableSessionFile(sessionsDir, session, assertCurrent);
28
+ return saveDurableSessionFile(sessionsDir, session, assertCurrent, metadataChange);
28
29
  }
29
30
  const filePath = getSessionFilePath(sessionsDir, session.id);
31
+ const previousSource = metadataChange === "request-only" ? await currentSourceStamp(filePath) : undefined;
30
32
  const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
33
+ let source;
31
34
  try {
32
35
  await writeFile(tempPath, JSON.stringify(session, null, 2), "utf-8");
36
+ source = sessionSourceStamp(await stat(tempPath, { bigint: true }));
33
37
  assertCurrent?.();
34
38
  await rename(tempPath, filePath);
35
39
  }
@@ -37,12 +41,14 @@ export async function saveSessionFile(sessionsDir, session, assertCurrent) {
37
41
  await rm(tempPath, { force: true }).catch(() => undefined);
38
42
  throw error;
39
43
  }
44
+ await updateSessionMetadata(sessionsDir, session, source, previousSource);
40
45
  }
41
46
  export async function deleteSessionFile(sessionsDir, sessionId) {
42
47
  const filePath = getSessionFilePath(sessionsDir, sessionId);
43
48
  try {
44
49
  await rm(filePath);
45
50
  await syncSessionDirectory(sessionsDir);
51
+ await deleteSessionMetadata(sessionsDir, sessionId);
46
52
  await cleanupSessionContinuations(sessionsDir, sessionId);
47
53
  return true;
48
54
  }
@@ -0,0 +1,17 @@
1
+ import type { SessionRecord, SessionSnapshot, SessionSnapshotMessage } from "./types.js";
2
+ export type SessionMessageIdentity = Pick<SessionSnapshotMessage, "id" | "role" | "createdAt" | "requestId">;
3
+ export type SessionSnapshotOptions = {
4
+ afterMessageId?: string | number | null;
5
+ includeRequests?: boolean;
6
+ /** Web read receipts need identities, never message bodies or request events. */
7
+ identitiesOnly?: boolean;
8
+ page?: {
9
+ limit: number;
10
+ cursor?: string | null;
11
+ targetMessageId?: string;
12
+ targetCreatedAt?: number;
13
+ targetRequestId?: string;
14
+ waitingRequestId?: string;
15
+ };
16
+ };
17
+ export declare function projectSessionSnapshot(session: SessionRecord, options?: SessionSnapshotOptions): SessionSnapshot;
@@ -0,0 +1,105 @@
1
+ import { clientVisibleMessages, filterMessagesAfter, createMessageRequestIdResolver, toEpochMs, toMessageIdForUi, toSnapshotMessage, toSnapshotRequest } from "./record/projection.js";
2
+ function encodeAnchor(sessionId, message, direction) {
3
+ return Buffer.from(JSON.stringify({ sessionId, id: message.id, createdAt: message.createdAt, direction })).toString("base64url");
4
+ }
5
+ function decodeAnchor(cursor, sessionId) {
6
+ try {
7
+ const anchor = JSON.parse(Buffer.from(cursor, "base64url").toString());
8
+ if (anchor.sessionId !== sessionId)
9
+ throw new Error();
10
+ if (typeof anchor.id !== "string" || typeof anchor.createdAt !== "string")
11
+ throw new Error();
12
+ if (!["older", "newer"].includes(anchor.direction))
13
+ throw new Error();
14
+ return anchor;
15
+ }
16
+ catch {
17
+ throw new Error("history_cursor_stale");
18
+ }
19
+ }
20
+ function messageWindow(sessionId, messages, page, resolveRequestId) {
21
+ const limit = page.limit;
22
+ if (!Number.isSafeInteger(limit) || limit < 1)
23
+ throw new Error("history_page_size_invalid");
24
+ let start = Math.max(0, messages.length - limit);
25
+ let end = messages.length;
26
+ if (page.targetMessageId != null) {
27
+ const target = messages.findIndex((message) => {
28
+ if (String(toMessageIdForUi(message.id)) !== page.targetMessageId)
29
+ return false;
30
+ if (page.targetCreatedAt == null)
31
+ return true;
32
+ if (toEpochMs(message.createdAt) !== page.targetCreatedAt)
33
+ return false;
34
+ return (resolveRequestId(message) || "") === (page.targetRequestId || "");
35
+ });
36
+ if (target >= 0) {
37
+ start = target;
38
+ end = Math.min(messages.length, start + limit);
39
+ }
40
+ }
41
+ else if (page.targetRequestId) {
42
+ const target = messages.findIndex((message) => resolveRequestId(message) === page.targetRequestId);
43
+ if (target >= 0) {
44
+ start = target;
45
+ end = Math.min(messages.length, start + limit);
46
+ }
47
+ }
48
+ if (page.cursor) {
49
+ const anchor = decodeAnchor(page.cursor, sessionId);
50
+ const index = messages.findIndex((message) => message.id === anchor.id && message.createdAt === anchor.createdAt);
51
+ if (index < 0)
52
+ throw new Error("history_cursor_stale");
53
+ start = anchor.direction === "older" ? Math.max(0, index - limit) : index + 1;
54
+ end = anchor.direction === "older" ? index : Math.min(messages.length, start + limit);
55
+ }
56
+ const selected = messages.slice(start, end);
57
+ return {
58
+ selected,
59
+ nextCursor: start > 0 && selected.length ? encodeAnchor(sessionId, selected[0], "older") : null,
60
+ newerCursor: end < messages.length && selected.length ? encodeAnchor(sessionId, selected.at(-1), "newer") : null,
61
+ };
62
+ }
63
+ function isRequiredPageRequest(request, ids, waitingRequestId, continuation = false) {
64
+ if (ids.has(request.requestId))
65
+ return true;
66
+ if (continuation)
67
+ return false;
68
+ if (request.requestId === waitingRequestId)
69
+ return true;
70
+ if (request.status === "streaming")
71
+ return true;
72
+ return request.status === "awaiting_approval";
73
+ }
74
+ export function projectSessionSnapshot(session, options = {}) {
75
+ const visible = clientVisibleMessages(session.messages);
76
+ const requests = session.requests ?? [];
77
+ const resolveRequestId = createMessageRequestIdResolver(requests);
78
+ const base = {
79
+ sessionId: session.id, title: session.title,
80
+ ...(session.kind ? { kind: session.kind } : {}),
81
+ ...(session.project ? { project: session.project } : {}),
82
+ };
83
+ // The default projection is kept intact for existing session consumers.
84
+ if (!options.page && !options.identitiesOnly)
85
+ return {
86
+ ...base,
87
+ messages: filterMessagesAfter(visible, options.afterMessageId).map((message) => toSnapshotMessage(session.id, message, requests, resolveRequestId)),
88
+ requests: options.includeRequests === false ? [] : requests.map(toSnapshotRequest),
89
+ nextCursor: null,
90
+ };
91
+ const messageIndex = visible.map((message) => ({
92
+ id: toMessageIdForUi(message.id), role: message.role, createdAt: toEpochMs(message.createdAt),
93
+ requestId: resolveRequestId(message),
94
+ }));
95
+ if (options.identitiesOnly)
96
+ return { ...base, messages: [], requests: [], nextCursor: null, messageIndex };
97
+ const page = messageWindow(session.id, visible, options.page, resolveRequestId);
98
+ const messages = page.selected.map((message) => toSnapshotMessage(session.id, message, requests, resolveRequestId));
99
+ const ids = new Set(messages.map((message) => message.requestId));
100
+ return {
101
+ ...base, messages, messageIndex, nextCursor: page.nextCursor, newerCursor: page.newerCursor,
102
+ requests: options.includeRequests === false ? [] : requests
103
+ .filter((request) => isRequiredPageRequest(request, ids, options.page?.waitingRequestId, Boolean(options.page?.cursor))).map(toSnapshotRequest),
104
+ };
105
+ }
@@ -130,6 +130,8 @@ export type SessionSnapshot = {
130
130
  messages: SessionSnapshotMessage[];
131
131
  requests: SessionSnapshotRequest[];
132
132
  nextCursor: string | null;
133
+ newerCursor?: string | null;
134
+ messageIndex?: import("./snapshot.js").SessionMessageIdentity[];
133
135
  };
134
136
  export type SessionDeleteResult = {
135
137
  sessionId: string;
@@ -0,0 +1,2 @@
1
+ /** Matches the existing wildcard, owner, tool, and qualified tool selectors. */
2
+ export declare function matchesToolSelectionId(ownerId: string, toolName: string, configuredId: string): boolean;
@@ -0,0 +1,7 @@
1
+ /** Matches the existing wildcard, owner, tool, and qualified tool selectors. */
2
+ export function matchesToolSelectionId(ownerId, toolName, configuredId) {
3
+ return (configuredId === "*" ||
4
+ configuredId === ownerId ||
5
+ configuredId === toolName ||
6
+ configuredId === `${ownerId}.${toolName}`);
7
+ }
@@ -216,6 +216,20 @@ The server checks synchronous owner admission, refuses busy or externally owned
216
216
  environments, and refreshes its gateway through the owning lifecycle callback.
217
217
  Browser reload and saved selection are not evidence of live activation.
218
218
 
219
+ Plugin configuration uses the existing manifest defaults and secret declarations.
220
+ `components/plugins/configuration-fields.js` owns the shared install/edit form;
221
+ `configuration-editor.js` keeps an editing dialog outside dashboard replacement.
222
+ Installation drafts move their existing controls during rendering rather than
223
+ serializing password values. Environment/workspace navigation respects unfinished
224
+ configuration, and writes keep the existing external mutation guard.
225
+
226
+ `plugin-configuration-service.ts` owns saved-value validation and the redacted
227
+ projection. Its private store is installation-scoped, outside plugin packages,
228
+ and survives removal. Saves and Apply acquire the canonical Runtime-file lock
229
+ then the private-store lock. The plugin loader captures local values once per
230
+ compiled configuration lifetime, preserving previous-owner rollback without
231
+ changing plugin SDK or manifest contracts. No process environment is mutated.
232
+
219
233
  ### Additive model setup
220
234
 
221
235
  Configuration composes a separate Provider / Model / Ready dialog in
@@ -68,6 +68,7 @@ let projectsFeature;
68
68
  let workspaceRoutes;
69
69
  let notifications;
70
70
  const operationsController = createOperationsController({
71
+ onSummaryChange: () => configWorkspace?.syncSummary(),
71
72
  dom,
72
73
  client: runtimeClient,
73
74
  getEnvironmentId: selectedEnvironmentId,
@@ -100,7 +101,7 @@ const steerController = createSteerController({
100
101
 
101
102
  const shell = createWorkspaceShell({
102
103
  dom,
103
- onNavigationChange: () => workspaceRoutes?.sync(),
104
+ onNavigationChange: () => { configWorkspace?.syncSummary(); workspaceRoutes?.sync(); },
104
105
  isWorkspaceAvailable: (destination) => {
105
106
  if (!notifications?.isWorkspaceAvailable(destination)) return false;
106
107
  return schedulesFeature?.isWorkspaceAvailable(destination) ?? false;
@@ -166,7 +167,7 @@ schedulesFeature = createSchedulesFeature({
166
167
  getCurrentSessionId: () => state.currentSessionId,
167
168
  getAgentModes: () => state.supportedAgentModes,
168
169
  isRuntimeReady: runtimeOnboarding.isReady,
169
- openSession: (sessionId) => conversationSession.openSession(sessionId),
170
+ openSession: (sessionId, options) => conversationSession.openSession(sessionId, options),
170
171
  });
171
172
  passiveLearning = createPassiveLearningFeature({
172
173
  isRuntimeReady: runtimeOnboarding.isReady,
@@ -190,7 +191,7 @@ dashboardFeature = createDashboardFeature({
190
191
  schedules: schedulesFeature,
191
192
  selectedEnvironmentId,
192
193
  loadSessions,
193
- openSession: (sessionId) => conversationSession.openSession(sessionId),
194
+ openSession: (sessionId, options) => conversationSession.openSession(sessionId, options),
194
195
  isComposerAvailable: runtimeOnboarding.isReady,
195
196
  passiveLearning,
196
197
  });
@@ -563,8 +564,10 @@ const appEventBindings = createAppEventBindings({
563
564
  });
564
565
 
565
566
  configWorkspace = createConfigurationFeature({
567
+ getOperationsSummary: () => operationsController.summary(shell.activeOperationsTab()),
566
568
  getLearningSnapshot: () => passiveLearning?.snapshot(),
567
569
  isRuntimeReady: runtimeOnboarding.isReady,
570
+ isComputerAccessAvailable: () => shell.isWorkspaceAvailable("config"),
568
571
  onNavigationChange: () => workspaceRoutes?.sync(),
569
572
  state,
570
573
  selection: runtimeSelection,
@@ -126,6 +126,8 @@ export function formattedConfig(config) {
126
126
  export function createConfigWorkspaceModel() {
127
127
  const state = {
128
128
  configDashboard: null,
129
+ configDashboardError: false,
130
+ modelPluginCatalog: null,
129
131
  baselinesByKey: new Map(),
130
132
  rawDraftsByKey: new Map(),
131
133
  appliedJsonRepairKeys: new Set(),
@@ -0,0 +1,130 @@
1
+ import { escapeAttribute, escapeHtml } from "../../lib/text-format.js";
2
+ import {
3
+ modelPluginRulesNeedRepair,
4
+ projectModelPluginSelection,
5
+ } from "./model-plugin-selection.js";
6
+
7
+ export async function loadModelPluginCatalog(loadPlugins) {
8
+ if (!loadPlugins) return null;
9
+ try {
10
+ const snapshot = await loadPlugins();
11
+ return { plugins: snapshot.plugins || [], error: "" };
12
+ } catch (error) {
13
+ return {
14
+ plugins: [],
15
+ error: error instanceof Error ? error.message : String(error),
16
+ };
17
+ }
18
+ }
19
+
20
+ function modelLabel(file) {
21
+ return file.config.label || file.id;
22
+ }
23
+
24
+ function renderCapabilitySwitch(file, plugin, capability) {
25
+ const reason = capability.blockedReason;
26
+ const reasonId = `model-tool-policy-${encodeURIComponent(file.id)}-${encodeURIComponent(plugin.id)}-${encodeURIComponent(capability.id)}`;
27
+ return `<li class="plugin-capability-row">
28
+ <div class="plugin-capability-copy">
29
+ <code>${escapeHtml(capability.id)}</code>
30
+ ${capability.description ? `<p class="plugin-capability-description" title="${escapeAttribute(capability.description)}">${escapeHtml(capability.description)}</p>` : ""}
31
+ ${reason ? `<p class="plugin-capability-policy" id="${escapeAttribute(reasonId)}">${escapeHtml(reason)}</p>` : ""}
32
+ </div>
33
+ <label class="plugin-capability-switch">
34
+ <input type="checkbox" role="switch" data-config-action="model-plugin-capability-enabled"
35
+ data-kind="model" data-id="${escapeAttribute(file.id)}"
36
+ data-plugin-id="${escapeAttribute(plugin.id)}" data-capability-id="${escapeAttribute(capability.id)}"
37
+ aria-label="${escapeAttribute(`Allow ${capability.id} in ${plugin.id} for ${modelLabel(file)}`)}"
38
+ ${reason ? `aria-describedby="${escapeAttribute(reasonId)}" disabled` : ""}
39
+ ${capability.enabled ? "checked" : ""} />
40
+ <span aria-hidden="true"></span>
41
+ </label>
42
+ </li>`;
43
+ }
44
+
45
+ function renderPluginRow(file, plugin, globalPlugin, viewState) {
46
+ const key = JSON.stringify([file.id, plugin.id]);
47
+ const open = viewState.expandedPlugins?.has(key);
48
+ const count = plugin.capabilities.length;
49
+ const reason = plugin.controlBlockedReason;
50
+ const pluginIdentity = `${encodeURIComponent(file.id)}-${encodeURIComponent(plugin.id)}`;
51
+ const summaryId = `model-plugin-summary-${pluginIdentity}`;
52
+ const reasonId = `model-plugin-policy-${pluginIdentity}`;
53
+ const globallyRestricted = ["partial", "disabled"].includes(
54
+ globalPlugin.state,
55
+ );
56
+ return `<article class="model-plugin-row">
57
+ <details data-model-plugin-details="${escapeAttribute(plugin.id)}" data-model-id="${escapeAttribute(file.id)}" ${open ? "open" : ""}>
58
+ <summary id="${escapeAttribute(summaryId)}">
59
+ <span class="model-plugin-name" title="${escapeAttribute(plugin.id)}">${escapeHtml(plugin.id)}</span>
60
+ <span class="model-plugin-row-status">
61
+ ${globallyRestricted ? '<span class="model-plugin-global-note">Global restrictions</span>' : ""}
62
+ <span class="plugin-selection-state" data-plugin-state="${escapeAttribute(plugin.state)}">${plugin.selectedCapabilityCount}/${count} tools</span>
63
+ </span>
64
+ </summary>
65
+ <div class="model-plugin-details-body">
66
+ ${plugin.description ? `<p class="model-plugin-description">${escapeHtml(plugin.description)}</p>` : ""}
67
+ ${reason ? `<p class="plugin-capability-policy model-plugin-policy" id="${escapeAttribute(reasonId)}">${escapeHtml(reason)}</p>` : ""}
68
+ <ul class="plugin-capability-list model-plugin-capability-list" aria-label="${escapeAttribute(`Tools in ${plugin.id} for ${modelLabel(file)}`)}">
69
+ ${count ? plugin.capabilities.map((capability) => renderCapabilitySwitch(file, plugin, capability)).join("") : '<li class="plugin-capability-empty">This plugin does not expose any tools.</li>'}
70
+ </ul>
71
+ </div>
72
+ </details>
73
+ <label class="plugin-capability-switch model-plugin-master-switch" title="${escapeAttribute(reason || `Allow ${plugin.id} for this model`)}">
74
+ <input type="checkbox" role="switch" data-config-action="model-plugin-enabled"
75
+ data-kind="model" data-id="${escapeAttribute(file.id)}" data-plugin-id="${escapeAttribute(plugin.id)}"
76
+ aria-label="${escapeAttribute(`Allow ${plugin.id} for ${modelLabel(file)}`)}"
77
+ ${reason ? `aria-describedby="${escapeAttribute(reasonId)}" disabled` : ""}
78
+ ${plugin.pluginEnabled ? "checked" : ""} />
79
+ <span aria-hidden="true"></span>
80
+ </label>
81
+ </article>`;
82
+ }
83
+
84
+ function renderSavedRules(file, viewState) {
85
+ const denied = file.config.plugins?.deny || [];
86
+ if (!denied.length) return "";
87
+ const open = viewState.expandedRetainedRules?.has(file.id);
88
+ return `<details class="model-plugin-saved-rules" data-model-plugin-retained="${escapeAttribute(file.id)}" ${open ? "open" : ""}>
89
+ <summary>Saved rules <span>${denied.length}</span></summary>
90
+ <p>Rules without an editable switch can be changed in the model configuration file shown above.</p>
91
+ <ul>${denied.map((selector) => `<li><code>${escapeHtml(selector)}</code></li>`).join("")}</ul>
92
+ </details>`;
93
+ }
94
+
95
+ export function renderModelPluginPermissions(file, catalog, viewState = {}) {
96
+ if (!catalog) return "";
97
+ const open = catalog.error || viewState.expandedSections?.has(file.id);
98
+ const summaryId = `model-plugin-access-${encodeURIComponent(file.id)}`;
99
+ if (modelPluginRulesNeedRepair(file.config)) {
100
+ return `<details class="model-plugin-permissions" data-model-plugin-section="${escapeAttribute(file.id)}" open>
101
+ <summary id="${escapeAttribute(summaryId)}">Plugin access</summary>
102
+ <p class="error-text">Repair plugins.deny in the model configuration file shown above before changing model plugin restrictions.</p>
103
+ </details>`;
104
+ }
105
+ const plugins = catalog.plugins.map((plugin) =>
106
+ projectModelPluginSelection(file.config, plugin, catalog.plugins),
107
+ );
108
+ const selectedCount = plugins.reduce(
109
+ (count, plugin) => count + plugin.selectedCapabilityCount,
110
+ 0,
111
+ );
112
+ const capabilityCount = plugins.reduce(
113
+ (count, plugin) => count + plugin.capabilities.length,
114
+ 0,
115
+ );
116
+ return `<details class="model-plugin-permissions" data-model-plugin-section="${escapeAttribute(file.id)}" aria-label="${escapeAttribute(`Plugin access for ${modelLabel(file)}`)}" ${open ? "open" : ""}>
117
+ <summary id="${escapeAttribute(summaryId)}">
118
+ <span>Plugin access</span>
119
+ <span class="model-plugin-summary-count">${plugins.length} plugins · ${selectedCount}/${capabilityCount} tools available</span>
120
+ </summary>
121
+ <div class="model-plugin-permissions-body">
122
+ <p class="model-plugin-help">Allow plugins and individual tools for <strong>${escapeHtml(modelLabel(file))}</strong>. Global restrictions still apply. Save this model, then apply changes.</p>
123
+ ${catalog.error ? `<p class="error-text">Plugin list unavailable: ${escapeHtml(catalog.error)}. Refresh configuration to retry; saved restrictions are retained.</p>` : ""}
124
+ <div class="model-plugin-list">
125
+ ${plugins.map((plugin, index) => renderPluginRow(file, plugin, catalog.plugins[index], viewState)).join("")}
126
+ </div>
127
+ ${renderSavedRules(file, viewState)}
128
+ </div>
129
+ </details>`;
130
+ }