@abot-ai/runtime 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +2 -0
  2. package/dist/src/bridge/request-steering.js +60 -15
  3. package/dist/src/capabilities/normal-invocation/contracts.d.ts +3 -0
  4. package/dist/src/capabilities/normal-invocation/output-channels.d.ts +10 -0
  5. package/dist/src/capabilities/normal-invocation/output-channels.js +29 -0
  6. package/dist/src/capabilities/normal-invocation/validator.js +4 -2
  7. package/dist/src/capabilities/tool-types.d.ts +1 -1
  8. package/dist/src/cli/host-companion-bundle.mjs +7570 -6781
  9. package/dist/src/cli/host-companion-entry.js +5 -22
  10. package/dist/src/cli/host-companion-input.d.ts +3 -0
  11. package/dist/src/cli/host-companion-input.js +21 -0
  12. package/dist/src/cli/host-companion-lifecycle.d.ts +11 -0
  13. package/dist/src/cli/host-companion-lifecycle.js +32 -0
  14. package/dist/src/cli/host-companion-setup-target.d.ts +4 -0
  15. package/dist/src/cli/host-companion-setup-target.js +17 -0
  16. package/dist/src/cli/host-companion-startup.d.ts +2 -0
  17. package/dist/src/cli/host-companion-startup.js +7 -2
  18. package/dist/src/cli/host-companion.d.ts +6 -0
  19. package/dist/src/cli/host-companion.js +30 -27
  20. package/dist/src/cli/windows-companion-store-entry.d.ts +9 -0
  21. package/dist/src/cli/windows-companion-store-entry.js +67 -0
  22. package/dist/src/computer-access/command-output-capture.d.ts +37 -0
  23. package/dist/src/computer-access/command-output-capture.js +136 -0
  24. package/dist/src/computer-access/command-output-retention.d.ts +5 -0
  25. package/dist/src/computer-access/command-output-retention.js +90 -0
  26. package/dist/src/computer-access/command-output.d.ts +7 -0
  27. package/dist/src/computer-access/command-output.js +1 -0
  28. package/dist/src/computer-access/commands.d.ts +1 -0
  29. package/dist/src/computer-access/commands.js +1 -1
  30. package/dist/src/computer-access/companion/command-output-protocol.d.ts +12 -0
  31. package/dist/src/computer-access/companion/command-output-protocol.js +28 -0
  32. package/dist/src/computer-access/companion/command-output.d.ts +13 -0
  33. package/dist/src/computer-access/companion/command-output.js +110 -0
  34. package/dist/src/computer-access/companion/install-link-macos.d.ts +7 -0
  35. package/dist/src/computer-access/companion/install-link-macos.js +48 -0
  36. package/dist/src/computer-access/companion/install-link-registration.d.ts +4 -0
  37. package/dist/src/computer-access/companion/install-link-registration.js +184 -0
  38. package/dist/src/computer-access/companion/install-link-windows.d.ts +4 -0
  39. package/dist/src/computer-access/companion/install-link-windows.js +65 -0
  40. package/dist/src/computer-access/companion/install-link.d.ts +9 -0
  41. package/dist/src/computer-access/companion/install-link.js +54 -0
  42. package/dist/src/computer-access/companion/native-messages.js +3 -0
  43. package/dist/src/computer-access/companion/native-session.d.ts +1 -0
  44. package/dist/src/computer-access/companion/native-session.js +14 -2
  45. package/dist/src/computer-access/companion/native-supervisor.js +1 -0
  46. package/dist/src/computer-access/companion/notification-windows.d.ts +1 -1
  47. package/dist/src/computer-access/companion/notification-windows.js +8 -3
  48. package/dist/src/computer-access/companion/protocol.d.ts +1 -1
  49. package/dist/src/computer-access/companion/protocol.js +6 -0
  50. package/dist/src/computer-access/companion/release-version.d.ts +1 -1
  51. package/dist/src/computer-access/companion/release-version.js +1 -1
  52. package/dist/src/computer-access/companion/windows-store/connection-error.d.ts +7 -0
  53. package/dist/src/computer-access/companion/windows-store/connection-error.js +19 -0
  54. package/dist/src/computer-access/companion/windows-store/connection-link.d.ts +13 -0
  55. package/dist/src/computer-access/companion/windows-store/connection-link.js +109 -0
  56. package/dist/src/computer-access/companion/windows-store/identity.d.ts +13 -0
  57. package/dist/src/computer-access/companion/windows-store/identity.js +13 -0
  58. package/dist/src/computer-access/companion/windows-store/lifecycle.d.ts +5 -0
  59. package/dist/src/computer-access/companion/windows-store/lifecycle.js +90 -0
  60. package/dist/src/computer-access/contracts.d.ts +1 -1
  61. package/dist/src/computer-access/handlers.d.ts +2 -1
  62. package/dist/src/computer-access/handlers.js +5 -1
  63. package/dist/src/computer-access/process-capture.d.ts +6 -0
  64. package/dist/src/computer-access/process-capture.js +1 -0
  65. package/dist/src/computer-access/process-result.d.ts +2 -0
  66. package/dist/src/computer-access/process-result.js +14 -6
  67. package/dist/src/computer-access/process-runner.d.ts +2 -1
  68. package/dist/src/computer-access/process-runner.js +21 -13
  69. package/dist/src/model-gateway/server/configuration.d.ts +2 -0
  70. package/dist/src/model-gateway/server/configuration.js +73 -21
  71. package/dist/src/plugin-contract/install-source.d.ts +13 -0
  72. package/dist/src/plugin-contract/install-source.js +99 -0
  73. package/dist/src/plugin-contract/manifest.d.ts +2 -1
  74. package/dist/src/plugin-sdk/computer-access.d.ts +8 -0
  75. package/dist/src/plugin-sdk/computer-access.js +5 -0
  76. package/dist/src/runtime/adapters/in-memory-session-store.js +6 -16
  77. package/dist/src/runtime/admin/config-control.js +2 -1
  78. package/dist/src/runtime/automations/catalog.d.ts +3 -0
  79. package/dist/src/runtime/automations/catalog.js +1 -0
  80. package/dist/src/runtime/automations/model-dependency-projection.d.ts +2 -0
  81. package/dist/src/runtime/automations/service.d.ts +2 -0
  82. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.d.ts +10 -5
  83. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.js +8 -7
  84. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.d.ts +2 -2
  85. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.js +2 -2
  86. package/dist/src/runtime/capabilities/automation-builder/tool-contract.d.ts +2 -2
  87. package/dist/src/runtime/capabilities/automations/authoring-catalog.js +1 -1
  88. package/dist/src/runtime/capabilities/automations/authoring-preparation.d.ts +11 -5
  89. package/dist/src/runtime/capabilities/automations/tool-module.js +1 -1
  90. package/dist/src/runtime/capabilities/request-permission-catalog.d.ts +3 -1
  91. package/dist/src/runtime/capabilities/request-permission-catalog.js +21 -2
  92. package/dist/src/runtime/capabilities/request-permission-tool-registry.d.ts +2 -1
  93. package/dist/src/runtime/capabilities/request-permission-tool-registry.js +18 -10
  94. package/dist/src/runtime/capabilities/request-runtime-tool-registry.d.ts +2 -0
  95. package/dist/src/runtime/capabilities/request-runtime-tool-registry.js +1 -1
  96. package/dist/src/runtime/capabilities/scheduling/create-operations.d.ts +6 -0
  97. package/dist/src/runtime/config/builders.js +6 -5
  98. package/dist/src/runtime/config/effective-model-config-validation.js +4 -35
  99. package/dist/src/runtime/config/fields.js +15 -0
  100. package/dist/src/runtime/config/model-context-capacity.d.ts +20 -0
  101. package/dist/src/runtime/config/model-context-capacity.js +55 -0
  102. package/dist/src/runtime/config/model-execution-policy.d.ts +5 -1
  103. package/dist/src/runtime/config/model-execution-policy.js +16 -0
  104. package/dist/src/runtime/config/model-plugin-config.d.ts +8 -0
  105. package/dist/src/runtime/config/model-plugin-config.js +40 -0
  106. package/dist/src/runtime/config/schema.js +5 -1
  107. package/dist/src/runtime/config/validation/model-profile-validation.js +2 -0
  108. package/dist/src/runtime/config/validation/runtime-config-validation-contract.d.ts +3 -1
  109. package/dist/src/runtime/config/validation/runtime-config-validation-contract.js +3 -1
  110. package/dist/src/runtime/config/validation/runtime-root-section-validation.js +11 -4
  111. package/dist/src/runtime/config/validation/web-ui-config-validation.js +3 -2
  112. package/dist/src/runtime/config/web-ui.d.ts +5 -0
  113. package/dist/src/runtime/config/web-ui.js +5 -0
  114. package/dist/src/runtime/config.js +2 -0
  115. package/dist/src/runtime/local-application.d.ts +2 -0
  116. package/dist/src/runtime/local-host/app-owner.js +50 -6
  117. package/dist/src/runtime/local-host/app-request-control.d.ts +3 -1
  118. package/dist/src/runtime/local-host/app-request-control.js +91 -11
  119. package/dist/src/runtime/local-host/client-requests.js +32 -5
  120. package/dist/src/runtime/local-host/client-services.d.ts +2 -0
  121. package/dist/src/runtime/local-host/local-request-diagnostics.d.ts +9 -0
  122. package/dist/src/runtime/local-host/local-request-diagnostics.js +47 -0
  123. package/dist/src/runtime/local-host/saved-approvals.js +23 -2
  124. package/dist/src/runtime/model/model-selection.js +4 -1
  125. package/dist/src/runtime/observability/request-control-diagnostics.d.ts +6 -0
  126. package/dist/src/runtime/observability/request-control-diagnostics.js +52 -0
  127. package/dist/src/runtime/plugins/configuration-context.d.ts +9 -0
  128. package/dist/src/runtime/plugins/configuration-context.js +42 -0
  129. package/dist/src/runtime/plugins/configuration-settings.d.ts +2 -0
  130. package/dist/src/runtime/plugins/configuration-settings.js +26 -0
  131. package/dist/src/runtime/plugins/configuration-store.d.ts +23 -0
  132. package/dist/src/runtime/plugins/configuration-store.js +100 -0
  133. package/dist/src/runtime/plugins/configuration-write.d.ts +5 -0
  134. package/dist/src/runtime/plugins/configuration-write.js +58 -0
  135. package/dist/src/runtime/plugins/installation/archive.d.ts +2 -0
  136. package/dist/src/runtime/plugins/installation/archive.js +107 -0
  137. package/dist/src/runtime/plugins/installation/github-download.d.ts +9 -0
  138. package/dist/src/runtime/plugins/installation/github-download.js +72 -0
  139. package/dist/src/runtime/plugins/installation/installed-package.d.ts +9 -0
  140. package/dist/src/runtime/plugins/installation/installed-package.js +66 -0
  141. package/dist/src/runtime/plugins/installation/package.d.ts +45 -0
  142. package/dist/src/runtime/plugins/installation/package.js +79 -0
  143. package/dist/src/runtime/plugins/installation/portable-path.d.ts +2 -0
  144. package/dist/src/runtime/plugins/installation/portable-path.js +10 -0
  145. package/dist/src/runtime/plugins/installation/publication.d.ts +10 -0
  146. package/dist/src/runtime/plugins/installation/publication.js +17 -0
  147. package/dist/src/runtime/plugins/installation/service.d.ts +41 -0
  148. package/dist/src/runtime/plugins/installation/service.js +80 -0
  149. package/dist/src/runtime/plugins/loader.js +15 -29
  150. package/dist/src/runtime/plugins/manifest-projection.js +1 -0
  151. package/dist/src/runtime/plugins/manifest-validator.js +3 -0
  152. package/dist/src/runtime/plugins/module-cache.d.ts +2 -0
  153. package/dist/src/runtime/plugins/module-cache.js +19 -0
  154. package/dist/src/runtime/plugins/selection.d.ts +2 -0
  155. package/dist/src/runtime/plugins/selection.js +16 -11
  156. package/dist/src/runtime/ports.d.ts +6 -4
  157. package/dist/src/runtime/request/dependencies.d.ts +2 -1
  158. package/dist/src/runtime/request/execution-payload-compacted-evidence.d.ts +1 -1
  159. package/dist/src/runtime/request/handler.js +8 -0
  160. package/dist/src/runtime/request/prepared-execution.js +6 -1
  161. package/dist/src/runtime/request/request-steering.d.ts +4 -0
  162. package/dist/src/runtime/request/request-steering.js +37 -12
  163. package/dist/src/runtime/request/worker-capability-composition.d.ts +2 -0
  164. package/dist/src/runtime/request/worker-capability-composition.js +4 -1
  165. package/dist/src/runtime/scheduler/journal-index-state.d.ts +1 -1
  166. package/dist/src/sessions/assistant-initiative-message.d.ts +3 -0
  167. package/dist/src/sessions/assistant-initiative-message.js +12 -0
  168. package/dist/src/sessions/assistant-initiative.d.ts +2 -2
  169. package/dist/src/sessions/assistant-initiative.js +1 -7
  170. package/dist/src/sessions/durable-session-commit.d.ts +2 -1
  171. package/dist/src/sessions/durable-session-commit.js +6 -1
  172. package/dist/src/sessions/metadata/projection.d.ts +15 -0
  173. package/dist/src/sessions/metadata/projection.js +55 -0
  174. package/dist/src/sessions/metadata/publication.d.ts +12 -0
  175. package/dist/src/sessions/metadata/publication.js +78 -0
  176. package/dist/src/sessions/metadata/source-receipt.d.ts +5 -0
  177. package/dist/src/sessions/metadata/source-receipt.js +42 -0
  178. package/dist/src/sessions/metadata/store.d.ts +7 -0
  179. package/dist/src/sessions/metadata/store.js +119 -0
  180. package/dist/src/sessions/record/projection.d.ts +3 -1
  181. package/dist/src/sessions/record/projection.js +26 -18
  182. package/dist/src/sessions/request-lifecycle/service.js +3 -3
  183. package/dist/src/sessions/session-service.d.ts +2 -4
  184. package/dist/src/sessions/session-service.js +4 -16
  185. package/dist/src/sessions/session-store.d.ts +2 -1
  186. package/dist/src/sessions/session-store.js +9 -3
  187. package/dist/src/sessions/snapshot.d.ts +17 -0
  188. package/dist/src/sessions/snapshot.js +105 -0
  189. package/dist/src/sessions/types.d.ts +2 -0
  190. package/dist/src/shared/tool-selection.d.ts +2 -0
  191. package/dist/src/shared/tool-selection.js +7 -0
  192. package/dist/src/web-ui/app/ARCHITECTURE.md +14 -0
  193. package/dist/src/web-ui/app/app.js +6 -3
  194. package/dist/src/web-ui/app/components/config-workspace/config-model.js +2 -0
  195. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +130 -0
  196. package/dist/src/web-ui/app/components/config-workspace/model-plugin-selection.js +180 -0
  197. package/dist/src/web-ui/app/components/config-workspace/model-plugin-view-state.js +114 -0
  198. package/dist/src/web-ui/app/components/config-workspace/model-rendering.js +3 -0
  199. package/dist/src/web-ui/app/components/config-workspace/model-summary.js +39 -0
  200. package/dist/src/web-ui/app/components/config-workspace/summary-rendering.js +30 -0
  201. package/dist/src/web-ui/app/components/config-workspace/workspace-events.js +37 -0
  202. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +2 -0
  203. package/dist/src/web-ui/app/components/config-workspace/workspace-persistence.js +9 -1
  204. package/dist/src/web-ui/app/components/config-workspace/workspace-view.js +23 -67
  205. package/dist/src/web-ui/app/components/config-workspace.js +11 -2
  206. package/dist/src/web-ui/app/components/conversation-view.js +36 -5
  207. package/dist/src/web-ui/app/components/dashboard/recent-conversations.js +2 -1
  208. package/dist/src/web-ui/app/components/dashboard/workspace.js +2 -1
  209. package/dist/src/web-ui/app/components/operations-summary.js +105 -0
  210. package/dist/src/web-ui/app/components/passive-learning/home.js +1 -9
  211. package/dist/src/web-ui/app/components/plugins/configuration-draft.js +34 -0
  212. package/dist/src/web-ui/app/components/plugins/configuration-editor.js +147 -0
  213. package/dist/src/web-ui/app/components/plugins/configuration-fields.js +103 -0
  214. package/dist/src/web-ui/app/components/plugins/configuration-retained-secrets.js +20 -0
  215. package/dist/src/web-ui/app/components/plugins/configuration-settings.js +108 -0
  216. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +37 -0
  217. package/dist/src/web-ui/app/components/plugins/installation.js +212 -0
  218. package/dist/src/web-ui/app/components/plugins/manager.js +160 -6
  219. package/dist/src/web-ui/app/components/plugins/removal.js +130 -0
  220. package/dist/src/web-ui/app/components/plugins/rendering.js +14 -2
  221. package/dist/src/web-ui/app/components/plugins/summary.js +54 -0
  222. package/dist/src/web-ui/app/components/plugins/tabs.js +31 -0
  223. package/dist/src/web-ui/app/components/plugins/view-state.js +3 -1
  224. package/dist/src/web-ui/app/components/runtime-setup/connection-form.js +5 -2
  225. package/dist/src/web-ui/app/components/runtime-setup/connection-state.js +9 -1
  226. package/dist/src/web-ui/app/components/runtime-setup/context-window-feedback.js +71 -0
  227. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +2 -0
  228. package/dist/src/web-ui/app/components/runtime-setup-guide.js +15 -3
  229. package/dist/src/web-ui/app/components/spark-chat/empty-state.js +1 -0
  230. package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -0
  231. package/dist/src/web-ui/app/components/system-host/connection-card.js +35 -0
  232. package/dist/src/web-ui/app/components/system-host/macos-setup.js +1 -1
  233. package/dist/src/web-ui/app/components/system-host/manager.js +45 -12
  234. package/dist/src/web-ui/app/components/system-host/rendering.js +111 -106
  235. package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +293 -0
  236. package/dist/src/web-ui/app/components/workspace-shell.js +6 -0
  237. package/dist/src/web-ui/app/computer-access-feature.js +22 -5
  238. package/dist/src/web-ui/app/configuration-feature.js +35 -2
  239. package/dist/src/web-ui/app/controllers/app-event-bindings.js +4 -1
  240. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.d.ts +1 -0
  241. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.js +7 -3
  242. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +88 -0
  243. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +9 -3
  244. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +52 -144
  245. package/dist/src/web-ui/app/controllers/history-pagination.js +111 -0
  246. package/dist/src/web-ui/app/controllers/operations-controller.d.ts +12 -0
  247. package/dist/src/web-ui/app/controllers/operations-controller.js +28 -21
  248. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.d.ts +1 -0
  249. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.js +11 -0
  250. package/dist/src/web-ui/app/controllers/session-controller.js +10 -2
  251. package/dist/src/web-ui/app/controllers/session-list-pagination.js +71 -0
  252. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +6 -4
  253. package/dist/src/web-ui/app/controllers/spark-chat-reading.js +1 -0
  254. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +24 -5
  255. package/dist/src/web-ui/app/controllers/workspace-route-controller.js +21 -19
  256. package/dist/src/web-ui/app/dashboard-feature.js +2 -2
  257. package/dist/src/web-ui/app/index.html +6 -2
  258. package/dist/src/web-ui/app/lib/history-page-messages.js +49 -0
  259. package/dist/src/web-ui/app/lib/request-lifecycle-view.js +8 -0
  260. package/dist/src/web-ui/app/lib/workspace-route.d.ts +3 -0
  261. package/dist/src/web-ui/app/lib/workspace-route.js +4 -0
  262. package/dist/src/web-ui/app/passive-learning-feature.js +0 -1
  263. package/dist/src/web-ui/app/runtime-onboarding-feature.js +3 -0
  264. package/dist/src/web-ui/app/schedules-feature.js +1 -1
  265. package/dist/src/web-ui/app/services/runtime-web-client/configuration.js +20 -0
  266. package/dist/src/web-ui/app/services/runtime-web-client/plugin-configuration.js +19 -0
  267. package/dist/src/web-ui/app/services/runtime-web-client/spark-chat.js +4 -4
  268. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  269. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +6 -1
  270. package/dist/src/web-ui/app/services/runtime-web-client.js +12 -3
  271. package/dist/src/web-ui/app/spark-chat-feature.js +76 -19
  272. package/dist/src/web-ui/app/styles/11-product-links.css +30 -0
  273. package/dist/src/web-ui/app/styles/41-plugin-configuration.css +79 -0
  274. package/dist/src/web-ui/app/styles/41-plugin-discovery.css +132 -0
  275. package/dist/src/web-ui/app/styles/41-plugin-management.css +6 -0
  276. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +173 -0
  277. package/dist/src/web-ui/app/styles/46-system-host.css +61 -107
  278. package/dist/src/web-ui/app/styles/47-config-controls.css +13 -1
  279. package/dist/src/web-ui/app/styles/54-spark-chat.css +33 -1
  280. package/dist/src/web-ui/app/styles.css +4 -0
  281. package/dist/src/web-ui/local-runtime/api-router.js +11 -6
  282. package/dist/src/web-ui/local-runtime/approval-request-attachment.js +14 -5
  283. package/dist/src/web-ui/local-runtime/configuration-activation-source.d.ts +1 -1
  284. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +9 -3
  285. package/dist/src/web-ui/local-runtime/contracts.d.ts +4 -3
  286. package/dist/src/web-ui/local-runtime/environment-registry.d.ts +5 -1
  287. package/dist/src/web-ui/local-runtime/environment-registry.js +53 -11
  288. package/dist/src/web-ui/local-runtime/history-pagination.d.ts +16 -0
  289. package/dist/src/web-ui/local-runtime/history-pagination.js +20 -0
  290. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.d.ts +16 -0
  291. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.js +68 -0
  292. package/dist/src/web-ui/local-runtime/plugin-installation-routes.d.ts +16 -0
  293. package/dist/src/web-ui/local-runtime/plugin-installation-routes.js +96 -0
  294. package/dist/src/web-ui/local-runtime/plugin-management-routes.d.ts +8 -1
  295. package/dist/src/web-ui/local-runtime/plugin-management-routes.js +17 -0
  296. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.d.ts +7 -0
  297. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.js +17 -0
  298. package/dist/src/web-ui/local-runtime/plugin-removal-routes.d.ts +18 -0
  299. package/dist/src/web-ui/local-runtime/plugin-removal-routes.js +60 -0
  300. package/dist/src/web-ui/local-runtime/realtime-controller.js +41 -2
  301. package/dist/src/web-ui/local-runtime/request-cancellation-route.js +28 -1
  302. package/dist/src/web-ui/local-runtime/request-control-observation.d.ts +19 -0
  303. package/dist/src/web-ui/local-runtime/request-control-observation.js +80 -0
  304. package/dist/src/web-ui/local-runtime/request-execution.js +69 -37
  305. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +20 -0
  306. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +44 -0
  307. package/dist/src/web-ui/local-runtime/runtime-setup-routes.js +2 -0
  308. package/dist/src/web-ui/local-runtime/runtime-setup-validation.js +9 -2
  309. package/dist/src/web-ui/local-runtime/session-routes.d.ts +1 -0
  310. package/dist/src/web-ui/local-runtime/session-routes.js +16 -4
  311. package/dist/src/web-ui/local-runtime/spark-chat-routes.js +4 -3
  312. package/dist/src/web-ui/plugin-capability-selection.js +4 -1
  313. package/dist/src/web-ui/plugin-configuration-input.d.ts +12 -0
  314. package/dist/src/web-ui/plugin-configuration-input.js +68 -0
  315. package/dist/src/web-ui/plugin-configuration-retained-secrets.d.ts +9 -0
  316. package/dist/src/web-ui/plugin-configuration-retained-secrets.js +48 -0
  317. package/dist/src/web-ui/plugin-configuration-service.d.ts +52 -0
  318. package/dist/src/web-ui/plugin-configuration-service.js +66 -0
  319. package/dist/src/web-ui/plugin-configuration-view.d.ts +25 -0
  320. package/dist/src/web-ui/plugin-configuration-view.js +45 -0
  321. package/dist/src/web-ui/plugin-disabled-selection.d.ts +7 -0
  322. package/dist/src/web-ui/plugin-disabled-selection.js +17 -0
  323. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  324. package/dist/src/web-ui/plugin-management-catalog.js +11 -1
  325. package/dist/src/web-ui/plugin-management-selection.js +22 -9
  326. package/dist/src/web-ui/plugin-management-service.d.ts +5 -1
  327. package/dist/src/web-ui/plugin-management-service.js +11 -7
  328. package/dist/src/web-ui/plugin-removal-error.d.ts +7 -0
  329. package/dist/src/web-ui/plugin-removal-error.js +16 -0
  330. package/dist/src/web-ui/plugin-removal-service.d.ts +30 -0
  331. package/dist/src/web-ui/plugin-removal-service.js +109 -0
  332. package/dist/src/web-ui/runtime-setup-gateway.d.ts +6 -2
  333. package/dist/src/web-ui/runtime-setup-gateway.js +30 -10
  334. package/dist/src/web-ui/server.js +6 -2
  335. package/dist/src/web-ui/session-read-state/overview.d.ts +42 -0
  336. package/dist/src/web-ui/session-read-state/overview.js +16 -0
  337. package/dist/src/web-ui/session-read-state/pagination.d.ts +15 -0
  338. package/dist/src/web-ui/session-read-state/pagination.js +42 -0
  339. package/dist/src/web-ui/session-read-state/projection.d.ts +4 -3
  340. package/dist/src/web-ui/session-read-state/service.d.ts +213 -20
  341. package/dist/src/web-ui/session-read-state/service.js +25 -23
  342. package/dist/src/web-ui/session-read-state/visible-messages.d.ts +3 -3
  343. package/dist/src/web-ui/system-host-setup/companion-linux.js +1 -1
  344. package/dist/src/web-ui/system-host-setup/installer-contract.d.ts +1 -1
  345. package/dist/src/web-ui/system-host-setup/installer-contract.js +2 -2
  346. package/dist/src/web-ui/system-host-setup/installers.js +0 -7
  347. package/dist/src/web-ui/system-host-setup/local-connection.d.ts +4 -1
  348. package/dist/src/web-ui/system-host-setup/local-connection.js +10 -17
  349. package/dist/src/web-ui/system-host-setup/routes.d.ts +2 -0
  350. package/dist/src/web-ui/system-host-setup/routes.js +32 -9
  351. package/dist/src/web-ui/system-host-setup/setup-mutation.d.ts +9 -0
  352. package/dist/src/web-ui/system-host-setup/setup-mutation.js +27 -0
  353. package/dist/src/web-ui/system-host-setup/windows-store-route.d.ts +13 -0
  354. package/dist/src/web-ui/system-host-setup/windows-store-route.js +68 -0
  355. package/docs/configuration.md +46 -0
  356. package/docs/installation.md +45 -24
  357. package/docs/plugins.md +165 -2
  358. package/docs/projects-and-full-plus.md +2 -6
  359. package/docs/runtime-library.md +0 -1
  360. package/docs/windows-companion-store.md +127 -0
  361. package/package.json +3 -3
  362. package/plugins/document-reader/plugin.json +1 -0
  363. package/plugins/exec/plugin.json +3 -0
  364. package/plugins/filesystem/plugin.json +2 -0
  365. package/plugins/local-search/plugin.json +1 -0
  366. package/plugins/system/README.md +43 -3
  367. package/plugins/system/plugin.json +5 -0
  368. package/plugins/system/source/companion-command-output.ts +82 -0
  369. package/plugins/system/source/host-dispatch.ts +4 -0
  370. package/plugins/system/source/index.ts +11 -5
  371. package/plugins/system/source/local-command-output.ts +61 -0
  372. package/plugins/system/source/request-system-modules.ts +2 -0
  373. package/plugins/system/src/index.cjs +474 -39
  374. package/plugins/web/README.md +2 -2
  375. package/plugins/web/plugin.json +4 -0
  376. package/runtime.config.schema.json +25 -1
  377. package/src/runtime/README.md +12 -2
  378. package/dist/src/web-ui/system-host-setup/companion-windows.d.ts +0 -2
  379. package/dist/src/web-ui/system-host-setup/companion-windows.js +0 -108
  380. package/docs/publishing.md +0 -167
