@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
@@ -4,7 +4,8 @@ import { getNumber, getString, sendJson } from "./http.js";
4
4
  import { PendingToolApprovals } from "./pending-tool-approvals.js";
5
5
  import { createWorkspaceChangeNotifier } from "./workspace-notifications.js";
6
6
  import { attachApprovalRequest } from "./approval-request-attachment.js";
7
- import { publicSparkChatAdmissionFailure, resolveSparkChatRequest } from "./spark-chat-admission.js";
7
+ import { publicSparkChatAdmissionFailure, resolveSparkChatRequest, } from "./spark-chat-admission.js";
8
+ import { traceWebProjection, webSteerRoute, WebSteerObservation, } from "./request-control-observation.js";
8
9
  function createRequestId() {
9
10
  const random = Math.random().toString(36).slice(2, 8);
10
11
  return `web-${Date.now()}-${random}`;
@@ -26,6 +27,7 @@ export class LocalRequestExecution {
26
27
  scheduledRequestOptions(run) {
27
28
  const requestSteering = createRequestSteeringInbox({
28
29
  requestId: run.requestId,
30
+ diagnostics: { origin: "web_projection" },
29
31
  });
30
32
  this.activeRequests.set(run.requestId, {
31
33
  requestId: run.requestId,
@@ -38,6 +40,7 @@ export class LocalRequestExecution {
38
40
  finalState: null,
39
41
  requestSteering,
40
42
  });
43
+ traceWebProjection("projection.opened", run.requestId, this.activeRequests.get(run.requestId), "schedule");
41
44
  return {
42
45
  toolApprovalController: this.toolApprovals,
43
46
  requestSteering,
@@ -51,7 +54,10 @@ export class LocalRequestExecution {
51
54
  if (payload.sessionDeleted !== true)
52
55
  this.publish(outbound);
53
56
  if (isTerminal) {
54
- this.activeRequests.delete(getString(payload.requestId));
57
+ const requestId = getString(payload.requestId);
58
+ const active = this.activeRequests.get(requestId);
59
+ const removed = this.activeRequests.delete(requestId);
60
+ traceWebProjection("projection.removed", requestId, active, "published_terminal", removed);
55
61
  }
56
62
  }
57
63
  async start(res, body, environmentId, environment) {
@@ -78,10 +84,16 @@ export class LocalRequestExecution {
78
84
  body = await resolveSparkChatRequest(environment, sessionId, body);
79
85
  }
80
86
  catch (error) {
81
- sendJson(res, 409, { ok: false, ...publicSparkChatAdmissionFailure(error) });
87
+ sendJson(res, 409, {
88
+ ok: false,
89
+ ...publicSparkChatAdmissionFailure(error),
90
+ });
82
91
  return;
83
92
  }
84
- const requestSteering = createRequestSteeringInbox({ requestId });
93
+ const requestSteering = createRequestSteeringInbox({
94
+ requestId,
95
+ diagnostics: { origin: "web_projection" },
96
+ });
85
97
  const request = {
86
98
  type: "run_request",
87
99
  requestId,
@@ -103,6 +115,7 @@ export class LocalRequestExecution {
103
115
  finalState: null,
104
116
  requestSteering,
105
117
  });
118
+ traceWebProjection("projection.opened", requestId, this.activeRequests.get(requestId), "ordinary");
106
119
  void this.run(environment, request, environmentId, sessionId, requestSteering)
107
120
  .catch((error) => {
108
121
  this.publish({
@@ -113,7 +126,11 @@ export class LocalRequestExecution {
113
126
  error: error instanceof Error ? error.message : String(error),
114
127
  });
115
128
  })
116
- .finally(() => this.activeRequests.delete(requestId));
129
+ .finally(() => {
130
+ const active = this.activeRequests.get(requestId);
131
+ const removed = this.activeRequests.delete(requestId);
132
+ traceWebProjection("projection.removed", requestId, active, "run_handle_settled", removed);
133
+ });
117
134
  sendJson(res, 200, { ok: true, requestId, sessionId });
118
135
  }
119
136
  activeReplay(requestId, afterSeq) {
@@ -151,45 +168,60 @@ export class LocalRequestExecution {
151
168
  const steerId = getString(message.steerId).trim();
152
169
  const text = getString(message.text).trim();
153
170
  const active = requestId ? this.activeRequests.get(requestId) : undefined;
154
- if (active) {
155
- const sessions = resolveEnvironment(active.environmentId).services.sessions;
156
- try {
157
- await sessions.assertInteractiveSession?.(active.sessionId);
171
+ const observation = new WebSteerObservation(requestId, steerId, getString(message.environment), text.length, active, () => this.activeRequests.get(requestId));
172
+ try {
173
+ if (active) {
174
+ observation.selectRoute("interactive_session_check");
175
+ const sessions = resolveEnvironment(active.environmentId).services
176
+ .sessions;
177
+ try {
178
+ await sessions.assertInteractiveSession?.(active.sessionId);
179
+ }
180
+ catch (error) {
181
+ if (!isAutomationSessionLockedError(error))
182
+ throw error;
183
+ const acknowledgement = {
184
+ type: "steer_ack",
185
+ requestId,
186
+ steerId,
187
+ accepted: false,
188
+ reason: "automation_session_locked",
189
+ };
190
+ observation.result(acknowledgement);
191
+ return acknowledgement;
192
+ }
158
193
  }
159
- catch (error) {
160
- if (!isAutomationSessionLockedError(error))
161
- throw error;
162
- return {
194
+ observation.selectRoute("environment_resolution");
195
+ const steer = active
196
+ ? resolveEnvironment(active.environmentId).requests.steer
197
+ : undefined;
198
+ observation.selectRoute(webSteerRoute(active, steer));
199
+ const result = (steer
200
+ ? await steer(requestId, { steerId, text })
201
+ : active?.requestSteering.append({ steerId, text })) ??
202
+ { ok: false, reason: "request_not_active" };
203
+ const acknowledgement = result.ok
204
+ ? {
205
+ type: "steer_ack",
206
+ requestId,
207
+ steerId,
208
+ accepted: true,
209
+ acceptedSequence: result.update.sequence,
210
+ }
211
+ : {
163
212
  type: "steer_ack",
164
213
  requestId,
165
214
  steerId,
166
215
  accepted: false,
167
- reason: "automation_session_locked",
216
+ reason: result.reason,
168
217
  };
169
- }
218
+ observation.result(acknowledgement);
219
+ return acknowledgement;
220
+ }
221
+ catch (error) {
222
+ observation.failed(error);
223
+ throw error;
170
224
  }
171
- const steer = active
172
- ? resolveEnvironment(active.environmentId).requests.steer
173
- : undefined;
174
- const result = (steer
175
- ? await steer(requestId, { steerId, text })
176
- : active?.requestSteering.append({ steerId, text })) ??
177
- { ok: false, reason: "request_not_active" };
178
- return result.ok
179
- ? {
180
- type: "steer_ack",
181
- requestId,
182
- steerId,
183
- accepted: true,
184
- acceptedSequence: result.update.sequence,
185
- }
186
- : {
187
- type: "steer_ack",
188
- requestId,
189
- steerId,
190
- accepted: false,
191
- reason: result.reason,
192
- };
193
225
  }
194
226
  resolveToolApproval(message) {
195
227
  this.toolApprovals.resolveRealtime(message);
@@ -0,0 +1,20 @@
1
+ import type { ModelContextCapacityIssue } from "../../runtime/config/model-context-capacity.js";
2
+ import { RuntimeSetupError } from "./runtime-setup-input.js";
3
+ export type RuntimeSetupContextWindowIssue = Readonly<{
4
+ field: "contextWindowTokens";
5
+ declaredTokens: number;
6
+ effectiveTokens: number;
7
+ reservedTokens: number;
8
+ minimumTokens: number;
9
+ allocationTokens?: number;
10
+ environmentId?: string;
11
+ }>;
12
+ export declare class RuntimeSetupContextWindowError extends RuntimeSetupError {
13
+ readonly contextWindow: RuntimeSetupContextWindowIssue;
14
+ constructor(issue: ModelContextCapacityIssue, environmentId?: string);
15
+ }
16
+ /** Project only known capacity evidence; other exceptions keep their redaction. */
17
+ export declare function throwRuntimeSetupValidationError(error: unknown, environmentId?: string): never;
18
+ export declare function runtimeSetupContextWindowErrorDetails(error: unknown): {
19
+ contextWindow?: RuntimeSetupContextWindowIssue;
20
+ };
@@ -0,0 +1,44 @@
1
+ import { RuntimeConfigValidationError } from "../../runtime/config/validation.js";
2
+ import { RuntimeSetupError } from "./runtime-setup-input.js";
3
+ function setupContextWindowMessage(issue) {
4
+ const capacity = `The effective context window is ${issue.effectiveTokens} tokens, but the configured reserves require more than ${issue.reservedTokens} tokens. Use a model-supported context window of at least ${issue.minimumTokens} tokens or adjust the configured reserves.`;
5
+ if (issue.allocationTokens === undefined)
6
+ return capacity;
7
+ if (issue.allocationTokens >= issue.minimumTokens)
8
+ return capacity;
9
+ return `${capacity} The Ollama num_ctx allocation of ${issue.allocationTokens} tokens must also support that window.`;
10
+ }
11
+ export class RuntimeSetupContextWindowError extends RuntimeSetupError {
12
+ contextWindow;
13
+ constructor(issue, environmentId) {
14
+ super("context_window_too_small", setupContextWindowMessage(issue));
15
+ this.contextWindow = {
16
+ field: "contextWindowTokens",
17
+ declaredTokens: issue.declaredTokens,
18
+ effectiveTokens: issue.effectiveTokens,
19
+ reservedTokens: issue.reservedTokens,
20
+ minimumTokens: issue.minimumTokens,
21
+ ...(issue.allocationTokens === undefined
22
+ ? {}
23
+ : { allocationTokens: issue.allocationTokens }),
24
+ ...(environmentId === undefined ? {} : { environmentId }),
25
+ };
26
+ }
27
+ }
28
+ function readSetupContextCapacityIssue(error) {
29
+ if (!(error instanceof RuntimeConfigValidationError))
30
+ return undefined;
31
+ return error.capacityIssues.find((issue) => issue.profileId === "default");
32
+ }
33
+ /** Project only known capacity evidence; other exceptions keep their redaction. */
34
+ export function throwRuntimeSetupValidationError(error, environmentId) {
35
+ const issue = readSetupContextCapacityIssue(error);
36
+ if (!issue)
37
+ throw error;
38
+ throw new RuntimeSetupContextWindowError(issue, environmentId);
39
+ }
40
+ export function runtimeSetupContextWindowErrorDetails(error) {
41
+ if (!(error instanceof RuntimeSetupContextWindowError))
42
+ return {};
43
+ return { contextWindow: error.contextWindow };
44
+ }
@@ -1,6 +1,7 @@
1
1
  import { assertConfigMutationRequest, ConfigMutationRequestError, } from "./config-mutation-request.js";
2
2
  import { readBody, readJsonBody, sendJson } from "./http.js";
3
3
  import { RuntimeSetupError } from "./runtime-setup-input.js";
4
+ import { runtimeSetupContextWindowErrorDetails } from "./runtime-setup-context-window.js";
4
5
  export class RuntimeSetupRoutes {
5
6
  service;
6
7
  constructor(service) {
@@ -43,6 +44,7 @@ export class RuntimeSetupRoutes {
43
44
  error instanceof ConfigMutationRequestError;
44
45
  sendJson(params.response, isPublicError ? error.statusCode : 400, {
45
46
  ok: false,
47
+ ...runtimeSetupContextWindowErrorDetails(error),
46
48
  error: error instanceof RuntimeSetupError
47
49
  ? error.code
48
50
  : "runtime_setup_failed",
@@ -2,6 +2,7 @@ import { mkdtemp, rm, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { loadRuntimeConfig } from "../../runtime/config.js";
4
4
  import { isRecord } from "../../runtime/config/utils.js";
5
+ import { throwRuntimeSetupValidationError } from "./runtime-setup-context-window.js";
5
6
  /** Validate complete effective configuration in isolation before replacing local files. */
6
7
  export async function validateRuntimeSetupPlan(params) {
7
8
  const staging = await mkdtemp(join(params.rootDir, ".runtime-setup-validation-"));
@@ -26,8 +27,14 @@ export async function validateRuntimeSetupPlan(params) {
26
27
  ? Object.keys(environment.profiles)
27
28
  : [];
28
29
  const environments = profileIds.length ? profileIds : [undefined];
29
- for (const profileId of environments)
30
- loadRuntimeConfig({ rootDir: params.rootDir, configPath, profileId });
30
+ for (const profileId of environments) {
31
+ try {
32
+ loadRuntimeConfig({ rootDir: params.rootDir, configPath, profileId });
33
+ }
34
+ catch (error) {
35
+ throwRuntimeSetupValidationError(error, profileId);
36
+ }
37
+ }
31
38
  }
32
39
  finally {
33
40
  await rm(staging, { recursive: true, force: true });
@@ -3,6 +3,7 @@ import type { RuntimeEnvironment, JsonObject } from "./contracts.js";
3
3
  import { WebSessionReadStates } from "../session-read-state/service.js";
4
4
  import type { WorkspaceChangeNotifier } from "./workspace-notifications.js";
5
5
  type SessionRouteRequest = {
6
+ url?: URL;
6
7
  method: string;
7
8
  segments: string[];
8
9
  body: JsonObject | null;
@@ -1,3 +1,4 @@
1
+ import { historyPageOptions, publicHistorySnapshot } from "./history-pagination.js";
1
2
  import { deleteSessionWithAttachments } from "../../runtime/session/session-attachment-deletion.js";
2
3
  import { deleteSessionAttachmentsIfSupported } from "./attachment-routes.js";
3
4
  import { sendJson } from "./http.js";
@@ -34,13 +35,24 @@ export class WebSessionRoutes {
34
35
  });
35
36
  return true;
36
37
  }
38
+ if (method === "POST" && sessionId === "page" && !action) {
39
+ sendJson(response, 200, { ok: true, ...(await this.readStates.list(environmentId, body ?? {})) });
40
+ return true;
41
+ }
37
42
  if (!sessionId)
38
43
  return false;
39
44
  const sessions = environment.services.sessions;
40
45
  if (method === "GET" && action === "messages") {
41
- const snapshot = await sessions.getSessionSnapshot(sessionId, {
42
- includeRequests: true,
43
- });
46
+ let snapshot;
47
+ try {
48
+ snapshot = await sessions.getSessionSnapshot(sessionId, historyPageOptions(request.url, environment.services.config));
49
+ }
50
+ catch (error) {
51
+ if (!(error instanceof Error) || error.message !== "history_cursor_stale")
52
+ throw error;
53
+ sendJson(response, 409, { ok: false, error: error.message });
54
+ return true;
55
+ }
44
56
  if (!snapshot) {
45
57
  sendJson(response, 404, {
46
58
  ok: false,
@@ -52,7 +64,7 @@ export class WebSessionRoutes {
52
64
  }
53
65
  sendJson(response, 200, {
54
66
  ok: true,
55
- ...snapshot,
67
+ ...publicHistorySnapshot(snapshot),
56
68
  readState: await this.readStates.project(environmentId, snapshot),
57
69
  });
58
70
  return true;
@@ -1,3 +1,4 @@
1
+ import { historyPageOptions, publicHistorySnapshot } from "./history-pagination.js";
1
2
  import { ensureSparkSession } from "../../sessions/spark-session.js";
2
3
  import { acceptConfigMutationRequest } from "./config-mutation-request.js";
3
4
  import { loadSparkChatConfiguration, readSparkChatConfigurationUpdate } from "./spark-chat-configuration.js";
@@ -40,11 +41,11 @@ export class SparkChatRoutes {
40
41
  if (update)
41
42
  await environment.services.passiveLearning.configure(update);
42
43
  const configuration = await loadSparkChatConfiguration(environment.services.passiveLearning);
43
- const snapshot = await environment.services.sessions.getSessionSnapshot(session.id, { includeRequests: true });
44
+ const snapshot = await environment.services.sessions.getSessionSnapshot(session.id, historyPageOptions(new URL(input.request.url ?? "/", "http://localhost"), environment.services.config));
44
45
  if (!snapshot)
45
46
  throw new Error("spark_chat_unavailable");
46
47
  sendJson(input.response, 200, {
47
- ok: true, sessionId: session.id, ...configuration, snapshot,
48
+ ok: true, sessionId: session.id, ...configuration, snapshot: publicHistorySnapshot(snapshot),
48
49
  readState: await this.reads.project(input.environmentId, snapshot),
49
50
  });
50
51
  return true;
@@ -52,7 +53,7 @@ export class SparkChatRoutes {
52
53
  catch (error) {
53
54
  const code = error instanceof Error ? error.message : "spark_chat_unavailable";
54
55
  const invalid = ["spark_chat_preferences_invalid", "invalid_spark_tool_permission_mode", "visible_message_ids_invalid", "visible_message_receipts_invalid"].includes(code);
55
- const stale = ["read_generation_changed", "visible_message_receipt_stale"].includes(code);
56
+ const stale = ["read_generation_changed", "visible_message_receipt_stale", "history_cursor_stale"].includes(code);
56
57
  sendJson(input.response, invalid ? 400 : 409, {
57
58
  ok: false, error: invalid || stale ? code : "spark_chat_unavailable",
58
59
  });
@@ -1,9 +1,11 @@
1
- import { isPluginToolSelected, normalizePluginSelection, } from "../runtime/plugins/selection.js";
1
+ import { isPluginToolSelected, isPluginDisabledById, normalizePluginSelection, } from "../runtime/plugins/selection.js";
2
2
  export function pluginParentBlockReason(pluginId, selection) {
3
3
  if (!selection.enabled)
4
4
  return "Plugins are disabled globally.";
5
5
  if (selection.deny.includes("*"))
6
6
  return "The global deny rule blocks all plugins.";
7
+ if (isPluginDisabledById(pluginId, selection))
8
+ return "Enable this plugin before changing its capabilities.";
7
9
  if (selection.deny.includes(pluginId))
8
10
  return "Enable this plugin before changing its capabilities.";
9
11
  return undefined;
@@ -25,6 +27,7 @@ function isCapabilityAllowed(params) {
25
27
  ...params.current,
26
28
  enabled: true,
27
29
  deny: [],
30
+ disabledPluginIds: [],
28
31
  }),
29
32
  });
30
33
  }
@@ -0,0 +1,12 @@
1
+ import type { PluginConfigurationDeclaration } from "../runtime/plugins/configuration-context.js";
2
+ import { type PluginLocalConfiguration } from "../runtime/plugins/configuration-store.js";
3
+ export declare function parsePluginConfigurationUpdate(input: unknown, declaration: PluginConfigurationDeclaration, previous?: PluginLocalConfiguration): {
4
+ revision: string;
5
+ configuration: {
6
+ settings: Record<string, unknown>;
7
+ secrets: Record<string, {
8
+ env: string;
9
+ value: string | null;
10
+ }>;
11
+ };
12
+ };
@@ -0,0 +1,68 @@
1
+ import { clearRetainedPluginSecrets, requireRetainedSecretClearedBeforeReplacement, } from "./plugin-configuration-retained-secrets.js";
2
+ import { pluginSettingMatchesDefault } from "../runtime/plugins/configuration-settings.js";
3
+ import { isRecord } from "../runtime/config/utils.js";
4
+ import { PluginConfigurationError, } from "../runtime/plugins/configuration-store.js";
5
+ function invalidConfiguration(message) {
6
+ throw new PluginConfigurationError("invalid_plugin_configuration", message);
7
+ }
8
+ function parseSettings(input, declaration) {
9
+ if (!isRecord(input))
10
+ return invalidConfiguration("Plugin settings must be an object.");
11
+ const defaults = declaration.settings?.defaults ?? {};
12
+ for (const [name, value] of Object.entries(input)) {
13
+ if (!Object.hasOwn(defaults, name))
14
+ return invalidConfiguration("Only declared plugin settings can be edited.");
15
+ if (!pluginSettingMatchesDefault(value, defaults[name]))
16
+ return invalidConfiguration(`The value for ${name} must match its default type.`);
17
+ }
18
+ return input;
19
+ }
20
+ function parseSecretChanges(input, declaration, previous) {
21
+ if (!isRecord(input))
22
+ return invalidConfiguration("Plugin secrets must be an object.");
23
+ const declarations = declaration.secrets ?? {};
24
+ const changes = Object.entries(input).map(([name, change]) => {
25
+ if (!Object.hasOwn(declarations, name))
26
+ return invalidConfiguration("Only declared plugin secrets can be edited.");
27
+ requireRetainedSecretClearedBeforeReplacement(name, declaration, previous);
28
+ if (!isRecord(change))
29
+ return invalidConfiguration("Choose how to update each secret.");
30
+ if (change.action === "clear") {
31
+ if (Object.keys(change).length !== 1)
32
+ return invalidConfiguration("Clear accepts no secret value.");
33
+ return [name, { env: declarations[name].env, value: null }];
34
+ }
35
+ if (change.action !== "set")
36
+ return invalidConfiguration("A secret change must be set or clear; omit it to keep the current value.");
37
+ if (Object.keys(change).some((key) => !["action", "value"].includes(key)))
38
+ return invalidConfiguration("Unsupported secret change.");
39
+ if (typeof change.value !== "string" || !change.value.trim())
40
+ return invalidConfiguration("Enter a non-empty secret or explicitly clear it.");
41
+ return [
42
+ name,
43
+ { env: declarations[name].env, value: change.value },
44
+ ];
45
+ });
46
+ return { ...previous?.secrets, ...Object.fromEntries(changes) };
47
+ }
48
+ export function parsePluginConfigurationUpdate(input, declaration, previous) {
49
+ if (!isRecord(input))
50
+ return invalidConfiguration("Reload plugin configuration before saving.");
51
+ if (Object.keys(input).some((key) => !["revision", "settings", "secrets", "clearRetainedSecrets"].includes(key)))
52
+ return invalidConfiguration("Unsupported plugin configuration fields.");
53
+ if (typeof input.revision !== "string" || !input.revision)
54
+ return invalidConfiguration("Reload plugin configuration before saving.");
55
+ if (Buffer.byteLength(JSON.stringify(input)) > 128 * 1024)
56
+ return invalidConfiguration("Plugin configuration is too large.");
57
+ const kept = {
58
+ settings: previous?.settings ?? {},
59
+ secrets: clearRetainedPluginSecrets(input.clearRetainedSecrets, declaration, previous),
60
+ };
61
+ return {
62
+ revision: input.revision,
63
+ configuration: {
64
+ settings: parseSettings(input.settings, declaration),
65
+ secrets: parseSecretChanges(input.secrets ?? {}, declaration, kept),
66
+ },
67
+ };
68
+ }
@@ -0,0 +1,9 @@
1
+ import type { PluginConfigurationDeclaration } from "../runtime/plugins/configuration-context.js";
2
+ import { type PluginLocalConfiguration } from "../runtime/plugins/configuration-store.js";
3
+ export declare function retainedPluginSecrets(declaration: PluginConfigurationDeclaration, local?: PluginLocalConfiguration): {
4
+ name: string;
5
+ env: string;
6
+ configured: boolean;
7
+ }[];
8
+ export declare function clearRetainedPluginSecrets(input: unknown, declaration: PluginConfigurationDeclaration, previous?: PluginLocalConfiguration): PluginLocalConfiguration["secrets"];
9
+ export declare function requireRetainedSecretClearedBeforeReplacement(name: string, declaration: PluginConfigurationDeclaration, previous?: PluginLocalConfiguration): void;
@@ -0,0 +1,48 @@
1
+ import { isRecord } from "../runtime/config/utils.js";
2
+ import { PluginConfigurationError, } from "../runtime/plugins/configuration-store.js";
3
+ function isDeclaredSecretBinding(declaration, name, env) {
4
+ const secrets = declaration.secrets ?? {};
5
+ if (!Object.hasOwn(secrets, name))
6
+ return false;
7
+ return secrets[name].env === env;
8
+ }
9
+ export function retainedPluginSecrets(declaration, local) {
10
+ return Object.entries(local?.secrets ?? {})
11
+ .filter(([name, saved]) => !isDeclaredSecretBinding(declaration, name, saved.env))
12
+ .map(([name, saved]) => ({
13
+ name,
14
+ env: saved.env,
15
+ configured: Boolean(saved.value?.trim()),
16
+ }));
17
+ }
18
+ function invalidRetainedSecretChange(message) {
19
+ throw new PluginConfigurationError("invalid_plugin_configuration", message);
20
+ }
21
+ export function clearRetainedPluginSecrets(input, declaration, previous) {
22
+ const kept = { ...previous?.secrets };
23
+ if (input === undefined)
24
+ return kept;
25
+ if (!Array.isArray(input))
26
+ return invalidRetainedSecretChange("Choose which unused saved keys to delete.");
27
+ for (const entry of input) {
28
+ if (!isRecord(entry))
29
+ return invalidRetainedSecretChange("Choose an unused saved key to delete.");
30
+ if (Object.keys(entry).some((key) => !["name", "env"].includes(key)))
31
+ return invalidRetainedSecretChange("An unused key removal accepts only its name and environment binding.");
32
+ if (typeof entry.name !== "string" || typeof entry.env !== "string")
33
+ return invalidRetainedSecretChange("An unused key removal requires its name and environment binding.");
34
+ if (!Object.hasOwn(kept, entry.name) || kept[entry.name].env !== entry.env)
35
+ return invalidRetainedSecretChange("The unused saved key changed. Reload the form before deleting it.");
36
+ if (isDeclaredSecretBinding(declaration, entry.name, entry.env))
37
+ return invalidRetainedSecretChange("Use the declared key's Clear value action to clear it.");
38
+ delete kept[entry.name];
39
+ }
40
+ return kept;
41
+ }
42
+ export function requireRetainedSecretClearedBeforeReplacement(name, declaration, previous) {
43
+ if (!previous || !Object.hasOwn(previous.secrets, name))
44
+ return;
45
+ if (isDeclaredSecretBinding(declaration, name, previous.secrets[name].env))
46
+ return;
47
+ throw new PluginConfigurationError("invalid_plugin_configuration", `Delete the unused saved key ${name} explicitly before configuring its new environment binding.`);
48
+ }
@@ -0,0 +1,52 @@
1
+ import type { ConfigFileTransaction } from "../runtime/adapters/config-file-transaction.js";
2
+ import type { PluginManagementOptions } from "./plugin-management-service.js";
3
+ export declare function getRuntimePluginConfiguration(options: PluginManagementOptions, pluginId: string): {
4
+ pluginId: string;
5
+ revision: string;
6
+ scope: "installation";
7
+ defaults: Readonly<Record<string, unknown>>;
8
+ settings: Record<string, unknown>;
9
+ settingOverrides: string[];
10
+ retainedSecrets: {
11
+ name: string;
12
+ env: string;
13
+ configured: boolean;
14
+ }[];
15
+ secrets: {
16
+ name: string;
17
+ env: string;
18
+ required: boolean;
19
+ configured: boolean;
20
+ locallyConfigured: boolean;
21
+ }[];
22
+ };
23
+ /** Configuration and package selection commit under the same locks as Apply. */
24
+ export declare function saveRuntimePluginConfiguration<T>(options: PluginManagementOptions, params: {
25
+ pluginId: string;
26
+ input: unknown;
27
+ transaction?: ConfigFileTransaction;
28
+ installation?: boolean;
29
+ commit?: () => Promise<T>;
30
+ }): Promise<{
31
+ result: Awaited<T> | undefined;
32
+ configuration: {
33
+ pluginId: string;
34
+ revision: string;
35
+ scope: "installation";
36
+ defaults: Readonly<Record<string, unknown>>;
37
+ settings: Record<string, unknown>;
38
+ settingOverrides: string[];
39
+ retainedSecrets: {
40
+ name: string;
41
+ env: string;
42
+ configured: boolean;
43
+ }[];
44
+ secrets: {
45
+ name: string;
46
+ env: string;
47
+ required: boolean;
48
+ configured: boolean;
49
+ locallyConfigured: boolean;
50
+ }[];
51
+ };
52
+ }>;
@@ -0,0 +1,66 @@
1
+ import { realpathSync } from "node:fs";
2
+ import { inspectRuntimeConfigFileWithMeta } from "../runtime/config/loader.js";
3
+ import { ABOT_RUNTIME_EXTENSION } from "../plugin-contract/manifest.js";
4
+ import { discoverConfiguredRuntimePluginManifests } from "../runtime/plugins/configured-manifests.js";
5
+ import { configuredPluginSecret, } from "../runtime/plugins/configuration-context.js";
6
+ import { PluginConfigurationError, readPluginConfigurationStore, } from "../runtime/plugins/configuration-store.js";
7
+ import { commitPluginConfigurationStore, withPluginConfigurationLock, } from "../runtime/plugins/configuration-write.js";
8
+ import { withConfigDashboardRootTransaction } from "./config-dashboard-save-transaction.js";
9
+ import { parsePluginConfigurationUpdate } from "./plugin-configuration-input.js";
10
+ import { pluginConfigurationRevision, projectPluginConfiguration, } from "./plugin-configuration-view.js";
11
+ function installedPluginDeclaration(rootDir, pluginId) {
12
+ const plugin = discoverConfiguredRuntimePluginManifests(rootDir).find((entry) => entry.manifest.name === pluginId);
13
+ if (!plugin)
14
+ throw new PluginConfigurationError("plugin_not_found", "The selected plugin is not installed.", 404);
15
+ const extension = plugin.manifest.extensions[ABOT_RUNTIME_EXTENSION];
16
+ return { settings: extension.settings, secrets: extension.secrets };
17
+ }
18
+ export function getRuntimePluginConfiguration(options, pluginId) {
19
+ return projectPluginConfiguration(pluginId, installedPluginDeclaration(options.rootDir, pluginId), readPluginConfigurationStore(options.rootDir));
20
+ }
21
+ function requireInstallationSecrets(declaration, configuration) {
22
+ for (const [name, secret] of Object.entries(declaration.secrets ?? {})) {
23
+ if (!secret.required)
24
+ continue;
25
+ if (configuredPluginSecret(name, secret, configuration))
26
+ continue;
27
+ throw new PluginConfigurationError("plugin_secret_required", `Configure the required secret ${name} before installing.`);
28
+ }
29
+ }
30
+ /** Configuration and package selection commit under the same locks as Apply. */
31
+ export async function saveRuntimePluginConfiguration(options, params) {
32
+ const source = inspectRuntimeConfigFileWithMeta(options.rootDir, options.configPath);
33
+ if (!source.exists)
34
+ throw new PluginConfigurationError("runtime_setup_required", "Complete Runtime setup before configuring plugins.", 409);
35
+ const rootDir = realpathSync(options.rootDir);
36
+ return withConfigDashboardRootTransaction(realpathSync(source.path), params.transaction, () => withPluginConfigurationLock(rootDir, async () => {
37
+ options.requireMutationIdle?.();
38
+ const declaration = installedPluginDeclaration(rootDir, params.pluginId);
39
+ const previous = readPluginConfigurationStore(rootDir);
40
+ const local = Object.hasOwn(previous.plugins, params.pluginId)
41
+ ? previous.plugins[params.pluginId]
42
+ : undefined;
43
+ if (params.installation && params.input === undefined) {
44
+ requireInstallationSecrets(declaration, local);
45
+ return {
46
+ result: await params.commit?.(),
47
+ configuration: projectPluginConfiguration(params.pluginId, declaration, previous),
48
+ };
49
+ }
50
+ const update = parsePluginConfigurationUpdate(params.input, declaration, local);
51
+ if (update.revision !==
52
+ pluginConfigurationRevision(params.pluginId, declaration, previous))
53
+ throw new PluginConfigurationError("plugin_configuration_changed", "Plugin configuration changed. Reload the form before saving.", 409);
54
+ if (params.installation)
55
+ requireInstallationSecrets(declaration, update.configuration);
56
+ options.requireMutationIdle?.();
57
+ const result = await commitPluginConfigurationStore(rootDir, previous, {
58
+ ...previous.plugins,
59
+ [params.pluginId]: update.configuration,
60
+ }, async () => params.commit?.());
61
+ return {
62
+ result,
63
+ configuration: projectPluginConfiguration(params.pluginId, declaration, readPluginConfigurationStore(rootDir)),
64
+ };
65
+ }));
66
+ }