@abot-ai/runtime 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +2 -0
  2. package/dist/src/bridge/request-steering.js +60 -15
  3. package/dist/src/capabilities/normal-invocation/contracts.d.ts +3 -0
  4. package/dist/src/capabilities/normal-invocation/output-channels.d.ts +10 -0
  5. package/dist/src/capabilities/normal-invocation/output-channels.js +29 -0
  6. package/dist/src/capabilities/normal-invocation/validator.js +4 -2
  7. package/dist/src/capabilities/tool-types.d.ts +1 -1
  8. package/dist/src/cli/host-companion-bundle.mjs +7570 -6781
  9. package/dist/src/cli/host-companion-entry.js +5 -22
  10. package/dist/src/cli/host-companion-input.d.ts +3 -0
  11. package/dist/src/cli/host-companion-input.js +21 -0
  12. package/dist/src/cli/host-companion-lifecycle.d.ts +11 -0
  13. package/dist/src/cli/host-companion-lifecycle.js +32 -0
  14. package/dist/src/cli/host-companion-setup-target.d.ts +4 -0
  15. package/dist/src/cli/host-companion-setup-target.js +17 -0
  16. package/dist/src/cli/host-companion-startup.d.ts +2 -0
  17. package/dist/src/cli/host-companion-startup.js +7 -2
  18. package/dist/src/cli/host-companion.d.ts +6 -0
  19. package/dist/src/cli/host-companion.js +30 -27
  20. package/dist/src/cli/windows-companion-store-entry.d.ts +9 -0
  21. package/dist/src/cli/windows-companion-store-entry.js +67 -0
  22. package/dist/src/computer-access/command-output-capture.d.ts +37 -0
  23. package/dist/src/computer-access/command-output-capture.js +136 -0
  24. package/dist/src/computer-access/command-output-retention.d.ts +5 -0
  25. package/dist/src/computer-access/command-output-retention.js +90 -0
  26. package/dist/src/computer-access/command-output.d.ts +7 -0
  27. package/dist/src/computer-access/command-output.js +1 -0
  28. package/dist/src/computer-access/commands.d.ts +1 -0
  29. package/dist/src/computer-access/commands.js +1 -1
  30. package/dist/src/computer-access/companion/command-output-protocol.d.ts +12 -0
  31. package/dist/src/computer-access/companion/command-output-protocol.js +28 -0
  32. package/dist/src/computer-access/companion/command-output.d.ts +13 -0
  33. package/dist/src/computer-access/companion/command-output.js +110 -0
  34. package/dist/src/computer-access/companion/install-link-macos.d.ts +7 -0
  35. package/dist/src/computer-access/companion/install-link-macos.js +48 -0
  36. package/dist/src/computer-access/companion/install-link-registration.d.ts +4 -0
  37. package/dist/src/computer-access/companion/install-link-registration.js +184 -0
  38. package/dist/src/computer-access/companion/install-link-windows.d.ts +4 -0
  39. package/dist/src/computer-access/companion/install-link-windows.js +65 -0
  40. package/dist/src/computer-access/companion/install-link.d.ts +9 -0
  41. package/dist/src/computer-access/companion/install-link.js +54 -0
  42. package/dist/src/computer-access/companion/native-messages.js +3 -0
  43. package/dist/src/computer-access/companion/native-session.d.ts +1 -0
  44. package/dist/src/computer-access/companion/native-session.js +14 -2
  45. package/dist/src/computer-access/companion/native-supervisor.js +1 -0
  46. package/dist/src/computer-access/companion/notification-windows.d.ts +1 -1
  47. package/dist/src/computer-access/companion/notification-windows.js +8 -3
  48. package/dist/src/computer-access/companion/protocol.d.ts +1 -1
  49. package/dist/src/computer-access/companion/protocol.js +6 -0
  50. package/dist/src/computer-access/companion/release-version.d.ts +1 -1
  51. package/dist/src/computer-access/companion/release-version.js +1 -1
  52. package/dist/src/computer-access/companion/windows-store/connection-error.d.ts +7 -0
  53. package/dist/src/computer-access/companion/windows-store/connection-error.js +19 -0
  54. package/dist/src/computer-access/companion/windows-store/connection-link.d.ts +13 -0
  55. package/dist/src/computer-access/companion/windows-store/connection-link.js +109 -0
  56. package/dist/src/computer-access/companion/windows-store/identity.d.ts +13 -0
  57. package/dist/src/computer-access/companion/windows-store/identity.js +13 -0
  58. package/dist/src/computer-access/companion/windows-store/lifecycle.d.ts +5 -0
  59. package/dist/src/computer-access/companion/windows-store/lifecycle.js +90 -0
  60. package/dist/src/computer-access/contracts.d.ts +1 -1
  61. package/dist/src/computer-access/handlers.d.ts +2 -1
  62. package/dist/src/computer-access/handlers.js +5 -1
  63. package/dist/src/computer-access/process-capture.d.ts +6 -0
  64. package/dist/src/computer-access/process-capture.js +1 -0
  65. package/dist/src/computer-access/process-result.d.ts +2 -0
  66. package/dist/src/computer-access/process-result.js +14 -6
  67. package/dist/src/computer-access/process-runner.d.ts +2 -1
  68. package/dist/src/computer-access/process-runner.js +21 -13
  69. package/dist/src/model-gateway/server/configuration.d.ts +2 -0
  70. package/dist/src/model-gateway/server/configuration.js +73 -21
  71. package/dist/src/plugin-contract/install-source.d.ts +13 -0
  72. package/dist/src/plugin-contract/install-source.js +99 -0
  73. package/dist/src/plugin-contract/manifest.d.ts +2 -1
  74. package/dist/src/plugin-sdk/computer-access.d.ts +8 -0
  75. package/dist/src/plugin-sdk/computer-access.js +5 -0
  76. package/dist/src/runtime/adapters/in-memory-session-store.js +6 -16
  77. package/dist/src/runtime/admin/config-control.js +2 -1
  78. package/dist/src/runtime/automations/catalog.d.ts +3 -0
  79. package/dist/src/runtime/automations/catalog.js +1 -0
  80. package/dist/src/runtime/automations/model-dependency-projection.d.ts +2 -0
  81. package/dist/src/runtime/automations/service.d.ts +2 -0
  82. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.d.ts +10 -5
  83. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.js +8 -7
  84. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.d.ts +2 -2
  85. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.js +2 -2
  86. package/dist/src/runtime/capabilities/automation-builder/tool-contract.d.ts +2 -2
  87. package/dist/src/runtime/capabilities/automations/authoring-catalog.js +1 -1
  88. package/dist/src/runtime/capabilities/automations/authoring-preparation.d.ts +11 -5
  89. package/dist/src/runtime/capabilities/automations/tool-module.js +1 -1
  90. package/dist/src/runtime/capabilities/request-permission-catalog.d.ts +3 -1
  91. package/dist/src/runtime/capabilities/request-permission-catalog.js +21 -2
  92. package/dist/src/runtime/capabilities/request-permission-tool-registry.d.ts +2 -1
  93. package/dist/src/runtime/capabilities/request-permission-tool-registry.js +18 -10
  94. package/dist/src/runtime/capabilities/request-runtime-tool-registry.d.ts +2 -0
  95. package/dist/src/runtime/capabilities/request-runtime-tool-registry.js +1 -1
  96. package/dist/src/runtime/capabilities/scheduling/create-operations.d.ts +6 -0
  97. package/dist/src/runtime/config/builders.js +6 -5
  98. package/dist/src/runtime/config/effective-model-config-validation.js +4 -35
  99. package/dist/src/runtime/config/fields.js +15 -0
  100. package/dist/src/runtime/config/model-context-capacity.d.ts +20 -0
  101. package/dist/src/runtime/config/model-context-capacity.js +55 -0
  102. package/dist/src/runtime/config/model-execution-policy.d.ts +5 -1
  103. package/dist/src/runtime/config/model-execution-policy.js +16 -0
  104. package/dist/src/runtime/config/model-plugin-config.d.ts +8 -0
  105. package/dist/src/runtime/config/model-plugin-config.js +40 -0
  106. package/dist/src/runtime/config/schema.js +5 -1
  107. package/dist/src/runtime/config/validation/model-profile-validation.js +2 -0
  108. package/dist/src/runtime/config/validation/runtime-config-validation-contract.d.ts +3 -1
  109. package/dist/src/runtime/config/validation/runtime-config-validation-contract.js +3 -1
  110. package/dist/src/runtime/config/validation/runtime-root-section-validation.js +11 -4
  111. package/dist/src/runtime/config/validation/web-ui-config-validation.js +3 -2
  112. package/dist/src/runtime/config/web-ui.d.ts +5 -0
  113. package/dist/src/runtime/config/web-ui.js +5 -0
  114. package/dist/src/runtime/config.js +2 -0
  115. package/dist/src/runtime/local-application.d.ts +2 -0
  116. package/dist/src/runtime/local-host/app-owner.js +50 -6
  117. package/dist/src/runtime/local-host/app-request-control.d.ts +3 -1
  118. package/dist/src/runtime/local-host/app-request-control.js +91 -11
  119. package/dist/src/runtime/local-host/client-requests.js +32 -5
  120. package/dist/src/runtime/local-host/client-services.d.ts +2 -0
  121. package/dist/src/runtime/local-host/local-request-diagnostics.d.ts +9 -0
  122. package/dist/src/runtime/local-host/local-request-diagnostics.js +47 -0
  123. package/dist/src/runtime/local-host/saved-approvals.js +23 -2
  124. package/dist/src/runtime/model/model-selection.js +4 -1
  125. package/dist/src/runtime/observability/request-control-diagnostics.d.ts +6 -0
  126. package/dist/src/runtime/observability/request-control-diagnostics.js +52 -0
  127. package/dist/src/runtime/plugins/configuration-context.d.ts +9 -0
  128. package/dist/src/runtime/plugins/configuration-context.js +42 -0
  129. package/dist/src/runtime/plugins/configuration-settings.d.ts +2 -0
  130. package/dist/src/runtime/plugins/configuration-settings.js +26 -0
  131. package/dist/src/runtime/plugins/configuration-store.d.ts +23 -0
  132. package/dist/src/runtime/plugins/configuration-store.js +100 -0
  133. package/dist/src/runtime/plugins/configuration-write.d.ts +5 -0
  134. package/dist/src/runtime/plugins/configuration-write.js +58 -0
  135. package/dist/src/runtime/plugins/installation/archive.d.ts +2 -0
  136. package/dist/src/runtime/plugins/installation/archive.js +107 -0
  137. package/dist/src/runtime/plugins/installation/github-download.d.ts +9 -0
  138. package/dist/src/runtime/plugins/installation/github-download.js +72 -0
  139. package/dist/src/runtime/plugins/installation/installed-package.d.ts +9 -0
  140. package/dist/src/runtime/plugins/installation/installed-package.js +66 -0
  141. package/dist/src/runtime/plugins/installation/package.d.ts +45 -0
  142. package/dist/src/runtime/plugins/installation/package.js +79 -0
  143. package/dist/src/runtime/plugins/installation/portable-path.d.ts +2 -0
  144. package/dist/src/runtime/plugins/installation/portable-path.js +10 -0
  145. package/dist/src/runtime/plugins/installation/publication.d.ts +10 -0
  146. package/dist/src/runtime/plugins/installation/publication.js +17 -0
  147. package/dist/src/runtime/plugins/installation/service.d.ts +41 -0
  148. package/dist/src/runtime/plugins/installation/service.js +80 -0
  149. package/dist/src/runtime/plugins/loader.js +15 -29
  150. package/dist/src/runtime/plugins/manifest-projection.js +1 -0
  151. package/dist/src/runtime/plugins/manifest-validator.js +3 -0
  152. package/dist/src/runtime/plugins/module-cache.d.ts +2 -0
  153. package/dist/src/runtime/plugins/module-cache.js +19 -0
  154. package/dist/src/runtime/plugins/selection.d.ts +2 -0
  155. package/dist/src/runtime/plugins/selection.js +16 -11
  156. package/dist/src/runtime/ports.d.ts +6 -4
  157. package/dist/src/runtime/request/dependencies.d.ts +2 -1
  158. package/dist/src/runtime/request/execution-payload-compacted-evidence.d.ts +1 -1
  159. package/dist/src/runtime/request/handler.js +8 -0
  160. package/dist/src/runtime/request/prepared-execution.js +6 -1
  161. package/dist/src/runtime/request/request-steering.d.ts +4 -0
  162. package/dist/src/runtime/request/request-steering.js +37 -12
  163. package/dist/src/runtime/request/worker-capability-composition.d.ts +2 -0
  164. package/dist/src/runtime/request/worker-capability-composition.js +4 -1
  165. package/dist/src/runtime/scheduler/journal-index-state.d.ts +1 -1
  166. package/dist/src/sessions/assistant-initiative-message.d.ts +3 -0
  167. package/dist/src/sessions/assistant-initiative-message.js +12 -0
  168. package/dist/src/sessions/assistant-initiative.d.ts +2 -2
  169. package/dist/src/sessions/assistant-initiative.js +1 -7
  170. package/dist/src/sessions/durable-session-commit.d.ts +2 -1
  171. package/dist/src/sessions/durable-session-commit.js +6 -1
  172. package/dist/src/sessions/metadata/projection.d.ts +15 -0
  173. package/dist/src/sessions/metadata/projection.js +55 -0
  174. package/dist/src/sessions/metadata/publication.d.ts +12 -0
  175. package/dist/src/sessions/metadata/publication.js +78 -0
  176. package/dist/src/sessions/metadata/source-receipt.d.ts +5 -0
  177. package/dist/src/sessions/metadata/source-receipt.js +42 -0
  178. package/dist/src/sessions/metadata/store.d.ts +7 -0
  179. package/dist/src/sessions/metadata/store.js +119 -0
  180. package/dist/src/sessions/record/projection.d.ts +3 -1
  181. package/dist/src/sessions/record/projection.js +26 -18
  182. package/dist/src/sessions/request-lifecycle/service.js +3 -3
  183. package/dist/src/sessions/session-service.d.ts +2 -4
  184. package/dist/src/sessions/session-service.js +4 -16
  185. package/dist/src/sessions/session-store.d.ts +2 -1
  186. package/dist/src/sessions/session-store.js +9 -3
  187. package/dist/src/sessions/snapshot.d.ts +17 -0
  188. package/dist/src/sessions/snapshot.js +105 -0
  189. package/dist/src/sessions/types.d.ts +2 -0
  190. package/dist/src/shared/tool-selection.d.ts +2 -0
  191. package/dist/src/shared/tool-selection.js +7 -0
  192. package/dist/src/web-ui/app/ARCHITECTURE.md +14 -0
  193. package/dist/src/web-ui/app/app.js +6 -3
  194. package/dist/src/web-ui/app/components/config-workspace/config-model.js +2 -0
  195. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +130 -0
  196. package/dist/src/web-ui/app/components/config-workspace/model-plugin-selection.js +180 -0
  197. package/dist/src/web-ui/app/components/config-workspace/model-plugin-view-state.js +114 -0
  198. package/dist/src/web-ui/app/components/config-workspace/model-rendering.js +3 -0
  199. package/dist/src/web-ui/app/components/config-workspace/model-summary.js +39 -0
  200. package/dist/src/web-ui/app/components/config-workspace/summary-rendering.js +30 -0
  201. package/dist/src/web-ui/app/components/config-workspace/workspace-events.js +37 -0
  202. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +2 -0
  203. package/dist/src/web-ui/app/components/config-workspace/workspace-persistence.js +9 -1
  204. package/dist/src/web-ui/app/components/config-workspace/workspace-view.js +23 -67
  205. package/dist/src/web-ui/app/components/config-workspace.js +11 -2
  206. package/dist/src/web-ui/app/components/conversation-view.js +36 -5
  207. package/dist/src/web-ui/app/components/dashboard/recent-conversations.js +2 -1
  208. package/dist/src/web-ui/app/components/dashboard/workspace.js +2 -1
  209. package/dist/src/web-ui/app/components/operations-summary.js +105 -0
  210. package/dist/src/web-ui/app/components/passive-learning/home.js +1 -9
  211. package/dist/src/web-ui/app/components/plugins/configuration-draft.js +34 -0
  212. package/dist/src/web-ui/app/components/plugins/configuration-editor.js +147 -0
  213. package/dist/src/web-ui/app/components/plugins/configuration-fields.js +103 -0
  214. package/dist/src/web-ui/app/components/plugins/configuration-retained-secrets.js +20 -0
  215. package/dist/src/web-ui/app/components/plugins/configuration-settings.js +108 -0
  216. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +37 -0
  217. package/dist/src/web-ui/app/components/plugins/installation.js +212 -0
  218. package/dist/src/web-ui/app/components/plugins/manager.js +160 -6
  219. package/dist/src/web-ui/app/components/plugins/removal.js +130 -0
  220. package/dist/src/web-ui/app/components/plugins/rendering.js +14 -2
  221. package/dist/src/web-ui/app/components/plugins/summary.js +54 -0
  222. package/dist/src/web-ui/app/components/plugins/tabs.js +31 -0
  223. package/dist/src/web-ui/app/components/plugins/view-state.js +3 -1
  224. package/dist/src/web-ui/app/components/runtime-setup/connection-form.js +5 -2
  225. package/dist/src/web-ui/app/components/runtime-setup/connection-state.js +9 -1
  226. package/dist/src/web-ui/app/components/runtime-setup/context-window-feedback.js +71 -0
  227. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +2 -0
  228. package/dist/src/web-ui/app/components/runtime-setup-guide.js +15 -3
  229. package/dist/src/web-ui/app/components/spark-chat/empty-state.js +1 -0
  230. package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -0
  231. package/dist/src/web-ui/app/components/system-host/connection-card.js +35 -0
  232. package/dist/src/web-ui/app/components/system-host/macos-setup.js +1 -1
  233. package/dist/src/web-ui/app/components/system-host/manager.js +45 -12
  234. package/dist/src/web-ui/app/components/system-host/rendering.js +111 -106
  235. package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +293 -0
  236. package/dist/src/web-ui/app/components/workspace-shell.js +6 -0
  237. package/dist/src/web-ui/app/computer-access-feature.js +22 -5
  238. package/dist/src/web-ui/app/configuration-feature.js +35 -2
  239. package/dist/src/web-ui/app/controllers/app-event-bindings.js +4 -1
  240. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.d.ts +1 -0
  241. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.js +7 -3
  242. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +88 -0
  243. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +9 -3
  244. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +52 -144
  245. package/dist/src/web-ui/app/controllers/history-pagination.js +111 -0
  246. package/dist/src/web-ui/app/controllers/operations-controller.d.ts +12 -0
  247. package/dist/src/web-ui/app/controllers/operations-controller.js +28 -21
  248. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.d.ts +1 -0
  249. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.js +11 -0
  250. package/dist/src/web-ui/app/controllers/session-controller.js +10 -2
  251. package/dist/src/web-ui/app/controllers/session-list-pagination.js +71 -0
  252. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +6 -4
  253. package/dist/src/web-ui/app/controllers/spark-chat-reading.js +1 -0
  254. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +24 -5
  255. package/dist/src/web-ui/app/controllers/workspace-route-controller.js +21 -19
  256. package/dist/src/web-ui/app/dashboard-feature.js +2 -2
  257. package/dist/src/web-ui/app/index.html +6 -2
  258. package/dist/src/web-ui/app/lib/history-page-messages.js +49 -0
  259. package/dist/src/web-ui/app/lib/request-lifecycle-view.js +8 -0
  260. package/dist/src/web-ui/app/lib/workspace-route.d.ts +3 -0
  261. package/dist/src/web-ui/app/lib/workspace-route.js +4 -0
  262. package/dist/src/web-ui/app/passive-learning-feature.js +0 -1
  263. package/dist/src/web-ui/app/runtime-onboarding-feature.js +3 -0
  264. package/dist/src/web-ui/app/schedules-feature.js +1 -1
  265. package/dist/src/web-ui/app/services/runtime-web-client/configuration.js +20 -0
  266. package/dist/src/web-ui/app/services/runtime-web-client/plugin-configuration.js +19 -0
  267. package/dist/src/web-ui/app/services/runtime-web-client/spark-chat.js +4 -4
  268. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  269. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +6 -1
  270. package/dist/src/web-ui/app/services/runtime-web-client.js +12 -3
  271. package/dist/src/web-ui/app/spark-chat-feature.js +76 -19
  272. package/dist/src/web-ui/app/styles/11-product-links.css +30 -0
  273. package/dist/src/web-ui/app/styles/41-plugin-configuration.css +79 -0
  274. package/dist/src/web-ui/app/styles/41-plugin-discovery.css +132 -0
  275. package/dist/src/web-ui/app/styles/41-plugin-management.css +6 -0
  276. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +173 -0
  277. package/dist/src/web-ui/app/styles/46-system-host.css +61 -107
  278. package/dist/src/web-ui/app/styles/47-config-controls.css +13 -1
  279. package/dist/src/web-ui/app/styles/54-spark-chat.css +33 -1
  280. package/dist/src/web-ui/app/styles.css +4 -0
  281. package/dist/src/web-ui/local-runtime/api-router.js +11 -6
  282. package/dist/src/web-ui/local-runtime/approval-request-attachment.js +14 -5
  283. package/dist/src/web-ui/local-runtime/configuration-activation-source.d.ts +1 -1
  284. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +9 -3
  285. package/dist/src/web-ui/local-runtime/contracts.d.ts +4 -3
  286. package/dist/src/web-ui/local-runtime/environment-registry.d.ts +5 -1
  287. package/dist/src/web-ui/local-runtime/environment-registry.js +53 -11
  288. package/dist/src/web-ui/local-runtime/history-pagination.d.ts +16 -0
  289. package/dist/src/web-ui/local-runtime/history-pagination.js +20 -0
  290. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.d.ts +16 -0
  291. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.js +68 -0
  292. package/dist/src/web-ui/local-runtime/plugin-installation-routes.d.ts +16 -0
  293. package/dist/src/web-ui/local-runtime/plugin-installation-routes.js +96 -0
  294. package/dist/src/web-ui/local-runtime/plugin-management-routes.d.ts +8 -1
  295. package/dist/src/web-ui/local-runtime/plugin-management-routes.js +17 -0
  296. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.d.ts +7 -0
  297. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.js +17 -0
  298. package/dist/src/web-ui/local-runtime/plugin-removal-routes.d.ts +18 -0
  299. package/dist/src/web-ui/local-runtime/plugin-removal-routes.js +60 -0
  300. package/dist/src/web-ui/local-runtime/realtime-controller.js +41 -2
  301. package/dist/src/web-ui/local-runtime/request-cancellation-route.js +28 -1
  302. package/dist/src/web-ui/local-runtime/request-control-observation.d.ts +19 -0
  303. package/dist/src/web-ui/local-runtime/request-control-observation.js +80 -0
  304. package/dist/src/web-ui/local-runtime/request-execution.js +69 -37
  305. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +20 -0
  306. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +44 -0
  307. package/dist/src/web-ui/local-runtime/runtime-setup-routes.js +2 -0
  308. package/dist/src/web-ui/local-runtime/runtime-setup-validation.js +9 -2
  309. package/dist/src/web-ui/local-runtime/session-routes.d.ts +1 -0
  310. package/dist/src/web-ui/local-runtime/session-routes.js +16 -4
  311. package/dist/src/web-ui/local-runtime/spark-chat-routes.js +4 -3
  312. package/dist/src/web-ui/plugin-capability-selection.js +4 -1
  313. package/dist/src/web-ui/plugin-configuration-input.d.ts +12 -0
  314. package/dist/src/web-ui/plugin-configuration-input.js +68 -0
  315. package/dist/src/web-ui/plugin-configuration-retained-secrets.d.ts +9 -0
  316. package/dist/src/web-ui/plugin-configuration-retained-secrets.js +48 -0
  317. package/dist/src/web-ui/plugin-configuration-service.d.ts +52 -0
  318. package/dist/src/web-ui/plugin-configuration-service.js +66 -0
  319. package/dist/src/web-ui/plugin-configuration-view.d.ts +25 -0
  320. package/dist/src/web-ui/plugin-configuration-view.js +45 -0
  321. package/dist/src/web-ui/plugin-disabled-selection.d.ts +7 -0
  322. package/dist/src/web-ui/plugin-disabled-selection.js +17 -0
  323. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  324. package/dist/src/web-ui/plugin-management-catalog.js +11 -1
  325. package/dist/src/web-ui/plugin-management-selection.js +22 -9
  326. package/dist/src/web-ui/plugin-management-service.d.ts +5 -1
  327. package/dist/src/web-ui/plugin-management-service.js +11 -7
  328. package/dist/src/web-ui/plugin-removal-error.d.ts +7 -0
  329. package/dist/src/web-ui/plugin-removal-error.js +16 -0
  330. package/dist/src/web-ui/plugin-removal-service.d.ts +30 -0
  331. package/dist/src/web-ui/plugin-removal-service.js +109 -0
  332. package/dist/src/web-ui/runtime-setup-gateway.d.ts +6 -2
  333. package/dist/src/web-ui/runtime-setup-gateway.js +30 -10
  334. package/dist/src/web-ui/server.js +6 -2
  335. package/dist/src/web-ui/session-read-state/overview.d.ts +42 -0
  336. package/dist/src/web-ui/session-read-state/overview.js +16 -0
  337. package/dist/src/web-ui/session-read-state/pagination.d.ts +15 -0
  338. package/dist/src/web-ui/session-read-state/pagination.js +42 -0
  339. package/dist/src/web-ui/session-read-state/projection.d.ts +4 -3
  340. package/dist/src/web-ui/session-read-state/service.d.ts +213 -20
  341. package/dist/src/web-ui/session-read-state/service.js +25 -23
  342. package/dist/src/web-ui/session-read-state/visible-messages.d.ts +3 -3
  343. package/dist/src/web-ui/system-host-setup/companion-linux.js +1 -1
  344. package/dist/src/web-ui/system-host-setup/installer-contract.d.ts +1 -1
  345. package/dist/src/web-ui/system-host-setup/installer-contract.js +2 -2
  346. package/dist/src/web-ui/system-host-setup/installers.js +0 -7
  347. package/dist/src/web-ui/system-host-setup/local-connection.d.ts +4 -1
  348. package/dist/src/web-ui/system-host-setup/local-connection.js +10 -17
  349. package/dist/src/web-ui/system-host-setup/routes.d.ts +2 -0
  350. package/dist/src/web-ui/system-host-setup/routes.js +32 -9
  351. package/dist/src/web-ui/system-host-setup/setup-mutation.d.ts +9 -0
  352. package/dist/src/web-ui/system-host-setup/setup-mutation.js +27 -0
  353. package/dist/src/web-ui/system-host-setup/windows-store-route.d.ts +13 -0
  354. package/dist/src/web-ui/system-host-setup/windows-store-route.js +68 -0
  355. package/docs/configuration.md +46 -0
  356. package/docs/installation.md +45 -24
  357. package/docs/plugins.md +165 -2
  358. package/docs/projects-and-full-plus.md +2 -6
  359. package/docs/runtime-library.md +0 -1
  360. package/docs/windows-companion-store.md +127 -0
  361. package/package.json +3 -3
  362. package/plugins/document-reader/plugin.json +1 -0
  363. package/plugins/exec/plugin.json +3 -0
  364. package/plugins/filesystem/plugin.json +2 -0
  365. package/plugins/local-search/plugin.json +1 -0
  366. package/plugins/system/README.md +43 -3
  367. package/plugins/system/plugin.json +5 -0
  368. package/plugins/system/source/companion-command-output.ts +82 -0
  369. package/plugins/system/source/host-dispatch.ts +4 -0
  370. package/plugins/system/source/index.ts +11 -5
  371. package/plugins/system/source/local-command-output.ts +61 -0
  372. package/plugins/system/source/request-system-modules.ts +2 -0
  373. package/plugins/system/src/index.cjs +474 -39
  374. package/plugins/web/README.md +2 -2
  375. package/plugins/web/plugin.json +4 -0
  376. package/runtime.config.schema.json +25 -1
  377. package/src/runtime/README.md +12 -2
  378. package/dist/src/web-ui/system-host-setup/companion-windows.d.ts +0 -2
  379. package/dist/src/web-ui/system-host-setup/companion-windows.js +0 -108
  380. package/docs/publishing.md +0 -167