@@ -1,4 +1,4 @@
1
- import { traceDebug } from "../observability/debug-logger.js";
1
+ import { createRequestControlDiagnosticId, traceRequestControl, } from "../observability/request-control-diagnostics.js";
2
2
  export const REQUEST_STEERING_FEATURE = "request_steering_v1";
3
3
  export const REQUEST_STEERING_MESSAGE_KIND = "runtime_active_request_updates_v1";
4
4
  const LOG_SCOPE = "runtime.request_steering";
@@ -30,6 +30,10 @@ export function projectRequestSteeringSnapshot(inbox, version) {
30
30
  });
31
31
  }
32
32
  export function createRequestSteeringInbox(params) {
33
+ const diagnosticIdentity = {
34
+ inboxId: params.diagnostics?.inboxId ?? createRequestControlDiagnosticId("inbox"),
35
+ inboxOrigin: params.diagnostics?.origin ?? "request",
36
+ };
33
37
  const updates = [];
34
38
  const bySteerId = new Map();
35
39
  let closed = false;
@@ -37,6 +41,10 @@ export function createRequestSteeringInbox(params) {
37
41
  let persistenceBound = false;
38
42
  let persistUpdate;
39
43
  let persistenceTail = Promise.resolve();
44
+ traceRequestControl(LOG_SCOPE, "inbox.opened", {
45
+ ...diagnosticIdentity,
46
+ requestId: params.requestId,
47
+ });
40
48
  function schedulePersistence(update) {
41
49
  if (!persistUpdate)
42
50
  return;
@@ -44,7 +52,8 @@ export function createRequestSteeringInbox(params) {
44
52
  persistenceTail = persistenceTail.then(async () => {
45
53
  try {
46
54
  await persist(update);
47
- traceDebug(LOG_SCOPE, "update.persisted", {
55
+ traceRequestControl(LOG_SCOPE, "update.persisted", {
56
+ ...diagnosticIdentity,
48
57
  requestId: params.requestId,
49
58
  steerId: update.steerId,
50
59
  sequence: update.sequence,
@@ -52,7 +61,8 @@ export function createRequestSteeringInbox(params) {
52
61
  });
53
62
  }
54
63
  catch (error) {
55
- traceDebug(LOG_SCOPE, "update.persistence_failed", {
64
+ traceRequestControl(LOG_SCOPE, "update.persistence_failed", {
65
+ ...diagnosticIdentity,
56
66
  requestId: params.requestId,
57
67
  steerId: update.steerId,
58
68
  sequence: update.sequence,
@@ -66,8 +76,10 @@ export function createRequestSteeringInbox(params) {
66
76
  const steerId = input.steerId.trim();
67
77
  const text = input.text.trim();
68
78
  if (!steerId || !text) {
69
- traceDebug(LOG_SCOPE, "update.rejected", {
79
+ traceRequestControl(LOG_SCOPE, "update.rejected", {
80
+ ...diagnosticIdentity,
70
81
  requestId: params.requestId,
82
+ steerId,
71
83
  reason: "invalid_steer_request",
72
84
  steerIdLength: steerId.length,
73
85
  textLength: text.length,
@@ -80,7 +92,8 @@ export function createRequestSteeringInbox(params) {
80
92
  const existing = bySteerId.get(steerId);
81
93
  if (existing) {
82
94
  if (existing.text !== text) {
83
- traceDebug(LOG_SCOPE, "update.rejected", {
95
+ traceRequestControl(LOG_SCOPE, "update.rejected", {
96
+ ...diagnosticIdentity,
84
97
  requestId: params.requestId,
85
98
  steerId,
86
99
  reason: "steer_id_conflict",
@@ -90,7 +103,8 @@ export function createRequestSteeringInbox(params) {
90
103
  reason: "steer_id_conflict",
91
104
  });
92
105
  }
93
- traceDebug(LOG_SCOPE, "update.duplicate", {
106
+ traceRequestControl(LOG_SCOPE, "update.duplicate", {
107
+ ...diagnosticIdentity,
94
108
  requestId: params.requestId,
95
109
  steerId,
96
110
  sequence: existing.sequence,
@@ -102,7 +116,8 @@ export function createRequestSteeringInbox(params) {
102
116
  });
103
117
  }
104
118
  if (closed || sealed) {
105
- traceDebug(LOG_SCOPE, "update.rejected", {
119
+ traceRequestControl(LOG_SCOPE, "update.rejected", {
120
+ ...diagnosticIdentity,
106
121
  requestId: params.requestId,
107
122
  steerId,
108
123
  reason: "request_not_active",
@@ -122,7 +137,8 @@ export function createRequestSteeringInbox(params) {
122
137
  updates.push(update);
123
138
  bySteerId.set(steerId, update);
124
139
  schedulePersistence(update);
125
- traceDebug(LOG_SCOPE, "update.accepted", {
140
+ traceRequestControl(LOG_SCOPE, "update.accepted", {
141
+ ...diagnosticIdentity,
126
142
  requestId: params.requestId,
127
143
  steerId,
128
144
  sequence: update.sequence,
@@ -144,7 +160,8 @@ export function createRequestSteeringInbox(params) {
144
160
  for (const update of updates) {
145
161
  schedulePersistence(update);
146
162
  }
147
- traceDebug(LOG_SCOPE, "persistence.bound", {
163
+ traceRequestControl(LOG_SCOPE, "persistence.bound", {
164
+ ...diagnosticIdentity,
148
165
  requestId: params.requestId,
149
166
  queuedUpdateCount: updates.length,
150
167
  });
@@ -156,8 +173,14 @@ export function createRequestSteeringInbox(params) {
156
173
  }
157
174
  closed = true;
158
175
  sealed = true;
176
+ traceRequestControl(LOG_SCOPE, "inbox.closing", {
177
+ ...diagnosticIdentity,
178
+ requestId: params.requestId,
179
+ updateCount: updates.length,
180
+ });
159
181
  await persistenceTail;
160
- traceDebug(LOG_SCOPE, "inbox.closed", {
182
+ traceRequestControl(LOG_SCOPE, "inbox.closed", {
183
+ ...diagnosticIdentity,
161
184
  requestId: params.requestId,
162
185
  updateCount: updates.length,
163
186
  });
@@ -167,7 +190,8 @@ export function createRequestSteeringInbox(params) {
167
190
  },
168
191
  seal(version) {
169
192
  if (closed || sealed || updates.length !== version) {
170
- traceDebug(LOG_SCOPE, "finalization.rejected", {
193
+ traceRequestControl(LOG_SCOPE, "finalization.rejected", {
194
+ ...diagnosticIdentity,
171
195
  requestId: params.requestId,
172
196
  expectedVersion: version,
173
197
  currentVersion: updates.length,
@@ -177,7 +201,8 @@ export function createRequestSteeringInbox(params) {
177
201
  return false;
178
202
  }
179
203
  sealed = true;
180
- traceDebug(LOG_SCOPE, "finalization.sealed", {
204
+ traceRequestControl(LOG_SCOPE, "finalization.sealed", {
205
+ ...diagnosticIdentity,
181
206
  requestId: params.requestId,
182
207
  version,
183
208
  });
@@ -1,3 +1,4 @@
1
+ import type { RuntimeModelPluginConfig } from "../config/model-plugin-config.js";
1
2
  import type { RuntimeFilesystemScope } from "../context/runtime-filesystem-scope.js";
2
3
  import type { RuntimeConfig, ToolRegistry } from "../ports.js";
3
4
  import type { ToolRequestAttachment } from "../../capabilities/tool-types.js";
@@ -10,6 +11,7 @@ type RequestWorkerCapabilityProviderParams<TRequest> = Readonly<{
10
11
  requestWorkingDirectory?: string;
11
12
  filesystemScope?: RuntimeFilesystemScope;
12
13
  executionPolicyAuthority?: ExecutionPolicyAuthoritySnapshot;
14
+ modelPlugins?: RuntimeModelPluginConfig;
13
15
  requestAttachments?: readonly ToolRequestAttachment[];
14
16
  runtimeConfig?: RuntimeConfig;
15
17
  toolRegistryOverride?: ToolRegistry;
@@ -16,6 +16,7 @@ export function createRequestWorkerCapabilityProvider(params) {
16
16
  request: params.request,
17
17
  requestWorkingDirectory: params.requestWorkingDirectory,
18
18
  toolPermissionMode: params.request.toolPermissionMode,
19
+ ...(params.modelPlugins ? { modelPlugins: params.modelPlugins } : {}),
19
20
  ...(params.requestAttachments
20
21
  ? { requestAttachments: params.requestAttachments }
21
22
  : {}),
@@ -41,7 +42,9 @@ export function createRequestWorkerCapabilityProvider(params) {
41
42
  const provider = createRegisteredToolWorkerCapabilityProvider({
42
43
  getRequestToolRegistry,
43
44
  requestId: params.request.requestId,
44
- ...(params.request.toolResources ? { toolResources: params.request.toolResources } : {}),
45
+ ...(params.request.toolResources
46
+ ? { toolResources: params.request.toolResources }
47
+ : {}),
45
48
  sessionId: params.request.sessionId,
46
49
  requestContext: Object.freeze({
47
50
  agentMode: params.request.agentMode,
@@ -23,10 +23,10 @@ export declare function encodeJournalIndexState(state: JournalIndexState, genera
23
23
  runs: {
24
24
  file: string;
25
25
  id: string;
26
- environmentId: string;
27
26
  status: import("./contracts.js").SchedulerRunStatus | "stopping" | "completed_with_skips";
28
27
  jobId: string;
29
28
  scheduledAt: string;
29
+ environmentId: string;
30
30
  jobRevision: number;
31
31
  target?: SchedulerStoredRun["target"];
32
32
  sessionId?: string;
@@ -0,0 +1,3 @@
1
+ import type { SessionMessage } from "./types.js";
2
+ /** Classification shared by persisted projections and model history. */
3
+ export declare function isAssistantInitiativeMessage(message: SessionMessage): boolean;
@@ -0,0 +1,12 @@
1
+ /** Classification shared by persisted projections and model history. */
2
+ export function isAssistantInitiativeMessage(message) {
3
+ if (message.role !== "assistant")
4
+ return false;
5
+ if (message.source !== "co_worker")
6
+ return false;
7
+ if (message.initiative?.kind !== "proactive_proposal_v1")
8
+ return false;
9
+ if (typeof message.initiative.proposalId !== "string")
10
+ return false;
11
+ return message.initiative.proposalId.length > 0;
12
+ }
@@ -1,4 +1,5 @@
1
- import type { SessionMessage, SessionRecord } from "./types.js";
1
+ import type { SessionRecord } from "./types.js";
2
+ export { isAssistantInitiativeMessage } from "./assistant-initiative-message.js";
2
3
  export type AssistantInitiative = Readonly<{
3
4
  kind: "proactive_proposal_v1";
4
5
  proposalId: string;
@@ -26,5 +27,4 @@ export declare function createAssistantConversationRecord(options: {
26
27
  input: CreateAssistantConversationInput;
27
28
  now: Date;
28
29
  }): Promise<SessionRecord>;
29
- export declare function isAssistantInitiativeMessage(message: SessionMessage): boolean;
30
30
  export declare function assertAssistantInitiative(input: CreateAssistantConversationInput): void;
@@ -1,6 +1,7 @@
1
1
  import { assertValidSessionId } from "./record/rules.js";
2
2
  import { deleteSessionFile, ensureSessionsDir, loadSessionFile, saveSessionFile } from "./session-store.js";
3
3
  import { isSparkHandoffBrief } from "./spark-handoff-brief.js";
4
+ export { isAssistantInitiativeMessage } from "./assistant-initiative-message.js";
4
5
  /** Called under the same per-session mutation queue as edits and deletion. */
5
6
  export async function createAssistantConversationRecord(options) {
6
7
  const { sessionId, input } = options;
@@ -34,13 +35,6 @@ export async function createAssistantConversationRecord(options) {
34
35
  }
35
36
  return record;
36
37
  }
37
- export function isAssistantInitiativeMessage(message) {
38
- if (message.role !== "assistant" || message.source !== "co_worker")
39
- return false;
40
- if (message.initiative?.kind !== "proactive_proposal_v1")
41
- return false;
42
- return typeof message.initiative.proposalId === "string" && message.initiative.proposalId.length > 0;
43
- }
44
38
  export function assertAssistantInitiative(input) {
45
39
  if (!input.title.trim() || input.title.length > 160)
46
40
  throw new Error("assistant_initiative_title_invalid");
@@ -1,4 +1,5 @@
1
1
  import type { SessionRecord } from "./types.js";
2
+ import type { SessionMetadataChange } from "./metadata/source-receipt.js";
2
3
  export declare class SessionCommitOutcomeUnknownError extends Error {
3
4
  readonly sessionId: string;
4
5
  readonly code = "session_commit_outcome_unknown";
@@ -6,4 +7,4 @@ export declare class SessionCommitOutcomeUnknownError extends Error {
6
7
  }
7
8
  export declare function syncSessionDirectory(directory: string): Promise<void>;
8
9
  /** Same session file and replacement boundary, with explicit durable-commit errors. */
9
- export declare function saveDurableSessionFile(sessionsDir: string, session: SessionRecord, assertCurrent?: () => void): Promise<void>;
10
+ export declare function saveDurableSessionFile(sessionsDir: string, session: SessionRecord, assertCurrent?: () => void, metadataChange?: SessionMetadataChange): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { open, rename, rm } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
+ import { currentSourceStamp, sessionSourceStamp, updateSessionMetadata } from "./metadata/store.js";
4
5
  export class SessionCommitOutcomeUnknownError extends Error {
5
6
  sessionId;
6
7
  code = "session_commit_outcome_unknown";
@@ -24,15 +25,18 @@ export async function syncSessionDirectory(directory) {
24
25
  }
25
26
  }
26
27
  /** Same session file and replacement boundary, with explicit durable-commit errors. */
27
- export async function saveDurableSessionFile(sessionsDir, session, assertCurrent) {
28
+ export async function saveDurableSessionFile(sessionsDir, session, assertCurrent, metadataChange = "projection") {
28
29
  const target = join(sessionsDir, `${session.id}.json`);
30
+ const previousSource = metadataChange === "request-only" ? await currentSourceStamp(target) : undefined;
29
31
  const temporary = `${target}.${process.pid}.${randomUUID()}.tmp`;
30
32
  let replaced = false;
33
+ let source;
31
34
  try {
32
35
  const handle = await open(temporary, "wx", 0o600);
33
36
  try {
34
37
  await handle.writeFile(JSON.stringify(session, null, 2), "utf8");
35
38
  await handle.sync();
39
+ source = sessionSourceStamp(await handle.stat({ bigint: true }));
36
40
  }
37
41
  finally {
38
42
  await handle.close();
@@ -48,4 +52,5 @@ export async function saveDurableSessionFile(sessionsDir, session, assertCurrent
48
52
  throw new SessionCommitOutcomeUnknownError(session.id, { cause: error });
49
53
  throw error;
50
54
  }
55
+ await updateSessionMetadata(sessionsDir, session, source, previousSource);
51
56
  }
@@ -0,0 +1,15 @@
1
+ import type { SessionListItem, SessionRecord, SessionSnapshotMessage } from "../types.js";
2
+ export type SessionMessageMetadata = Pick<SessionSnapshotMessage, "id" | "role" | "createdAt">;
3
+ /** Derived data only. User read cursors stay in the Web UI's existing store. */
4
+ export type SessionMetadata = {
5
+ version: 1;
6
+ source: string;
7
+ interactive: boolean;
8
+ updatedAt: string;
9
+ summary: SessionListItem;
10
+ messages: SessionMessageMetadata[];
11
+ };
12
+ export declare function projectSessionMetadata(session: SessionRecord, source: string): SessionMetadata;
13
+ export declare function isCurrentSessionMetadata(value: unknown, sessionId: string, source: string): value is SessionMetadata;
14
+ /** Stable ordering is owned here so future paging need not change callers' storage knowledge. */
15
+ export declare function compareSessionMetadata(left: SessionMetadata, right: SessionMetadata): number;
@@ -0,0 +1,55 @@
1
+ import { hasAutomationSessionOrigin } from "../automation-session-origin.js";
2
+ import { clientVisibleMessages, toEpochMs, toMessageIdForUi, toSessionListItem, } from "../record/projection.js";
3
+ export function projectSessionMetadata(session, source) {
4
+ return {
5
+ version: 1,
6
+ source,
7
+ interactive: !hasAutomationSessionOrigin(session),
8
+ updatedAt: session.updatedAt,
9
+ summary: toSessionListItem(session),
10
+ messages: clientVisibleMessages(session.messages).map((message) => ({
11
+ id: toMessageIdForUi(message.id),
12
+ role: message.role,
13
+ createdAt: toEpochMs(message.createdAt),
14
+ })),
15
+ };
16
+ }
17
+ function isMessageMetadata(value) {
18
+ if (!value)
19
+ return false;
20
+ if (typeof value.id !== "string" && typeof value.id !== "number")
21
+ return false;
22
+ if (value.role !== "user" && value.role !== "assistant")
23
+ return false;
24
+ return Number.isFinite(value.createdAt);
25
+ }
26
+ export function isCurrentSessionMetadata(value, sessionId, source) {
27
+ if (!value || typeof value !== "object")
28
+ return false;
29
+ const record = value;
30
+ if (record.version !== 1)
31
+ return false;
32
+ if (record.source !== source)
33
+ return false;
34
+ if (typeof record.interactive !== "boolean")
35
+ return false;
36
+ if (typeof record.updatedAt !== "string")
37
+ return false;
38
+ if (record.summary?.id !== sessionId)
39
+ return false;
40
+ if (typeof record.summary.title !== "string")
41
+ return false;
42
+ if (typeof record.summary.lastMessagePreview !== "string")
43
+ return false;
44
+ if (!Number.isFinite(record.summary.createdAt))
45
+ return false;
46
+ if (!Number.isFinite(record.summary.updatedAt))
47
+ return false;
48
+ if (!Array.isArray(record.messages))
49
+ return false;
50
+ return record.messages.every(isMessageMetadata);
51
+ }
52
+ /** Stable ordering is owned here so future paging need not change callers' storage knowledge. */
53
+ export function compareSessionMetadata(left, right) {
54
+ return right.updatedAt.localeCompare(left.updatedAt) || left.summary.id.localeCompare(right.summary.id);
55
+ }
@@ -0,0 +1,12 @@
1
+ import type { BigIntStats } from "node:fs";
2
+ export declare function isMissingSessionFile(error: unknown): boolean;
3
+ export declare function sessionSourceStamp(source: BigIntStats): string;
4
+ export declare function currentSourceStamp(path: string): Promise<string | null>;
5
+ export declare function reportMetadataFailure(sessionId: string, error: unknown): void;
6
+ /** Only the derived index is expendable; canonical session read failures still propagate. */
7
+ export declare function readMetadataJson(path: string): Promise<unknown>;
8
+ /** Serialize index publication/deletion by session, never across unrelated sessions. */
9
+ export declare function publishSessionMetadata(path: string, operation: () => Promise<void>): Promise<void>;
10
+ /** List backfills and the Runtime owner may run in different processes. */
11
+ export declare function publishSessionProjection(path: string, operation: () => Promise<void>): Promise<void>;
12
+ export declare function writeMetadataJson(target: string, value: unknown, sourcePath: string, source: string): Promise<boolean>;
@@ -0,0 +1,78 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
3
+ import { dirname, resolve } from "node:path";
4
+ import { withFileLock } from "../../runtime/adapters/long-term-memory/file-lock.js";
5
+ const pendingPublications = new Map();
6
+ export function isMissingSessionFile(error) {
7
+ return error?.code === "ENOENT";
8
+ }
9
+ export function sessionSourceStamp(source) {
10
+ return `${source.dev}:${source.ino}:${source.size}:${source.mtimeNs}`;
11
+ }
12
+ export async function currentSourceStamp(path) {
13
+ try {
14
+ return sessionSourceStamp(await stat(path, { bigint: true }));
15
+ }
16
+ catch (error) {
17
+ if (isMissingSessionFile(error))
18
+ return null;
19
+ throw error;
20
+ }
21
+ }
22
+ export function reportMetadataFailure(sessionId, error) {
23
+ process.emitWarning(`Session metadata update failed for ${sessionId}: ${String(error)}`, {
24
+ code: "SESSION_METADATA_WRITE_FAILED",
25
+ });
26
+ }
27
+ /** Only the derived index is expendable; canonical session read failures still propagate. */
28
+ export async function readMetadataJson(path) {
29
+ try {
30
+ return JSON.parse(await readFile(path, "utf8"));
31
+ }
32
+ catch (error) {
33
+ if (isMissingSessionFile(error))
34
+ return null;
35
+ if (error instanceof SyntaxError)
36
+ return null;
37
+ reportMetadataFailure(path, error);
38
+ return null;
39
+ }
40
+ }
41
+ /** Serialize index publication/deletion by session, never across unrelated sessions. */
42
+ export async function publishSessionMetadata(path, operation) {
43
+ const key = resolve(path);
44
+ const previous = pendingPublications.get(key) ?? Promise.resolve();
45
+ const pending = previous.then(operation).catch((error) => reportMetadataFailure(path, error));
46
+ pendingPublications.set(key, pending);
47
+ try {
48
+ await pending;
49
+ }
50
+ finally {
51
+ if (pendingPublications.get(key) === pending)
52
+ pendingPublications.delete(key);
53
+ }
54
+ }
55
+ /** List backfills and the Runtime owner may run in different processes. */
56
+ export async function publishSessionProjection(path, operation) {
57
+ return publishSessionMetadata(path, async () => {
58
+ await mkdir(dirname(path), { recursive: true });
59
+ await withFileLock(`${path}.lock`, operation);
60
+ });
61
+ }
62
+ export async function writeMetadataJson(target, value, sourcePath, source) {
63
+ if (await currentSourceStamp(sourcePath) !== source)
64
+ return false;
65
+ await mkdir(dirname(target), { recursive: true });
66
+ const temporary = `${target}.${process.pid}.${randomUUID()}.tmp`;
67
+ try {
68
+ await writeFile(temporary, JSON.stringify(value), { encoding: "utf8", mode: 0o600 });
69
+ // Validate at publication too: the canonical file may change while writing the temporary.
70
+ if (await currentSourceStamp(sourcePath) !== source)
71
+ return false;
72
+ await rename(temporary, target);
73
+ return true;
74
+ }
75
+ finally {
76
+ await rm(temporary, { force: true });
77
+ }
78
+ }
@@ -0,0 +1,5 @@
1
+ import type { SessionMetadata } from "./projection.js";
2
+ export type SessionMetadataChange = "projection" | "request-only";
3
+ export declare function writeSourceReceipt(path: string, sourcePath: string, source: string, updatedAt: string, previousSource?: string): Promise<void>;
4
+ /** Bind request-only changes to the exact projection they left unchanged. */
5
+ export declare function applySourceReceipt(path: string, record: SessionMetadata, source: string): Promise<SessionMetadata | null>;
@@ -0,0 +1,42 @@
1
+ import { toEpochMs } from "../record/projection.js";
2
+ import { readMetadataJson, writeMetadataJson } from "./publication.js";
3
+ function isSourceReceipt(value) {
4
+ if (!value || typeof value !== "object")
5
+ return false;
6
+ const receipt = value;
7
+ if (receipt.version !== 1)
8
+ return false;
9
+ if (typeof receipt.source !== "string")
10
+ return false;
11
+ if (typeof receipt.projectionSource !== "string")
12
+ return false;
13
+ return typeof receipt.updatedAt === "string";
14
+ }
15
+ async function receiptProjectionSource(path, source, previousSource) {
16
+ if (previousSource === undefined)
17
+ return source;
18
+ const previous = await readMetadataJson(path);
19
+ if (!isSourceReceipt(previous))
20
+ return previousSource;
21
+ if (previous.source !== previousSource)
22
+ return previousSource;
23
+ return previous.projectionSource;
24
+ }
25
+ export async function writeSourceReceipt(path, sourcePath, source, updatedAt, previousSource) {
26
+ const projectionSource = await receiptProjectionSource(path, source, previousSource);
27
+ await writeMetadataJson(path, { version: 1, source, projectionSource, updatedAt }, sourcePath, source);
28
+ }
29
+ /** Bind request-only changes to the exact projection they left unchanged. */
30
+ export async function applySourceReceipt(path, record, source) {
31
+ const receipt = await readMetadataJson(path);
32
+ if (!isSourceReceipt(receipt))
33
+ return null;
34
+ if (receipt.source !== source)
35
+ return null;
36
+ if (receipt.projectionSource !== record.source)
37
+ return null;
38
+ return {
39
+ ...record, source, updatedAt: receipt.updatedAt,
40
+ summary: { ...record.summary, updatedAt: toEpochMs(receipt.updatedAt) },
41
+ };
42
+ }
@@ -0,0 +1,7 @@
1
+ import type { SessionRecord } from "../types.js";
2
+ import { type SessionMetadata } from "./projection.js";
3
+ export { currentSourceStamp, sessionSourceStamp } from "./publication.js";
4
+ /** The canonical session has already committed. A derived-index failure cannot undo it. */
5
+ export declare function updateSessionMetadata(sessionsDir: string, session: SessionRecord, source: string, previousSource?: string | null): Promise<void>;
6
+ export declare function deleteSessionMetadata(sessionsDir: string, sessionId: string): Promise<void>;
7
+ export declare function listSessionMetadata(sessionsDir: string): Promise<SessionMetadata[]>;
@@ -0,0 +1,119 @@
1
+ import { mkdir, open, readdir, rm } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { compareSessionMetadata, isCurrentSessionMetadata, projectSessionMetadata, } from "./projection.js";
4
+ import { currentSourceStamp, isMissingSessionFile, publishSessionMetadata, publishSessionProjection, readMetadataJson, reportMetadataFailure, sessionSourceStamp, writeMetadataJson, } from "./publication.js";
5
+ import { applySourceReceipt, writeSourceReceipt } from "./source-receipt.js";
6
+ export { currentSourceStamp, sessionSourceStamp } from "./publication.js";
7
+ const pendingLists = new Map();
8
+ const concurrentMetadataReads = 4;
9
+ function metadataPath(sessionsDir, sessionId) {
10
+ return join(sessionsDir, ".metadata", `${sessionId}.json`);
11
+ }
12
+ async function writeMetadata(sessionsDir, record) {
13
+ const target = metadataPath(sessionsDir, record.summary.id);
14
+ const sourcePath = join(sessionsDir, `${record.summary.id}.json`);
15
+ await publishSessionProjection(target, async () => {
16
+ if (!await writeMetadataJson(target, record, sourcePath, record.source))
17
+ return;
18
+ // The full projection already carries its source; only request-only changes need a receipt.
19
+ await rm(`${target}.source`, { force: true });
20
+ });
21
+ }
22
+ /** The canonical session has already committed. A derived-index failure cannot undo it. */
23
+ export async function updateSessionMetadata(sessionsDir, session, source, previousSource) {
24
+ if (previousSource) {
25
+ const target = metadataPath(sessionsDir, session.id);
26
+ return publishSessionMetadata(target, () => writeSourceReceipt(`${target}.source`, join(sessionsDir, `${session.id}.json`), source, session.updatedAt, previousSource));
27
+ }
28
+ try {
29
+ await writeMetadata(sessionsDir, projectSessionMetadata(session, source));
30
+ }
31
+ catch (error) {
32
+ reportMetadataFailure(session.id, error);
33
+ }
34
+ }
35
+ export async function deleteSessionMetadata(sessionsDir, sessionId) {
36
+ const target = metadataPath(sessionsDir, sessionId);
37
+ await publishSessionProjection(target, async () => {
38
+ await rm(target, { force: true });
39
+ await rm(`${target}.source`, { force: true });
40
+ });
41
+ }
42
+ async function readSourceMetadata(path) {
43
+ const handle = await open(path, "r").catch((error) => {
44
+ if (isMissingSessionFile(error))
45
+ return null;
46
+ throw error;
47
+ });
48
+ if (!handle)
49
+ return null;
50
+ try {
51
+ const source = sessionSourceStamp(await handle.stat({ bigint: true }));
52
+ const session = JSON.parse(await handle.readFile("utf8"));
53
+ return projectSessionMetadata(session, source);
54
+ }
55
+ finally {
56
+ await handle.close();
57
+ }
58
+ }
59
+ async function readCurrentMetadata(target, sessionId, source) {
60
+ const stored = await readMetadataJson(target);
61
+ if (isCurrentSessionMetadata(stored, sessionId, source))
62
+ return stored;
63
+ const projectionSource = stored?.source;
64
+ if (typeof projectionSource !== "string")
65
+ return null;
66
+ if (!isCurrentSessionMetadata(stored, sessionId, projectionSource))
67
+ return null;
68
+ return applySourceReceipt(`${target}.source`, stored, source);
69
+ }
70
+ async function loadMetadata(sessionsDir, sessionId) {
71
+ const path = join(sessionsDir, `${sessionId}.json`);
72
+ const source = await currentSourceStamp(path);
73
+ if (source === null)
74
+ return null;
75
+ const current = await readCurrentMetadata(metadataPath(sessionsDir, sessionId), sessionId, source);
76
+ if (current)
77
+ return current;
78
+ const rebuilt = await readSourceMetadata(path);
79
+ if (!rebuilt)
80
+ return null;
81
+ await writeMetadata(sessionsDir, rebuilt);
82
+ return rebuilt;
83
+ }
84
+ function settledMetadata(result) {
85
+ if (result.status === "rejected")
86
+ throw result.reason;
87
+ return result.value;
88
+ }
89
+ /**
90
+ * Each atomically published record completes its own backfill. Restarts reuse
91
+ * those records; interrupted backfills only rebuild missing/stale entries.
92
+ * Source stamps also detect older writers and a crash between the two commits.
93
+ */
94
+ async function readMetadataList(sessionsDir) {
95
+ await mkdir(sessionsDir, { recursive: true });
96
+ const names = (await readdir(sessionsDir)).filter((name) => name.endsWith(".json"));
97
+ const records = [];
98
+ for (let offset = 0; offset < names.length; offset += concurrentMetadataReads) {
99
+ // Bound disk fan-out and drain the batch before propagating a canonical read failure.
100
+ const batch = await Promise.allSettled(names.slice(offset, offset + concurrentMetadataReads)
101
+ .map((name) => loadMetadata(sessionsDir, name.slice(0, -5))));
102
+ records.push(...batch.map(settledMetadata).filter((record) => record !== null));
103
+ }
104
+ return records.sort(compareSessionMetadata);
105
+ }
106
+ export async function listSessionMetadata(sessionsDir) {
107
+ const directory = resolve(sessionsDir);
108
+ const existing = pendingLists.get(directory);
109
+ if (existing)
110
+ return existing;
111
+ const pending = readMetadataList(directory);
112
+ pendingLists.set(directory, pending);
113
+ try {
114
+ return await pending;
115
+ }
116
+ finally {
117
+ pendingLists.delete(directory);
118
+ }
119
+ }
@@ -7,10 +7,12 @@ export declare function normalizeAfterSeq(afterSeq: number): number;
7
7
  export declare function toEpochMs(timestamp: string): number;
8
8
  export declare function toClientReplayEvent(event: SessionRuntimeEvent): Record<string, unknown>;
9
9
  export declare function getRequestFinalState(request: SessionRequestRecord): SessionRequestReplay["finalState"];
10
+ export declare function toMessageIdForUi(id: string): string | number;
10
11
  export declare function isSameMessageId(messageId: string, requestedId: string): boolean;
11
12
  export declare function filterMessagesAfter(messages: SessionRecord["messages"], afterMessageId: string | number | null | undefined): SessionRecord["messages"];
12
13
  export declare function clientVisibleMessages(messages: SessionRecord["messages"]): SessionRecord["messages"];
13
- export declare function toSnapshotMessage(sessionId: string, message: SessionRecord["messages"][number], requests: SessionRequestRecord[]): SessionSnapshotMessage;
14
+ export declare function toSnapshotMessage(sessionId: string, message: SessionRecord["messages"][number], requests: SessionRequestRecord[], resolveRequestId?: (message: SessionRecord["messages"][number]) => string | null): SessionSnapshotMessage;
15
+ export declare function createMessageRequestIdResolver(requests: SessionRequestRecord[]): (message: SessionRecord["messages"][number]) => string | null;
14
16
  export declare function toSnapshotRequest(request: SessionRequestRecord): SessionSnapshotRequest;
15
17
  export declare function normalizeSessionTitle(title: string): string;
16
18
  export declare function toSessionListItem(session: SessionRecord): {