@@ -0,0 +1,180 @@
1
+ import { isConfigObject } from "./config-model.js";
2
+
3
+ export function modelPluginRulesNeedRepair(config) {
4
+ if (config.plugins === undefined) return false;
5
+ if (!isConfigObject(config.plugins)) return true;
6
+ if (config.plugins.deny === undefined) return false;
7
+ if (!Array.isArray(config.plugins.deny)) return true;
8
+ return config.plugins.deny.some((value) => typeof value !== "string");
9
+ }
10
+
11
+ function modelDeniedSelectors(config) {
12
+ if (modelPluginRulesNeedRepair(config)) return [];
13
+ return (config.plugins?.deny || []).map((entry) => entry.trim());
14
+ }
15
+
16
+ // Browser projection of the existing deny contract; Runtime remains its enforcer.
17
+ function selectorMatchesCapability(selector, pluginId, capabilityId) {
18
+ return (
19
+ selector === "*" ||
20
+ selector === pluginId ||
21
+ selector === capabilityId ||
22
+ selector === `${pluginId}.${capabilityId}`
23
+ );
24
+ }
25
+
26
+ function selectorEscapesModelTarget(plugins, pluginId, capabilityId, selector) {
27
+ return plugins.some((plugin) =>
28
+ (plugin.capabilities || []).some((capability) => {
29
+ if (plugin.id === pluginId && capabilityId === undefined) return false;
30
+ if (plugin.id === pluginId && capability.id === capabilityId)
31
+ return false;
32
+ return selectorMatchesCapability(selector, plugin.id, capability.id);
33
+ }),
34
+ );
35
+ }
36
+
37
+ function modelPluginGlobalBlockReason(plugin) {
38
+ if (plugin.blockedByGlobalPolicy)
39
+ return "Blocked by the global plugin policy.";
40
+ if (plugin.pluginEnabled === false)
41
+ return "Enable this plugin in global plugin settings first.";
42
+ if (plugin.state === "disabled")
43
+ return "No tools are available in global plugin settings.";
44
+ return "";
45
+ }
46
+
47
+ function modelPluginControlBlockReason(config, plugin, plugins, denied) {
48
+ if (modelPluginRulesNeedRepair(config))
49
+ return "Repair this model's plugin restrictions before changing tools.";
50
+ if (denied.includes("*"))
51
+ return "The saved * rule blocks every plugin for this model.";
52
+ const globalReason = modelPluginGlobalBlockReason(plugin);
53
+ if (globalReason) return globalReason;
54
+ if (selectorEscapesModelTarget(plugins, plugin.id, undefined, plugin.id))
55
+ return "This plugin selector also affects tools in another plugin. Review the saved rules.";
56
+ return "";
57
+ }
58
+
59
+ function modelCapabilityControlBlockReason(
60
+ config,
61
+ plugin,
62
+ capability,
63
+ plugins,
64
+ denied,
65
+ ) {
66
+ if (modelPluginRulesNeedRepair(config))
67
+ return "Repair this model's plugin restrictions before changing tools.";
68
+ if (denied.includes("*"))
69
+ return "The saved * rule blocks every tool for this model.";
70
+ if (denied.includes(plugin.id))
71
+ return "Enable this plugin for the model before changing individual tools.";
72
+ if (denied.includes(capability.id))
73
+ return "A shared tool restriction blocks this tool. Review the saved rules.";
74
+ const globalReason = modelPluginGlobalBlockReason(plugin);
75
+ if (globalReason) return globalReason;
76
+ if (capability.enabled !== true)
77
+ return (
78
+ capability.blockedReason ||
79
+ "This tool is unavailable in global plugin settings."
80
+ );
81
+ const selector = `${plugin.id}.${capability.id}`;
82
+ if (selectorEscapesModelTarget(plugins, plugin.id, capability.id, selector))
83
+ return "This tool selector also affects another tool. Review the saved rules.";
84
+ return "";
85
+ }
86
+
87
+ function modelCapabilityIsEnabled(config, plugin, capability, denied) {
88
+ if (modelPluginRulesNeedRepair(config)) return false;
89
+ if (modelPluginGlobalBlockReason(plugin)) return false;
90
+ if (capability.enabled !== true) return false;
91
+ return !denied.some((selector) =>
92
+ selectorMatchesCapability(selector, plugin.id, capability.id),
93
+ );
94
+ }
95
+
96
+ function modelPluginSelectionState(selectedCount, capabilityCount) {
97
+ if (selectedCount === 0) return "disabled";
98
+ if (selectedCount < capabilityCount) return "partial";
99
+ return "enabled";
100
+ }
101
+
102
+ export function projectModelPluginSelection(config, plugin, plugins) {
103
+ const denied = modelDeniedSelectors(config);
104
+ const capabilities = (plugin.capabilities || []).map((capability) => ({
105
+ ...capability,
106
+ enabled: modelCapabilityIsEnabled(config, plugin, capability, denied),
107
+ blockedReason: modelCapabilityControlBlockReason(
108
+ config,
109
+ plugin,
110
+ capability,
111
+ plugins,
112
+ denied,
113
+ ),
114
+ }));
115
+ const selectedCapabilityCount = capabilities.filter(
116
+ (capability) => capability.enabled,
117
+ ).length;
118
+ return {
119
+ ...plugin,
120
+ // The parent is configured separately from individual tools and global policy.
121
+ pluginEnabled:
122
+ !modelPluginRulesNeedRepair(config) &&
123
+ !denied.includes("*") &&
124
+ !denied.includes(plugin.id),
125
+ capabilities,
126
+ capabilityCount: capabilities.length,
127
+ selectedCapabilityCount,
128
+ state: modelPluginSelectionState(
129
+ selectedCapabilityCount,
130
+ capabilities.length,
131
+ ),
132
+ controlBlockedReason: modelPluginControlBlockReason(
133
+ config,
134
+ plugin,
135
+ plugins,
136
+ denied,
137
+ ),
138
+ };
139
+ }
140
+
141
+ function updateExactModelSelector(config, selector, enabled) {
142
+ const denied = config.plugins?.deny || [];
143
+ const matches = (entry) => entry.trim() === selector;
144
+ if (enabled && !denied.some(matches)) return false;
145
+ if (!enabled && denied.some(matches)) return false;
146
+ const next = enabled
147
+ ? denied.filter((entry) => !matches(entry))
148
+ : [...denied, selector];
149
+ config.plugins = { ...config.plugins, deny: next };
150
+ return true;
151
+ }
152
+
153
+ export function setModelPluginEnabled(config, plugins, pluginId, enabled) {
154
+ const plugin = plugins.find((entry) => entry.id === pluginId);
155
+ if (!plugin) return false;
156
+ const selection = projectModelPluginSelection(config, plugin, plugins);
157
+ if (selection.controlBlockedReason) return false;
158
+ return updateExactModelSelector(config, pluginId, enabled);
159
+ }
160
+
161
+ export function setModelCapabilityEnabled(
162
+ config,
163
+ plugins,
164
+ pluginId,
165
+ capabilityId,
166
+ enabled,
167
+ ) {
168
+ const plugin = plugins.find((entry) => entry.id === pluginId);
169
+ if (!plugin) return false;
170
+ const selection = projectModelPluginSelection(config, plugin, plugins);
171
+ const capability = selection.capabilities.find(
172
+ (entry) => entry.id === capabilityId,
173
+ );
174
+ if (!capability || capability.blockedReason) return false;
175
+ return updateExactModelSelector(
176
+ config,
177
+ `${pluginId}.${capabilityId}`,
178
+ enabled,
179
+ );
180
+ }
@@ -0,0 +1,114 @@
1
+ /** Model-scoped disclosures and keyboard position survive draft redraws. */
2
+ export function createModelPluginViewState(root) {
3
+ const expandedSections = new Set();
4
+ const expandedPlugins = new Set();
5
+ const expandedRetainedRules = new Set();
6
+ let pendingFocus = null;
7
+ const detailSelector =
8
+ "details[data-model-plugin-section], details[data-model-plugin-details], details[data-model-plugin-retained]";
9
+ const controlSelector =
10
+ '[data-config-action="model-plugin-enabled"], [data-config-action="model-plugin-capability-enabled"], [data-model-plugin-section] > summary, [data-model-plugin-details] > summary, [data-model-plugin-retained] > summary';
11
+
12
+ function disclosureTarget(details) {
13
+ const data = details?.dataset;
14
+ if (!data) return null;
15
+ if (data.modelPluginSection)
16
+ return {
17
+ kind: "section",
18
+ set: expandedSections,
19
+ key: data.modelPluginSection,
20
+ };
21
+ if (data.modelPluginDetails)
22
+ return {
23
+ kind: "plugin",
24
+ set: expandedPlugins,
25
+ key: JSON.stringify([data.modelId, data.modelPluginDetails]),
26
+ };
27
+ if (data.modelPluginRetained)
28
+ return {
29
+ kind: "rules",
30
+ set: expandedRetainedRules,
31
+ key: data.modelPluginRetained,
32
+ };
33
+ return null;
34
+ }
35
+
36
+ function remember(details) {
37
+ if (details?.isConnected === false) return;
38
+ const target = disclosureTarget(details);
39
+ if (!target) return;
40
+ if (details.open) {
41
+ target.set.add(target.key);
42
+ return;
43
+ }
44
+ target.set.delete(target.key);
45
+ }
46
+
47
+ function controlKey(element) {
48
+ const data = element?.dataset;
49
+ if (!data) return null;
50
+ if (data.configAction === "model-plugin-enabled")
51
+ return JSON.stringify(["plugin", data.id, data.pluginId]);
52
+ if (data.configAction === "model-plugin-capability-enabled")
53
+ return JSON.stringify([
54
+ "capability",
55
+ data.id,
56
+ data.pluginId,
57
+ data.capabilityId,
58
+ ]);
59
+ if (element.tagName !== "SUMMARY") return null;
60
+ const details = element.parentElement;
61
+ const target = disclosureTarget(details);
62
+ if (!target) return null;
63
+ return JSON.stringify(["disclosure", target.kind, target.key]);
64
+ }
65
+
66
+ function capture() {
67
+ for (const details of root.querySelectorAll(detailSelector))
68
+ remember(details);
69
+ const active = root.ownerDocument?.activeElement;
70
+ const key = root.contains?.(active) ? controlKey(active) : null;
71
+ const viewport = key ? root.closest?.(".config-workspace-body") : null;
72
+ pendingFocus = key
73
+ ? { key, viewport, scrollTop: viewport?.scrollTop || 0 }
74
+ : null;
75
+ }
76
+
77
+ function canRestoreControlFocus(target) {
78
+ if (!target || target.isConnected === false || target.disabled)
79
+ return false;
80
+ if (target.closest?.("[hidden], [inert]")) return false;
81
+ if (target.getClientRects?.().length === 0) return false;
82
+ return true;
83
+ }
84
+
85
+ function restore() {
86
+ const focus = pendingFocus;
87
+ pendingFocus = null;
88
+ if (!focus) return;
89
+ const target = [...root.querySelectorAll(controlSelector)].find(
90
+ (element) => controlKey(element) === focus.key,
91
+ );
92
+ if (!canRestoreControlFocus(target)) return;
93
+ target.focus?.({ preventScroll: true });
94
+ if (focus.viewport && focus.viewport.isConnected !== false)
95
+ focus.viewport.scrollTop = focus.scrollTop;
96
+ }
97
+
98
+ function reset() {
99
+ expandedSections.clear();
100
+ expandedPlugins.clear();
101
+ expandedRetainedRules.clear();
102
+ pendingFocus = null;
103
+ }
104
+
105
+ return {
106
+ expandedSections,
107
+ expandedPlugins,
108
+ expandedRetainedRules,
109
+ remember,
110
+ capture,
111
+ restore,
112
+ reset,
113
+ };
114
+ }
@@ -1,6 +1,7 @@
1
1
  import { configRequiresRawRepair } from "./raw-config-repair.js";
2
2
  import { escapeAttribute, escapeHtml, textOf } from "../../lib/text-format.js";
3
3
  import { isConfigObject } from "./config-model.js";
4
+ import { renderModelPluginPermissions } from "./model-plugin-permissions.js";
4
5
 
5
6
  function modelListStatus(model, hasImage) {
6
7
  if (model.registered === false) return "Not registered";
@@ -15,6 +16,7 @@ function renderModelRegistrationAction(model) {
15
16
  }
16
17
 
17
18
  export function createConfigModelRendering({
19
+ modelPluginViewState,
18
20
  state,
19
21
  calibrationProfileLabel,
20
22
  configFileKey,
@@ -240,6 +242,7 @@ export function createConfigModelRendering({
240
242
  </div>
241
243
  ${renderExecutionRoute(model)}
242
244
  </div>
245
+ ${renderModelPluginPermissions(model, state.modelPluginCatalog, modelPluginViewState)}
243
246
  <details
244
247
  class="config-calibration-section"
245
248
  data-calibration-section-key="${escapeAttribute(calibrationSectionKey)}"
@@ -0,0 +1,39 @@
1
+ function modelSupportsImageInput(model) {
2
+ const modalities = model.config?.capabilities?.inputModalities;
3
+ return Array.isArray(modalities) && modalities.includes("image");
4
+ }
5
+
6
+ function modelSummaryUnavailableValue(state) {
7
+ if (state.loading) return "Loading…";
8
+ if (state.configDashboardError) return "Unavailable";
9
+ if (!state.configDashboard?.files) return "Not loaded";
10
+ return null;
11
+ }
12
+
13
+ function modelChangesLabel(count) {
14
+ if (count === 0) return "All saved";
15
+ return `${count} unsaved ${count === 1 ? "model" : "models"}`;
16
+ }
17
+
18
+ export function modelSummary(state, hasPendingFileChanges) {
19
+ const labels = ["Registered models", "Providers", "Image input", "Model changes"];
20
+ const unavailable = modelSummaryUnavailableValue(state);
21
+ if (unavailable) return {
22
+ label: "Models summary",
23
+ items: labels.map((label) => ({ label, value: unavailable })),
24
+ };
25
+ const models = Array.isArray(state.configDashboard.files.models)
26
+ ? state.configDashboard.files.models : [];
27
+ const registered = models.filter((model) => model.registered === true);
28
+ const providers = new Set(registered.map((model) => model.config?.provider).filter(Boolean));
29
+ const pending = models.filter(hasPendingFileChanges).length;
30
+ return {
31
+ label: "Models summary",
32
+ items: [
33
+ { label: labels[0], value: String(registered.length) },
34
+ { label: labels[1], value: String(providers.size) },
35
+ { label: labels[2], value: String(registered.filter(modelSupportsImageInput).length) },
36
+ { label: labels[3], value: modelChangesLabel(pending), status: true, dirty: pending > 0 },
37
+ ],
38
+ };
39
+ }
@@ -0,0 +1,30 @@
1
+ import { escapeAttribute, escapeHtml } from "../../lib/text-format.js";
2
+
3
+ const renderedSummaries = new WeakMap();
4
+
5
+ function renderSummaryItems(summary) {
6
+ return summary.items.map(({ label, value, status, dirty }) => `
7
+ <div class="config-summary-item">
8
+ <dt>${escapeHtml(label)}</dt>
9
+ <dd class="config-summary-value${dirty ? " dirty" : ""}"
10
+ title="${escapeAttribute(value)}"
11
+ ${status ? 'data-config-summary-status role="status" aria-live="polite"' : ""}
12
+ >${escapeHtml(value)}</dd>
13
+ </div>
14
+ `).join("");
15
+ }
16
+
17
+ export function renderConfigurationSummary(summary) {
18
+ return `<dl class="config-summary" data-config-summary aria-label="${escapeAttribute(summary.label)}">${renderSummaryItems(summary)}</dl>`;
19
+ }
20
+
21
+ export function syncConfigurationSummary(root, summary) {
22
+ const element = root.querySelector("[data-config-summary]");
23
+ if (!element) return;
24
+ const content = renderSummaryItems(summary);
25
+ const previous = renderedSummaries.get(element);
26
+ if (previous?.content === content && previous.label === summary.label) return;
27
+ element.setAttribute("aria-label", summary.label);
28
+ element.innerHTML = content;
29
+ renderedSummaries.set(element, { content, label: summary.label });
30
+ }
@@ -1,8 +1,13 @@
1
1
  import { rememberCalibrationDisclosure } from "./calibration-disclosure.js";
2
2
  import { textOf } from "../../lib/text-format.js";
3
3
  import { resolveModelExecutionRoute } from "./config-model.js";
4
+ import {
5
+ setModelPluginEnabled,
6
+ setModelCapabilityEnabled,
7
+ } from "./model-plugin-selection.js";
4
8
 
5
9
  export function createConfigWorkspaceEvents({
10
+ modelPluginViewState,
6
11
  state,
7
12
  dom,
8
13
  eventTarget,
@@ -91,6 +96,37 @@ export function createConfigWorkspaceEvents({
91
96
  const actionElement = element?.closest?.("[data-config-action]");
92
97
  if (!actionElement) return;
93
98
  const action = actionElement.dataset.configAction;
99
+ if (action === "model-plugin-enabled") {
100
+ mutateConfigFile(
101
+ "model",
102
+ actionElement.dataset.id,
103
+ (config) =>
104
+ setModelPluginEnabled(
105
+ config,
106
+ state.modelPluginCatalog?.plugins || [],
107
+ actionElement.dataset.pluginId,
108
+ actionElement.checked,
109
+ ),
110
+ { rerender: true },
111
+ );
112
+ return;
113
+ }
114
+ if (action === "model-plugin-capability-enabled") {
115
+ mutateConfigFile(
116
+ "model",
117
+ actionElement.dataset.id,
118
+ (config) =>
119
+ setModelCapabilityEnabled(
120
+ config,
121
+ state.modelPluginCatalog?.plugins || [],
122
+ actionElement.dataset.pluginId,
123
+ actionElement.dataset.capabilityId,
124
+ actionElement.checked,
125
+ ),
126
+ { rerender: true },
127
+ );
128
+ return;
129
+ }
94
130
  if (action === "step-value") {
95
131
  handleFieldMutation(actionElement);
96
132
  return;
@@ -106,6 +142,7 @@ export function createConfigWorkspaceEvents({
106
142
  state.rawPanelOpen = details.open;
107
143
  return;
108
144
  }
145
+ modelPluginViewState?.remember(details);
109
146
  rememberCalibrationDisclosure(state, details);
110
147
  }
111
148
 
@@ -11,6 +11,7 @@ import {
11
11
  } from "./config-model.js";
12
12
 
13
13
  export function createConfigWorkspaceMutations({
14
+ modelPluginViewState,
14
15
  state,
15
16
  dom,
16
17
  confirmDiscard,
@@ -125,6 +126,7 @@ export function createConfigWorkspaceMutations({
125
126
  }
126
127
 
127
128
  function clearDashboardSnapshot() {
129
+ modelPluginViewState?.reset();
128
130
  state.configDashboard = null;
129
131
  state.baselinesByKey.clear();
130
132
  state.rawDraftsByKey.clear();
@@ -1,5 +1,6 @@
1
1
  import { configRepairSaveIsConfirmed } from "./raw-config-repair.js";
2
2
  import { textOf } from "../../lib/text-format.js";
3
+ import { loadModelPluginCatalog } from "./model-plugin-permissions.js";
3
4
  import {
4
5
  cloneConfig,
5
6
  modelContextWindowValidationError,
@@ -10,6 +11,7 @@ export function createConfigWorkspacePersistence({
10
11
  state,
11
12
  dom,
12
13
  loadDashboard,
14
+ loadModelPlugins,
13
15
  saveFile,
14
16
  memorySetup,
15
17
  memoryManagement,
@@ -84,11 +86,16 @@ export function createConfigWorkspacePersistence({
84
86
  }
85
87
  const loadGeneration = ++state.loadGeneration;
86
88
  state.loading = true;
89
+ state.configDashboardError = false;
87
90
  setWorkspaceStatus("Loading…");
88
91
  syncDashboardInteractivity();
89
92
  try {
90
- const payload = await loadDashboard();
93
+ const [payload, modelPluginCatalog] = await Promise.all([
94
+ loadDashboard(),
95
+ loadModelPluginCatalog(loadModelPlugins),
96
+ ]);
91
97
  if (configLoadIsStale(loadGeneration)) return false;
98
+ state.modelPluginCatalog = modelPluginCatalog;
92
99
  replaceDashboard(payload);
93
100
  const memoryLoads = [memoryManagement.load()];
94
101
  if (pluginManagement) memoryLoads.push(pluginManagement.load());
@@ -115,6 +122,7 @@ export function createConfigWorkspacePersistence({
115
122
  return true;
116
123
  } catch (error) {
117
124
  if (configLoadIsStale(loadGeneration)) return false;
125
+ state.configDashboardError = true;
118
126
  const failurePrefix = textOf(options.failurePrefix).trim();
119
127
  const summary = error instanceof Error ? error.message : String(error);
120
128
  setWorkspaceStatus(
@@ -3,20 +3,22 @@ import {
3
3
  configRequiresRawRepair,
4
4
  } from "./raw-config-repair.js";
5
5
  import { renderModelSetupEntry } from "./model-setup-entry.js";
6
- import { escapeHtml, textOf } from "../../lib/text-format.js";
6
+ import { textOf } from "../../lib/text-format.js";
7
7
  import { CONFIG_CATEGORIES } from "./config-model.js";
8
+ import { modelSummary } from "./model-summary.js";
9
+ import { renderConfigurationSummary, syncConfigurationSummary } from "./summary-rendering.js";
8
10
 
9
11
  export function createConfigWorkspaceView({
12
+ modelPluginViewState,
10
13
  onNavigationChange = () => {},
11
14
  state,
12
15
  dom,
13
16
  eventTarget,
14
17
  pluginManagement,
18
+ getOperationsSummary = () => ({ label: "System summary", items: [{ label: "System", value: "Not loaded" }] }),
15
19
  configFileEntries,
16
20
  configFileKey,
17
- countObjectKeys,
18
21
  dashboardIsBusy,
19
- dirtyFiles,
20
22
  ensureRawSelection,
21
23
  fileStatusText,
22
24
  hasPendingFileChanges,
@@ -53,17 +55,6 @@ export function createConfigWorkspaceView({
53
55
  return requestRunner?.config?.schemaVersion === 2;
54
56
  }
55
57
 
56
- function configuredStepTargetCountLabel(count, sparseOverrides) {
57
- const noun = sparseOverrides ? "override" : "mapping";
58
- return `${count} ${count === 1 ? noun : `${noun}s`}`;
59
- }
60
-
61
- function configChangeSummary(count) {
62
- if (count === 0) return "All saved";
63
- const fileLabel = count === 1 ? "file" : "files";
64
- return `${count} unsaved ${fileLabel}`;
65
- }
66
-
67
58
  function requestPipelineContent(requestRunner) {
68
59
  if (!requestRunner) {
69
60
  return '<div class="empty-state compact">No request runner config found</div>';
@@ -95,6 +86,7 @@ export function createConfigWorkspaceView({
95
86
  const unavailable =
96
87
  '<div class="empty-state">No config dashboard data</div>';
97
88
  dom.configDashboard.innerHTML =
89
+ renderConfigurationSummary(currentSummary()) +
98
90
  '<div class="config-category-panels">' +
99
91
  CONFIG_CATEGORIES.map((category) =>
100
92
  renderCategoryPanel(
@@ -129,16 +121,17 @@ export function createConfigWorkspaceView({
129
121
  }
130
122
  dom.configDashboard.setAttribute("aria-busy", busy ? "true" : "false");
131
123
  dom.refreshConfigButton.disabled = busy;
124
+ syncDashboardSummary();
132
125
  }
133
126
 
134
127
  function renderConfigDashboard() {
128
+ modelPluginViewState?.capture();
135
129
  const dashboard = state.configDashboard;
136
130
  if (!dashboard?.files) {
137
131
  renderUnavailableDashboard();
138
132
  return;
139
133
  }
140
134
  const runtime = dashboard.files.runtime;
141
- const requestRunner = dashboard.files.requestRunner;
142
135
  const models = Array.isArray(dashboard.files.models)
143
136
  ? dashboard.files.models
144
137
  : [];
@@ -146,18 +139,6 @@ export function createConfigWorkspaceView({
146
139
  state.selectedConfigModelId = models[0]?.id || "";
147
140
  }
148
141
  ensureRawSelection();
149
- const registeredStepCount = Array.isArray(dashboard.modelSteps)
150
- ? dashboard.modelSteps.length
151
- : 0;
152
- const configuredStepTargetCount = requestRunner
153
- ? countObjectKeys(requestRunner.config?.models?.defaults?.steps)
154
- : 0;
155
- const sparseOverrides = requestRunnerUsesSparseOverrides(requestRunner);
156
- const configuredStepTargetLabel = configuredStepTargetCountLabel(
157
- configuredStepTargetCount,
158
- sparseOverrides,
159
- );
160
- const dirtyCount = dirtyFiles().length;
161
142
  const repairNeeded = configFileEntries().some((file) =>
162
143
  configRequiresRawRepair(
163
144
  file,
@@ -165,39 +146,7 @@ export function createConfigWorkspaceView({
165
146
  ),
166
147
  );
167
148
  dom.configDashboard.innerHTML = `
168
- <dl class="config-summary" aria-label="Configuration summary">
169
- <div class="config-summary-item">
170
- <dt>Runtime</dt>
171
- <dd class="config-summary-value">${escapeHtml(
172
- runtime?.exists ? "Ready" : "Missing",
173
- )}</dd>
174
- </div>
175
- <div class="config-summary-item">
176
- <dt>Pipeline</dt>
177
- <dd class="config-summary-value">
178
- <span data-config-registered-step-count>${escapeHtml(
179
- `${registeredStepCount} registered`,
180
- )}</span>
181
- <span aria-hidden="true"> · </span>
182
- <span data-config-step-target-count>${escapeHtml(
183
- configuredStepTargetLabel,
184
- )}</span>
185
- </dd>
186
- </div>
187
- <div class="config-summary-item">
188
- <dt>Models</dt>
189
- <dd class="config-summary-value">${escapeHtml(String(models.length))}</dd>
190
- </div>
191
- <div class="config-summary-item config-summary-changes">
192
- <dt>Changes</dt>
193
- <dd
194
- class="config-summary-value ${dirtyCount ? "dirty" : ""}"
195
- data-config-summary-status
196
- role="status"
197
- aria-live="polite"
198
- >${escapeHtml(configChangeSummary(dirtyCount))}</dd>
199
- </div>
200
- </dl>
149
+ ${renderConfigurationSummary(currentSummary())}
201
150
  ${
202
151
  repairNeeded
203
152
  ? `<section class="config-category-panel" aria-label="Repair configuration file">${renderConfigMap()}</section>`
@@ -224,6 +173,7 @@ export function createConfigWorkspaceView({
224
173
  );
225
174
  syncDirtyPresentation({ syncRawEditor: true });
226
175
  syncDashboardInteractivity();
176
+ modelPluginViewState?.restore();
227
177
  }
228
178
 
229
179
  function syncActiveCategory() {
@@ -240,6 +190,7 @@ export function createConfigWorkspaceView({
240
190
  if (!CONFIG_CATEGORIES.includes(category)) return;
241
191
  state.activeCategory = category;
242
192
  syncActiveCategory();
193
+ syncDashboardSummary();
243
194
  onNavigationChange();
244
195
  }
245
196
 
@@ -300,14 +251,18 @@ export function createConfigWorkspaceView({
300
251
  }
301
252
  }
302
253
 
254
+ function currentSummary() {
255
+ if (state.activeCategory === "plugins") {
256
+ return pluginManagement?.summary?.() ?? {
257
+ label: "Plugins summary", items: [{ label: "Plugins", value: "Not loaded" }],
258
+ };
259
+ }
260
+ if (state.activeCategory === "operations") return getOperationsSummary();
261
+ return modelSummary(state, hasPendingFileChanges);
262
+ }
263
+
303
264
  function syncDashboardSummary() {
304
- const status = dom.configDashboard.querySelector(
305
- "[data-config-summary-status]",
306
- );
307
- if (!status) return;
308
- const count = dirtyFiles().length;
309
- status.textContent = configChangeSummary(count);
310
- status.classList.toggle("dirty", count > 0);
265
+ syncConfigurationSummary(dom.configDashboard, currentSummary());
311
266
  }
312
267
 
313
268
  function syncRawControls(options = {}) {
@@ -365,6 +320,7 @@ export function createConfigWorkspaceView({
365
320
  renderConfigDashboard,
366
321
  setWorkspaceStatus,
367
322
  syncDashboardInteractivity,
323
+ syncDashboardSummary,
368
324
  syncDirtyPresentation,
369
325
  };
370
326
  }