@abot-ai/runtime 1.7.0 → 1.8.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 (443) hide show
  1. package/dist/src/capabilities/tool-request-resources.d.ts +3 -0
  2. package/dist/src/cli/abot.js +2 -0
  3. package/dist/src/cli/host-companion-bundle.mjs +751 -333
  4. package/dist/src/computer-access/collection-consent.d.ts +9 -0
  5. package/dist/src/computer-access/collection-consent.js +47 -0
  6. package/dist/src/computer-access/command-output-capture.d.ts +17 -6
  7. package/dist/src/computer-access/command-output-capture.js +134 -68
  8. package/dist/src/computer-access/command-output-protection.d.ts +17 -0
  9. package/dist/src/computer-access/command-output-protection.js +59 -0
  10. package/dist/src/computer-access/companion/command-output.d.ts +1 -0
  11. package/dist/src/computer-access/companion/command-output.js +23 -6
  12. package/dist/src/computer-access/companion/install-link-macos.js +2 -1
  13. package/dist/src/computer-access/companion/native-notifications.js +3 -2
  14. package/dist/src/computer-access/companion/native-session.js +6 -2
  15. package/dist/src/computer-access/companion/observation-filter.js +2 -26
  16. package/dist/src/computer-access/companion/observation-process.d.ts +2 -0
  17. package/dist/src/computer-access/companion/observation-process.js +51 -25
  18. package/dist/src/computer-access/companion/observation-redaction.d.ts +2 -7
  19. package/dist/src/computer-access/companion/observation-redaction.js +2 -111
  20. package/dist/src/computer-access/companion/secret-protection-protocol.d.ts +6 -0
  21. package/dist/src/computer-access/companion/secret-protection-protocol.js +6 -0
  22. package/dist/src/computer-access/computer/companion-sessions.js +7 -6
  23. package/dist/src/computer-access/computer/unix-native-process.js +23 -11
  24. package/dist/src/computer-access/handlers.d.ts +2 -1
  25. package/dist/src/computer-access/handlers.js +79 -11
  26. package/dist/src/computer-access/host-observation.d.ts +3 -3
  27. package/dist/src/computer-access/native-observation-connection.d.ts +12 -0
  28. package/dist/src/computer-access/native-observation-connection.js +78 -0
  29. package/dist/src/computer-access/native-observation-ownership.d.ts +6 -0
  30. package/dist/src/computer-access/native-observation-ownership.js +55 -0
  31. package/dist/src/computer-access/native-observation-shutdown.d.ts +7 -0
  32. package/dist/src/computer-access/native-observation-shutdown.js +58 -0
  33. package/dist/src/computer-access/observation-source.d.ts +6 -0
  34. package/dist/src/computer-access/observation-source.js +10 -0
  35. package/dist/src/computer-access/security/desktop-result.d.ts +8 -0
  36. package/dist/src/computer-access/security/desktop-result.js +146 -0
  37. package/dist/src/computer-access/security/observed-error.d.ts +2 -0
  38. package/dist/src/computer-access/security/observed-error.js +10 -0
  39. package/dist/src/computer-access/security/secret-text.d.ts +7 -0
  40. package/dist/src/computer-access/security/secret-text.js +111 -0
  41. package/dist/src/computer-access/security/system-results.d.ts +2 -0
  42. package/dist/src/computer-access/security/system-results.js +53 -0
  43. package/dist/src/computer-access/system-result-protection.d.ts +11 -0
  44. package/dist/src/computer-access/system-result-protection.js +1 -0
  45. package/dist/src/model-gateway/observability/provider-response-capture.d.ts +60 -0
  46. package/dist/src/model-gateway/observability/provider-response-capture.js +68 -0
  47. package/dist/src/model-gateway/observability/provider-response-prefix.d.ts +7 -0
  48. package/dist/src/model-gateway/observability/provider-response-prefix.js +14 -0
  49. package/dist/src/model-gateway/observability/provider-response-tail.d.ts +8 -0
  50. package/dist/src/model-gateway/observability/provider-response-tail.js +28 -0
  51. package/dist/src/model-gateway/observability/provider-sse-diagnostics.d.ts +30 -0
  52. package/dist/src/model-gateway/observability/provider-sse-diagnostics.js +119 -0
  53. package/dist/src/model-gateway/observability/provider-trace.js +30 -8
  54. package/dist/src/model-gateway/providers/ollama/adapter.js +8 -2
  55. package/dist/src/model-gateway/providers/ollama/stream-normalizer.js +70 -50
  56. package/dist/src/model-gateway/providers/ollama/stream-termination.d.ts +6 -0
  57. package/dist/src/model-gateway/providers/ollama/stream-termination.js +20 -0
  58. package/dist/src/model-gateway/providers/openai/adapter.js +9 -7
  59. package/dist/src/model-gateway/providers/openai/diagnostics.d.ts +0 -1
  60. package/dist/src/model-gateway/providers/openai/diagnostics.js +0 -9
  61. package/dist/src/model-gateway/providers/openai/function-output.d.ts +11 -0
  62. package/dist/src/model-gateway/providers/openai/function-output.js +37 -0
  63. package/dist/src/model-gateway/providers/openai/function-result.d.ts +7 -0
  64. package/dist/src/model-gateway/providers/openai/function-result.js +35 -0
  65. package/dist/src/model-gateway/providers/openai/message-output-policy.d.ts +3 -0
  66. package/dist/src/model-gateway/providers/openai/message-output-policy.js +16 -0
  67. package/dist/src/model-gateway/providers/openai/payload.d.ts +0 -2
  68. package/dist/src/model-gateway/providers/openai/payload.js +6 -23
  69. package/dist/src/model-gateway/providers/openai/response-lifetime.d.ts +2 -0
  70. package/dist/src/model-gateway/providers/openai/response-lifetime.js +64 -0
  71. package/dist/src/model-gateway/providers/openai/sse-data.d.ts +9 -0
  72. package/dist/src/model-gateway/providers/openai/sse-data.js +67 -0
  73. package/dist/src/model-gateway/providers/openai/stream-normalizer.d.ts +10 -22
  74. package/dist/src/model-gateway/providers/openai/stream-normalizer.js +78 -79
  75. package/dist/src/model-gateway/providers/openai/stream.js +13 -41
  76. package/dist/src/model-gateway/providers/openai/structured-message-output.d.ts +42 -0
  77. package/dist/src/model-gateway/providers/openai/structured-message-output.js +175 -0
  78. package/dist/src/model-gateway/server.js +5 -1
  79. package/dist/src/plugin-contract/index.d.ts +1 -0
  80. package/dist/src/plugin-contract/index.js +1 -0
  81. package/dist/src/plugin-contract/manifest.d.ts +2 -0
  82. package/dist/src/plugin-contract/manifest.js +1 -0
  83. package/dist/src/plugin-contract/platform-compatibility.d.ts +16 -0
  84. package/dist/src/plugin-contract/platform-compatibility.js +3 -0
  85. package/dist/src/plugin-sdk/computer-access.d.ts +4 -0
  86. package/dist/src/plugin-sdk/computer-access.js +1 -0
  87. package/dist/src/plugin-sdk/files-windows/process.d.ts +3 -0
  88. package/dist/src/plugin-sdk/files-windows/process.js +93 -0
  89. package/dist/src/plugin-sdk/files-windows/read-script.d.ts +1 -0
  90. package/dist/src/plugin-sdk/files-windows/read-script.js +43 -0
  91. package/dist/src/plugin-sdk/files-windows/read.d.ts +6 -0
  92. package/dist/src/plugin-sdk/files-windows/read.js +56 -0
  93. package/dist/src/plugin-sdk/files-windows/result.d.ts +4 -0
  94. package/dist/src/plugin-sdk/files-windows/result.js +67 -0
  95. package/dist/src/plugin-sdk/files.js +4 -0
  96. package/dist/src/plugin-sdk/index.d.ts +1 -0
  97. package/dist/src/plugin-sdk/index.js +1 -0
  98. package/dist/src/plugin-sdk/mutation-result.d.ts +7 -0
  99. package/dist/src/plugin-sdk/mutation-result.js +11 -0
  100. package/dist/src/runtime/adapters/long-term-memory/file-lock/acquisition.js +20 -3
  101. package/dist/src/runtime/adapters/long-term-memory/file-lock/owner-record.js +3 -1
  102. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.d.ts +3 -0
  103. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.js +20 -0
  104. package/dist/src/runtime/adapters/long-term-memory/file-lock/snapshot.js +7 -3
  105. package/dist/src/runtime/adapters/passive-learning-runtime.d.ts +1 -1
  106. package/dist/src/runtime/adapters/passive-learning-runtime.js +3 -3
  107. package/dist/src/runtime/adapters/runtime-observation-connection.d.ts +5 -0
  108. package/dist/src/runtime/adapters/runtime-observation-connection.js +13 -0
  109. package/dist/src/runtime/local-host/windows-private-access.js +2 -0
  110. package/dist/src/runtime/passive-learning/application-catalog.js +3 -1
  111. package/dist/src/runtime/passive-learning/collection-source.js +7 -0
  112. package/dist/src/runtime/passive-learning/service.js +2 -3
  113. package/dist/src/runtime/passive-learning/status-projection.d.ts +2 -0
  114. package/dist/src/runtime/passive-learning/status-projection.js +9 -0
  115. package/dist/src/runtime/plugins/installation/package.d.ts +8 -0
  116. package/dist/src/runtime/plugins/installation/package.js +2 -0
  117. package/dist/src/runtime/plugins/installation/service.d.ts +7 -0
  118. package/dist/src/runtime/plugins/loader.js +24 -14
  119. package/dist/src/runtime/plugins/manifest-platform-compatibility.d.ts +2 -0
  120. package/dist/src/runtime/plugins/manifest-platform-compatibility.js +39 -0
  121. package/dist/src/runtime/plugins/manifest-validator.js +9 -1
  122. package/dist/src/runtime/plugins/platform-compatibility.d.ts +4 -0
  123. package/dist/src/runtime/plugins/platform-compatibility.js +44 -0
  124. package/dist/src/runtime/request/approval-wait/activation-events.js +19 -7
  125. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.d.ts +20 -0
  126. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.js +118 -0
  127. package/dist/src/runtime/request/approval-wait/super-compaction-restore.js +2 -1
  128. package/dist/src/runtime/request/prepared-execution.js +3 -0
  129. package/dist/src/runtime/steps/execution-agent/capability-result-context.d.ts +6 -0
  130. package/dist/src/runtime/steps/execution-agent/capability-result-context.js +29 -0
  131. package/dist/src/runtime/steps/execution-agent/format.js +2 -3
  132. package/dist/src/runtime/steps/execution-agent/input.js +1 -1
  133. package/dist/src/runtime/steps/execution-agent/prompt.js +5 -5
  134. package/dist/src/runtime/steps/execution-agent/response-prompt.js +1 -0
  135. package/dist/src/runtime/steps/execution-agent/state-context.d.ts +2 -3
  136. package/dist/src/runtime/steps/execution-agent/state-context.js +26 -35
  137. package/dist/src/runtime/steps/execution-agent/work-plan-contract.d.ts +1 -3
  138. package/dist/src/runtime/steps/execution-agent/work-plan-contract.js +0 -55
  139. package/dist/src/runtime/steps/execution-agent/work-plan-schema.d.ts +3 -0
  140. package/dist/src/runtime/steps/execution-agent/work-plan-schema.js +61 -0
  141. package/dist/src/sessions/durable-session-commit.js +3 -3
  142. package/dist/src/sessions/prepared-session-replacement.d.ts +6 -0
  143. package/dist/src/sessions/prepared-session-replacement.js +46 -0
  144. package/dist/src/sessions/session-store.js +3 -3
  145. package/dist/src/shared/passive-observation-self-exclusion.d.ts +5 -0
  146. package/dist/src/shared/passive-observation-self-exclusion.js +37 -0
  147. package/dist/src/shared/windows-file-io/authority-script.d.ts +1 -0
  148. package/dist/src/shared/windows-file-io/authority-script.js +94 -0
  149. package/dist/src/shared/windows-file-io/native-script.d.ts +2 -0
  150. package/dist/src/shared/windows-file-io/native-script.js +120 -0
  151. package/dist/src/shared/windows-file-io/read-bytes-script.d.ts +1 -0
  152. package/dist/src/shared/windows-file-io/read-bytes-script.js +18 -0
  153. package/dist/src/shared/windows-job-object.d.ts +2 -0
  154. package/dist/src/shared/windows-job-object.js +66 -0
  155. package/dist/src/web-ui/app/app-bootstrap.js +14 -1
  156. package/dist/src/web-ui/app/app-state.js +0 -7
  157. package/dist/src/web-ui/app/app.js +53 -156
  158. package/dist/src/web-ui/app/components/automations/node-inspector.js +3 -2
  159. package/dist/src/web-ui/app/components/automations/step-editor-dialog.js +3 -0
  160. package/dist/src/web-ui/app/components/composer-submission-notice.js +50 -0
  161. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +7 -1
  162. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +22 -2
  163. package/dist/src/web-ui/app/components/home-guidance/daily-review.js +2 -2
  164. package/dist/src/web-ui/app/components/home-guidance/home-guidance.js +20 -6
  165. package/dist/src/web-ui/app/components/model-setup/context-window-feedback.js +53 -0
  166. package/dist/src/web-ui/app/components/model-setup/save-flow.js +3 -1
  167. package/dist/src/web-ui/app/components/model-setup/save-outcome.js +1 -0
  168. package/dist/src/web-ui/app/components/model-setup/wizard.js +12 -0
  169. package/dist/src/web-ui/app/components/passive-learning/activity-controls.js +4 -0
  170. package/dist/src/web-ui/app/components/passive-learning/collection-access.js +35 -0
  171. package/dist/src/web-ui/app/components/passive-learning/collection-consent-dialog.js +59 -0
  172. package/dist/src/web-ui/app/components/passive-learning/collection-consent-gate.js +94 -0
  173. package/dist/src/web-ui/app/components/passive-learning/computer-update-notice.js +6 -0
  174. package/dist/src/web-ui/app/components/passive-learning/failure-copy.js +1 -0
  175. package/dist/src/web-ui/app/components/passive-learning/home.js +7 -2
  176. package/dist/src/web-ui/app/components/passive-learning/macos-collection-restart-notice.js +1 -0
  177. package/dist/src/web-ui/app/components/passive-learning/memory.js +2 -4
  178. package/dist/src/web-ui/app/components/passive-learning/workspace-view.js +2 -2
  179. package/dist/src/web-ui/app/components/plugins/compatibility.js +13 -0
  180. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +9 -1
  181. package/dist/src/web-ui/app/components/plugins/installation-compatibility.js +7 -0
  182. package/dist/src/web-ui/app/components/plugins/installation.js +2 -1
  183. package/dist/src/web-ui/app/components/plugins/rendering.js +3 -0
  184. package/dist/src/web-ui/app/components/reasoning-override-prompt.js +82 -0
  185. package/dist/src/web-ui/app/components/runtime-config-activation.js +22 -8
  186. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +7 -4
  187. package/dist/src/web-ui/app/components/runtime-setup/plugins.js +3 -1
  188. package/dist/src/web-ui/app/components/runtime-setup/rendering.js +6 -4
  189. package/dist/src/web-ui/app/components/runtime-setup-guide.d.ts +1 -0
  190. package/dist/src/web-ui/app/components/schedules/form.js +10 -8
  191. package/dist/src/web-ui/app/components/schedules/workspace.js +23 -4
  192. package/dist/src/web-ui/app/components/session-sidebar-sections.js +2 -2
  193. package/dist/src/web-ui/app/components/spark-chat/handoff-actions.js +9 -3
  194. package/dist/src/web-ui/app/components/spark-chat/placement.js +4 -7
  195. package/dist/src/web-ui/app/components/spark-chat/settings.js +7 -3
  196. package/dist/src/web-ui/app/components/system-host/macos-permissions.js +2 -0
  197. package/dist/src/web-ui/app/components/system-host/native-windows-access.js +50 -0
  198. package/dist/src/web-ui/app/components/system-host/rendering.js +3 -0
  199. package/dist/src/web-ui/app/components/workspace-storage-notice.js +37 -0
  200. package/dist/src/web-ui/app/configuration-environment-refresh.js +27 -34
  201. package/dist/src/web-ui/app/configuration-feature.js +9 -1
  202. package/dist/src/web-ui/app/controllers/app-event-bindings.js +38 -105
  203. package/dist/src/web-ui/app/controllers/chat-request-controller.d.ts +28 -0
  204. package/dist/src/web-ui/app/controllers/chat-request-controller.js +34 -66
  205. package/dist/src/web-ui/app/controllers/composer-attachments-controller.d.ts +15 -40
  206. package/dist/src/web-ui/app/controllers/composer-attachments-controller.js +26 -69
  207. package/dist/src/web-ui/app/controllers/composer-draft-view.d.ts +27 -0
  208. package/dist/src/web-ui/app/controllers/composer-draft-view.js +48 -0
  209. package/dist/src/web-ui/app/controllers/composer-drafts.d.ts +55 -0
  210. package/dist/src/web-ui/app/controllers/composer-drafts.js +120 -0
  211. package/dist/src/web-ui/app/controllers/composer-feature.d.ts +65 -0
  212. package/dist/src/web-ui/app/controllers/composer-feature.js +124 -0
  213. package/dist/src/web-ui/app/controllers/composer-queue-controller.d.ts +33 -94
  214. package/dist/src/web-ui/app/controllers/composer-queue-controller.js +185 -251
  215. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.d.ts +48 -0
  216. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.js +97 -0
  217. package/dist/src/web-ui/app/controllers/composer-submit-controller.d.ts +30 -61
  218. package/dist/src/web-ui/app/controllers/composer-submit-controller.js +56 -138
  219. package/dist/src/web-ui/app/controllers/composer-surface-controller.js +6 -0
  220. package/dist/src/web-ui/app/controllers/composer-workspace-controller.d.ts +22 -40
  221. package/dist/src/web-ui/app/controllers/composer-workspace-controller.js +49 -165
  222. package/dist/src/web-ui/app/controllers/conversation-navigation-intent.js +15 -0
  223. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +20 -17
  224. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +1 -2
  225. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +49 -22
  226. package/dist/src/web-ui/app/controllers/conversation-workspace-activation.js +27 -0
  227. package/dist/src/web-ui/app/controllers/daily-memory-review.js +15 -16
  228. package/dist/src/web-ui/app/controllers/environment-transition.js +126 -0
  229. package/dist/src/web-ui/app/controllers/environment-workspace-preparation.js +18 -0
  230. package/dist/src/web-ui/app/controllers/home-composer-feature.d.ts +14 -36
  231. package/dist/src/web-ui/app/controllers/home-composer-feature.js +17 -114
  232. package/dist/src/web-ui/app/controllers/home-conversation-activation.js +6 -8
  233. package/dist/src/web-ui/app/controllers/passive-learning-controller.js +56 -0
  234. package/dist/src/web-ui/app/controllers/projects-controller.d.ts +1 -1
  235. package/dist/src/web-ui/app/controllers/projects-controller.js +6 -1
  236. package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +174 -0
  237. package/dist/src/web-ui/app/controllers/runtime-selection-controller.d.ts +7 -0
  238. package/dist/src/web-ui/app/controllers/runtime-selection-controller.js +20 -155
  239. package/dist/src/web-ui/app/controllers/session-controller.js +33 -17
  240. package/dist/src/web-ui/app/controllers/session-pin-updates.js +14 -0
  241. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +12 -14
  242. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +2 -2
  243. package/dist/src/web-ui/app/controllers/steer-controller.js +9 -7
  244. package/dist/src/web-ui/app/controllers/tool-permission-mode-controller.js +1 -1
  245. package/dist/src/web-ui/app/controllers/workspace-conversation-opener.js +34 -0
  246. package/dist/src/web-ui/app/dashboard-feature.js +3 -2
  247. package/dist/src/web-ui/app/lib/reasoning-controls.js +35 -0
  248. package/dist/src/web-ui/app/lib/session-composer-queue-ownership.js +58 -0
  249. package/dist/src/web-ui/app/lib/session-composer-queue.d.ts +12 -0
  250. package/dist/src/web-ui/app/lib/session-composer-queue.js +25 -6
  251. package/dist/src/web-ui/app/passive-learning-feature.js +16 -3
  252. package/dist/src/web-ui/app/schedules-feature.js +5 -3
  253. package/dist/src/web-ui/app/services/client-preferences.d.ts +18 -10
  254. package/dist/src/web-ui/app/services/client-preferences.js +25 -16
  255. package/dist/src/web-ui/app/services/home-guidance-preferences.js +13 -13
  256. package/dist/src/web-ui/app/services/reasoning-override.js +12 -0
  257. package/dist/src/web-ui/app/services/runtime-web-client/automations.js +10 -2
  258. package/dist/src/web-ui/app/services/runtime-web-client/memory.js +7 -2
  259. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  260. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +2 -0
  261. package/dist/src/web-ui/app/services/runtime-web-client.js +2 -0
  262. package/dist/src/web-ui/app/services/server-composer-queue.js +32 -0
  263. package/dist/src/web-ui/app/services/session-sidebar-preferences.js +5 -5
  264. package/dist/src/web-ui/app/services/workspace-state-storage.js +116 -0
  265. package/dist/src/web-ui/app/services/workspace-state.js +27 -0
  266. package/dist/src/web-ui/app/spark-chat-conversation.js +34 -45
  267. package/dist/src/web-ui/app/spark-chat-feature.js +10 -4
  268. package/dist/src/web-ui/app/styles/21-composer-controls.css +16 -0
  269. package/dist/src/web-ui/app/styles/41-plugin-management.css +8 -0
  270. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +1 -0
  271. package/dist/src/web-ui/app/styles/49-collection-consent.css +30 -0
  272. package/dist/src/web-ui/app/styles/64-workspace-storage.css +23 -0
  273. package/dist/src/web-ui/app/styles.css +2 -0
  274. package/dist/src/web-ui/client-state/contracts.d.ts +15 -0
  275. package/dist/src/web-ui/client-state/contracts.js +13 -0
  276. package/dist/src/web-ui/client-state/preference-shapes.d.ts +2 -0
  277. package/dist/src/web-ui/client-state/preference-shapes.js +80 -0
  278. package/dist/src/web-ui/client-state/preferences.d.ts +3 -0
  279. package/dist/src/web-ui/client-state/preferences.js +84 -0
  280. package/dist/src/web-ui/client-state/queue.d.ts +3 -0
  281. package/dist/src/web-ui/client-state/queue.js +43 -0
  282. package/dist/src/web-ui/client-state/routes.d.ts +7 -0
  283. package/dist/src/web-ui/client-state/routes.js +58 -0
  284. package/dist/src/web-ui/client-state/store.d.ts +14 -0
  285. package/dist/src/web-ui/client-state/store.js +88 -0
  286. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +2 -0
  287. package/dist/src/web-ui/local-runtime/http.js +11 -2
  288. package/dist/src/web-ui/local-runtime/model-context-capacity-error.d.ts +14 -0
  289. package/dist/src/web-ui/local-runtime/model-context-capacity-error.js +28 -0
  290. package/dist/src/web-ui/local-runtime/model-setup-context-window.d.ts +15 -0
  291. package/dist/src/web-ui/local-runtime/model-setup-context-window.js +25 -0
  292. package/dist/src/web-ui/local-runtime/model-setup-routes.js +2 -0
  293. package/dist/src/web-ui/local-runtime/model-setup-service.js +5 -2
  294. package/dist/src/web-ui/local-runtime/model-setup-validation.d.ts +1 -0
  295. package/dist/src/web-ui/local-runtime/model-setup-validation.js +14 -7
  296. package/dist/src/web-ui/local-runtime/request-body-error.d.ts +11 -0
  297. package/dist/src/web-ui/local-runtime/request-body-error.js +14 -0
  298. package/dist/src/web-ui/local-runtime/request-control-observation.js +2 -2
  299. package/dist/src/web-ui/local-runtime/request-execution.js +18 -18
  300. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.d.ts +2 -0
  301. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.js +35 -22
  302. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +2 -9
  303. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +4 -27
  304. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.d.ts +15 -1
  305. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.js +30 -11
  306. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.d.ts +20 -0
  307. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.js +104 -0
  308. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.d.ts +29 -0
  309. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.js +151 -0
  310. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.d.ts +7 -0
  311. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.js +87 -0
  312. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.d.ts +3 -0
  313. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.js +37 -0
  314. package/dist/src/web-ui/local-runtime/runtime-setup-service.js +4 -0
  315. package/dist/src/web-ui/local-runtime-backend.js +14 -0
  316. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  317. package/dist/src/web-ui/plugin-management-catalog.js +3 -1
  318. package/dist/src/web-ui/plugin-management-service.d.ts +1 -0
  319. package/dist/src/web-ui/plugin-removal-service.d.ts +1 -0
  320. package/dist/src/web-ui/server-readiness.d.ts +3 -0
  321. package/dist/src/web-ui/server-readiness.js +36 -0
  322. package/dist/src/web-ui/server.d.ts +2 -0
  323. package/dist/src/web-ui/server.js +23 -1
  324. package/dist/src/web-ui/system-host-service.js +13 -2
  325. package/dist/src/web-ui/system-host-setup/collection-consent-route.d.ts +3 -0
  326. package/dist/src/web-ui/system-host-setup/collection-consent-route.js +30 -0
  327. package/docs/installation.md +44 -5
  328. package/docs/plugins.md +145 -4
  329. package/docs/tool-execution-result-evidence-contract.md +57 -0
  330. package/docs/windows-companion-store.md +5 -0
  331. package/package.json +4 -2
  332. package/plugins/capability-brief/plugin.json +4 -0
  333. package/plugins/code-outline/README.md +20 -0
  334. package/plugins/code-outline/plugin.json +1 -0
  335. package/plugins/code-outline/source/index.ts +16 -20
  336. package/plugins/code-outline/source/read-failure.ts +40 -0
  337. package/plugins/code-outline/src/index.cjs +614 -29
  338. package/plugins/document-reader/README.md +33 -0
  339. package/plugins/document-reader/plugin.json +1 -0
  340. package/plugins/document-reader/source/pdf-contract.ts +57 -0
  341. package/plugins/document-reader/source/pdf-parser.ts +139 -0
  342. package/plugins/document-reader/source/pdf-process-main.ts +56 -0
  343. package/plugins/document-reader/source/pdf-process.ts +207 -0
  344. package/plugins/document-reader/source/pdf-result.ts +79 -0
  345. package/plugins/document-reader/source/pdf-worker.ts +39 -303
  346. package/plugins/document-reader/source/pdf.ts +4 -1
  347. package/plugins/document-reader/source/read-failure.ts +37 -0
  348. package/plugins/document-reader/source/reader.ts +3 -19
  349. package/plugins/document-reader/src/index.cjs +995 -211
  350. package/plugins/exec/README.md +19 -0
  351. package/plugins/exec/plugin.json +4 -3
  352. package/plugins/exec/skills/exec_skill/SKILL.md +3 -2
  353. package/plugins/exec/source/filesystem-file-observer.ts +98 -0
  354. package/plugins/exec/source/filesystem-observer.ts +8 -79
  355. package/plugins/exec/source/output-files.ts +12 -6
  356. package/plugins/exec/source/paths.ts +3 -1
  357. package/plugins/exec/source/process-manager.ts +8 -24
  358. package/plugins/exec/source/shell-platform.ts +19 -3
  359. package/plugins/exec/source/shell-process.ts +55 -0
  360. package/plugins/exec/source/windows-job-source.ts +1 -0
  361. package/plugins/exec/source/windows-shell-bootstrap.ts +20 -0
  362. package/plugins/exec/src/index.cjs +252 -96
  363. package/plugins/filesystem/README.md +65 -0
  364. package/plugins/filesystem/plugin.json +6 -2
  365. package/plugins/filesystem/source/atomic-write.ts +2 -0
  366. package/plugins/filesystem/source/bounded-io.ts +80 -306
  367. package/plugins/filesystem/source/directory-sample.ts +2 -0
  368. package/plugins/filesystem/source/errors.ts +14 -0
  369. package/plugins/filesystem/source/file-observation.ts +151 -0
  370. package/plugins/filesystem/source/file-version.ts +41 -0
  371. package/plugins/filesystem/source/index.ts +6 -0
  372. package/plugins/filesystem/source/mutation-coordinator.ts +1 -0
  373. package/plugins/filesystem/source/windows/authority-script.ts +1 -0
  374. package/plugins/filesystem/source/windows/native-script.ts +1 -0
  375. package/plugins/filesystem/source/windows/operations.ts +197 -0
  376. package/plugins/filesystem/source/windows/process.ts +214 -0
  377. package/plugins/filesystem/source/windows/publication-script.ts +29 -0
  378. package/plugins/filesystem/source/windows/read-script.ts +63 -0
  379. package/plugins/filesystem/source/windows/request-availability.ts +67 -0
  380. package/plugins/filesystem/source/windows/source.ts +42 -0
  381. package/plugins/filesystem/source/windows/storage-script.ts +11 -0
  382. package/plugins/filesystem/source/windows/streams-script.ts +24 -0
  383. package/plugins/filesystem/source/windows/write-script.ts +86 -0
  384. package/plugins/filesystem/src/index.cjs +1208 -322
  385. package/plugins/json-inspector/README.md +18 -0
  386. package/plugins/json-inspector/plugin.json +1 -0
  387. package/plugins/json-inspector/source/index.ts +16 -19
  388. package/plugins/json-inspector/source/read-failure.ts +42 -0
  389. package/plugins/json-inspector/src/index.cjs +612 -27
  390. package/plugins/local-search/README.md +29 -0
  391. package/plugins/local-search/plugin.json +1 -0
  392. package/plugins/local-search/source/errors.ts +2 -0
  393. package/plugins/local-search/source/paths.ts +3 -0
  394. package/plugins/local-search/source/ripgrep-process.ts +31 -5
  395. package/plugins/local-search/source/ripgrep.ts +3 -3
  396. package/plugins/local-search/source/windows-authority.ts +99 -0
  397. package/plugins/local-search/source/windows-search-lease.ts +49 -0
  398. package/plugins/local-search/source/windows-search-process.ts +91 -0
  399. package/plugins/local-search/source/windows-search-script.ts +52 -0
  400. package/plugins/local-search/src/index.cjs +595 -26
  401. package/plugins/memory/plugin.json +4 -0
  402. package/plugins/memory/source/lock-directory-claim.ts +56 -0
  403. package/plugins/memory/source/lock-owner-file.ts +71 -0
  404. package/plugins/memory/source/lock-path-observation.ts +26 -0
  405. package/plugins/memory/source/prepared-memory-replacement.ts +40 -0
  406. package/plugins/memory/source/store-lock.ts +12 -7
  407. package/plugins/memory/source/store.ts +3 -2
  408. package/plugins/memory/src/index.cjs +174 -25
  409. package/plugins/project-orientation/README.md +23 -0
  410. package/plugins/project-orientation/plugin.json +1 -0
  411. package/plugins/project-orientation/source/index.ts +12 -9
  412. package/plugins/project-orientation/source/inspection-failure.ts +70 -0
  413. package/plugins/project-orientation/source/manifest-summary.ts +9 -2
  414. package/plugins/project-orientation/source/tree.ts +6 -0
  415. package/plugins/project-orientation/src/index.cjs +647 -31
  416. package/plugins/system/README.md +51 -15
  417. package/plugins/system/plugin.json +5 -1
  418. package/plugins/system/skills/system_actions/SKILL.md +1 -1
  419. package/plugins/system/source/command-working-directory.ts +47 -0
  420. package/plugins/system/source/computer/handlers.ts +13 -9
  421. package/plugins/system/source/computer/observation-result.ts +10 -5
  422. package/plugins/system/source/computer/request-computers.ts +10 -3
  423. package/plugins/system/source/computer/request-modules.ts +3 -6
  424. package/plugins/system/source/computer/runtime-platform.ts +18 -0
  425. package/plugins/system/source/host-dispatch.ts +18 -2
  426. package/plugins/system/source/index.ts +5 -3
  427. package/plugins/system/source/local-command-output-retention.ts +16 -0
  428. package/plugins/system/source/local-command-output.ts +16 -8
  429. package/plugins/system/source/request-system-modules.ts +12 -2
  430. package/plugins/system/source/request-target-snapshot.ts +2 -1
  431. package/plugins/system/source/security/desktop-result.ts +177 -0
  432. package/plugins/system/source/security/observed-error.ts +10 -0
  433. package/plugins/system/source/security/secret-text.ts +118 -0
  434. package/plugins/system/source/security/system-results.ts +62 -0
  435. package/plugins/system/source/security/windows-output-directory.ts +82 -0
  436. package/plugins/system/src/index.cjs +837 -151
  437. package/plugins/system-probe/plugin.json +8 -2
  438. package/plugins/system-probe/source/disk-path.ts +8 -0
  439. package/plugins/system-probe/source/index.ts +10 -5
  440. package/plugins/system-probe/source/machine-load.ts +33 -0
  441. package/plugins/system-probe/source/metrics.ts +6 -8
  442. package/plugins/system-probe/src/index.cjs +49 -16
  443. package/plugins/web/plugin.json +4 -0
@@ -0,0 +1,15 @@
1
+ /** Session opens and New conversation share the latest navigation intent. */
2
+ export function beginConversationNavigation(state) {
3
+ const revision = (state.conversationNavigationRevision ?? 0) + 1;
4
+ state.conversationNavigationRevision = revision;
5
+ return () => state.conversationNavigationRevision === revision;
6
+ }
7
+
8
+ /** The selector may name a target whose recovered drafts are not saved yet. */
9
+ export function canNavigateConversation(state) {
10
+ return hasCommittedConversationEnvironment(state);
11
+ }
12
+
13
+ export function hasCommittedConversationEnvironment(state) {
14
+ return state.environmentChangePending !== true;
15
+ }
@@ -15,6 +15,15 @@ function isQueuedTerminalRequest(request, queued) {
15
15
  if (textOf(request.requestId) !== queued?.waitForRequestId) return false;
16
16
  return request.status === "completed" || request.status === "failed";
17
17
  }
18
+ function mergeRefreshedRequests(previous, fresh) {
19
+ // A latest-page fetch includes every active request. Keep metadata for the
20
+ // displayed historical page, but never revive an older active projection.
21
+ const requests = new Map(previous
22
+ .filter((request) => !isStreamingRequest(request) && request.status !== "awaiting_approval")
23
+ .map((request) => [request.requestId, request]));
24
+ for (const request of fresh) requests.set(request.requestId, request);
25
+ return [...requests.values()];
26
+ }
18
27
  function requestsForEventRestoration(requests, streamingRequestIds, appendEvents) {
19
28
  if (!appendEvents) return requests;
20
29
  // Existing live rows already contain received tokens. Resume their events only after lastSeq.
@@ -35,6 +44,14 @@ export function createConversationRequestHydration({
35
44
  async function restore(requests, { appendEvents = false } = {}) {
36
45
  const scope = { environmentId: selectedEnvironmentId(), sessionId: state.currentSessionId };
37
46
  const viewVersion = state.sessionViewVersion;
47
+ await sessionQueue.refresh?.();
48
+ if (!isCurrentHydration(scope, viewVersion)) return false;
49
+ const waitingRequestId = sessionQueue.peek(scope)?.waitForRequestId;
50
+ if (!canRestoreSnapshotQueue({ requests }, waitingRequestId)) {
51
+ const snapshot = await client.loadSession(scope.sessionId, scope.environmentId, { waitingRequestId });
52
+ if (!isCurrentHydration(scope, viewVersion)) return false;
53
+ requests = mergeRefreshedRequests(requests, snapshot.requests || []);
54
+ }
38
55
  for (const message of state.messages) {
39
56
  if (!isBindableResponse(message)) continue;
40
57
  state.requestMessages.set(message.requestId, message.id);
@@ -45,13 +62,6 @@ export function createConversationRequestHydration({
45
62
  const streamingRequestIds = new Set(requests
46
63
  .filter(isStreamingRequest)
47
64
  .map((request) => textOf(request.requestId)));
48
- if (streamingRequestIds.size === 1) {
49
- const [streamingRequestId] = streamingRequestIds;
50
- try { sessionQueue.rebindBlocked(scope, streamingRequestId); }
51
- catch (error) {
52
- reportQueueFailure(scope, `The active request was restored, but the remaining Send next queue is paused: ${error instanceof Error ? error.message : String(error)}`);
53
- }
54
- }
55
65
  state.activeRequestId = [...streamingRequestIds][0] || "";
56
66
  updateComposerSendState();
57
67
  for (const requestId of streamingRequestIds) activeAssistantForRequest(requestId);
@@ -64,7 +74,8 @@ export function createConversationRequestHydration({
64
74
  resumeRequest(requestId);
65
75
  }
66
76
  if (state.activeRequestId) { renderMessages(); return true; }
67
- recoverBlockedQueue(scope);
77
+ await recoverBlockedQueue(scope);
78
+ if (!isCurrentHydration(scope, viewVersion)) return false;
68
79
  const queued = sessionQueue.peek(scope);
69
80
  const terminal = requests.find((request) => isQueuedTerminalRequest(request, queued));
70
81
  if (terminal) await drainQueuedMessage({ ...scope, terminalRequestId: terminal.requestId, cancelled: isStoppedRequest(terminal) });
@@ -73,15 +84,7 @@ export function createConversationRequestHydration({
73
84
  return true;
74
85
  }
75
86
  async function rehydrate(requests) {
76
- const scope = { environmentId: selectedEnvironmentId(), sessionId: state.currentSessionId };
77
- const viewVersion = state.sessionViewVersion;
78
- const waitingRequestId = sessionQueue.peek(scope)?.waitForRequestId;
79
- if (!canRestoreSnapshotQueue({ requests }, waitingRequestId)) {
80
- const snapshot = await client.loadSession(scope.sessionId, scope.environmentId, { waitingRequestId });
81
- if (!isCurrentHydration(scope, viewVersion)) return false;
82
- requests = snapshot.requests || [];
83
- }
84
- subscribeSession(scope.sessionId);
87
+ subscribeSession(state.currentSessionId);
85
88
  return restore(requests, { appendEvents: true });
86
89
  }
87
90
  return { restore, rehydrate };
@@ -86,7 +86,6 @@ export interface ConversationSessionControllerOptions {
86
86
  };
87
87
  conversationView: { reset(): void };
88
88
  selectedEnvironmentId(): string;
89
- clearPendingAttachments(): void;
90
89
  applyConversationChrome(): void;
91
90
  applyModelSelection(): void;
92
91
  renderSessions(): void;
@@ -137,7 +136,7 @@ export declare function createConversationSessionController(
137
136
  text: string;
138
137
  attachments: unknown[];
139
138
  requestId?: string;
140
- }): void;
139
+ }): () => void;
141
140
  appendRequestError(error: unknown): void;
142
141
  applySessionReadState(sessionId: string, readState: unknown): void;
143
142
  applySessionTitleUpdate(sessionId: string, title: unknown): void;
@@ -1,3 +1,4 @@
1
+ import { beginConversationNavigation, canNavigateConversation } from "./conversation-navigation-intent.js";
1
2
  import {
2
3
  captureContextReplayScope,
3
4
  bindContextReplayEvents,
@@ -58,7 +59,6 @@ export function createConversationSessionController({
58
59
  sessionQueue,
59
60
  conversationView,
60
61
  selectedEnvironmentId,
61
- clearPendingAttachments,
62
62
  applyConversationChrome,
63
63
  applyModelSelection,
64
64
  renderSessions,
@@ -95,6 +95,7 @@ export function createConversationSessionController({
95
95
  listPagination.invalidate();
96
96
  history.reset();
97
97
  sessionRestoreRevision += 1;
98
+ beginConversationNavigation(state);
98
99
  state.sessions = [];
99
100
  onSessionListState({ status: "loading", sessions: [] });
100
101
  renderSessions();
@@ -166,7 +167,6 @@ export function createConversationSessionController({
166
167
  state.taskProgressByRequest.clear();
167
168
  state.contextWindowByRequest.clear();
168
169
  state.activeRequestId = "";
169
- state.composerSending = false;
170
170
  conversationView.reset();
171
171
  state.submittedToolApprovalIds.clear();
172
172
  state.requestMessages.clear();
@@ -178,9 +178,10 @@ export function createConversationSessionController({
178
178
  }
179
179
 
180
180
  function clearCurrentSessionView() {
181
+ sessionRestoreRevision += 1;
182
+ beginConversationNavigation(state);
181
183
  state.currentSessionId = "";
182
184
  state.messages = [];
183
- clearPendingAttachments();
184
185
  resetLiveRequestView();
185
186
  dom.sessionTitle.textContent = "New conversation";
186
187
  applyConversationChrome();
@@ -189,7 +190,6 @@ export function createConversationSessionController({
189
190
 
190
191
  function clearSessionMessagesView() {
191
192
  state.messages = [];
192
- clearPendingAttachments();
193
193
  resetLiveRequestView();
194
194
  applyConversationChrome();
195
195
  renderMessages();
@@ -411,34 +411,52 @@ export function createConversationSessionController({
411
411
  sessionId,
412
412
  { isRouteCurrent, commitRouteNavigation, snapshot, page, preserveCurrentWindow = false } = {},
413
413
  ) {
414
+ if (!canNavigateConversation(state)) {
415
+ setMessageStatus("Wait for the environment change to finish before opening a conversation.");
416
+ return false;
417
+ }
418
+ sessionRestoreRevision += 1;
419
+ const isCurrentOpen = beginConversationNavigation(state);
414
420
  const routeOwned = typeof commitRouteNavigation === "function";
415
421
  const loadBeforeReset = routeOwned || preserveCurrentWindow;
416
422
  let payload;
417
423
  const pageOptions = { ...page, waitingRequestId: sessionQueue.peek({ environmentId: selectedEnvironmentId(), sessionId })?.waitForRequestId };
418
- const prefetched = canRestoreSnapshotQueue(snapshot, pageOptions.waitingRequestId) ? snapshot : undefined;
424
+ let prefetched = canRestoreSnapshotQueue(snapshot, pageOptions.waitingRequestId) ? snapshot : undefined;
419
425
  if (loadBeforeReset) {
420
426
  const environmentId = selectedEnvironmentId();
421
427
  const viewVersion = state.sessionViewVersion;
422
428
  const currentSessionId = state.currentSessionId;
423
429
  payload = prefetched ?? await client.loadSession(sessionId, environmentId, pageOptions);
424
- if (environmentId !== selectedEnvironmentId()) return;
425
- if (viewVersion !== state.sessionViewVersion) return;
426
- if (currentSessionId !== state.currentSessionId) return;
427
- if (routeOwned && isRouteCurrent?.() !== true) return;
430
+ if (!isCurrentOpen()) return false;
431
+ if (environmentId !== selectedEnvironmentId()) return false;
432
+ if (viewVersion !== state.sessionViewVersion) return false;
433
+ if (currentSessionId !== state.currentSessionId) return false;
434
+ if (routeOwned && isRouteCurrent?.() !== true) return false;
428
435
  }
429
- if (
430
- state.currentSessionId &&
431
- state.currentSessionId !== sessionId &&
432
- !suspendQueueRecovery()
433
- ) {
434
- return;
436
+ if (state.currentSessionId) {
437
+ const previousSessionId = state.currentSessionId;
438
+ const environmentId = selectedEnvironmentId();
439
+ const canSuspendRecovery = () => {
440
+ if (!canNavigateConversation(state)) return false;
441
+ if (!isCurrentOpen()) return false;
442
+ if (selectedEnvironmentId() !== environmentId) return false;
443
+ if (state.currentSessionId !== previousSessionId) return false;
444
+ if (routeOwned && isRouteCurrent?.() !== true) return false;
445
+ return true;
446
+ };
447
+ let prepared = suspendQueueRecovery(canSuspendRecovery);
448
+ if (typeof prepared?.then === "function") {
449
+ prepared = await prepared;
450
+ payload = undefined;
451
+ prefetched = undefined;
452
+ }
453
+ if (!prepared || !canSuspendRecovery()) return false;
435
454
  }
436
- if (routeOwned && commitRouteNavigation() !== true) return;
455
+ if (routeOwned && commitRouteNavigation() !== true) return false;
437
456
  const viewVersion = state.sessionViewVersion + 1;
438
457
  state.currentSessionId = sessionId;
439
458
  preferences.saveSessionIdForEnvironment(selectedEnvironmentId(), sessionId);
440
459
  state.messages = [];
441
- clearPendingAttachments();
442
460
  resetLiveRequestView();
443
461
  state.sessionViewVersion = viewVersion;
444
462
  sessions.setCurrentTitle(
@@ -450,14 +468,15 @@ export function createConversationSessionController({
450
468
  renderMessages();
451
469
  subscribeSession(sessionId);
452
470
 
453
- if (!loadBeforeReset) {
471
+ if (!payload) {
454
472
  payload = prefetched ?? await client.loadSession(sessionId, selectedEnvironmentId(), pageOptions);
455
473
  }
456
474
  if (
475
+ !isCurrentOpen() ||
457
476
  state.currentSessionId !== sessionId ||
458
477
  state.sessionViewVersion !== viewVersion
459
478
  ) {
460
- return;
479
+ return false;
461
480
  }
462
481
  history.adopt(payload);
463
482
  const rawMessages = Array.isArray(payload.messages) ? payload.messages : [];
@@ -468,8 +487,9 @@ export function createConversationSessionController({
468
487
  sessions.applyTitle(sessionId, payload.title);
469
488
  sessions.applyReadState(sessionId, payload.readState);
470
489
  const requests = Array.isArray(payload.requests) ? payload.requests : [];
471
- if (!await requestHydration.restore(requests)) return;
490
+ if (!await requestHydration.restore(requests)) return false;
472
491
  markDisplayedMessagesReadSoon(displayedPage);
492
+ return true;
473
493
  }
474
494
 
475
495
  function ensureSession() {
@@ -486,7 +506,7 @@ export function createConversationSessionController({
486
506
  }
487
507
 
488
508
  function appendLocalUserMessage({ text, attachments, requestId = "" }) {
489
- state.messages.push({
509
+ const message = {
490
510
  id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
491
511
  role: "user",
492
512
  text,
@@ -494,8 +514,15 @@ export function createConversationSessionController({
494
514
  requestId,
495
515
  streaming: false,
496
516
  attachments,
497
- });
517
+ };
518
+ state.messages.push(message);
498
519
  renderMessages();
520
+ return () => {
521
+ const index = state.messages.indexOf(message);
522
+ if (index < 0) return;
523
+ state.messages.splice(index, 1);
524
+ renderMessages();
525
+ };
499
526
  }
500
527
 
501
528
  function insertSteerMessage({ steerId, requestId, text }) {
@@ -0,0 +1,27 @@
1
+ import { canNavigateConversation } from "./conversation-navigation-intent.js";
2
+
3
+ /** Navigation commits only after the recovered draft is saved for the same view. */
4
+ export function createConversationWorkspaceActivation({ state, shell, composerQueue, selectedEnvironmentId }) {
5
+ return async () => {
6
+ if (!canNavigateConversation(state)) {
7
+ shell.showToast?.("Wait for the environment change to finish before opening a conversation.", "neutral");
8
+ return false;
9
+ }
10
+ const environment = selectedEnvironmentId();
11
+ const session = state.currentSessionId;
12
+ const version = state.sessionViewVersion;
13
+ const navigationRevision = shell.navigationRevision?.();
14
+ const recovery = await composerQueue.prepareRecoveryForNavigation();
15
+ if (!recovery || recovery.canCommit?.() === false) return false;
16
+ if (!canNavigateConversation(state)) return false;
17
+ const hasCurrentWorkspaceNavigation = navigationRevision === shell.navigationRevision?.();
18
+ if (!hasCurrentWorkspaceNavigation) return false;
19
+ if (environment !== selectedEnvironmentId()) return false;
20
+ if (session !== state.currentSessionId) return false;
21
+ if (version !== state.sessionViewVersion) return false;
22
+ const activate = shell.prepareWorkspaceActivation("chat", { focus: false });
23
+ if (!activate) return false;
24
+ recovery();
25
+ return activate() !== false;
26
+ };
27
+ }
@@ -94,11 +94,11 @@ export function createDailyMemoryReview({ client, getEnvironmentId, preferences,
94
94
  return request;
95
95
  }
96
96
 
97
- function markOffered() {
97
+ async function markOffered() {
98
98
  if (!items.length || environment !== getEnvironmentId()) return false;
99
99
  const day = localReviewDay(now());
100
100
  if (preferences.wasOffered(environment, day)) return false;
101
- preferences.markOffered(environment, day);
101
+ await preferences.markOffered(environment, day);
102
102
  return true;
103
103
  }
104
104
 
@@ -109,25 +109,24 @@ export function createDailyMemoryReview({ client, getEnvironmentId, preferences,
109
109
  const target = environment;
110
110
  const operation = revision;
111
111
  error = "";
112
- if (action === "delete") {
113
- busy = true;
114
- publish();
115
- try {
112
+ busy = true;
113
+ publish();
114
+ try {
115
+ if (action === "delete") {
116
116
  const result = await client.deleteLongTermMemory({ environmentId: target, id: record.id });
117
117
  if (!isCurrent(operation, target)) return false;
118
118
  if (result?.deleted !== true) throw new Error("Delete not confirmed");
119
- } catch {
120
- if (isCurrent(operation, target)) error = "This memory could not be deleted. Try again, or keep it for now.";
121
- return false;
122
- } finally {
123
- if (isCurrent(operation, target)) { busy = false; publish(); }
124
119
  }
120
+ if (action === "keep") await preferences.markReviewed(target, record);
121
+ if (!isCurrent(operation, target)) return false;
122
+ index += 1;
123
+ return true;
124
+ } catch {
125
+ if (isCurrent(operation, target)) error = "Your review could not be completed. Reload before continuing.";
126
+ return false;
127
+ } finally {
128
+ if (isCurrent(operation, target)) { busy = false; publish(); }
125
129
  }
126
- if (!isCurrent(operation, target)) return false;
127
- preferences.markReviewed(target, record);
128
- index += 1;
129
- publish();
130
- return true;
131
130
  }
132
131
 
133
132
  return {
@@ -0,0 +1,126 @@
1
+ /** Owns the active window environment. Its saved default is an independent preference. */
2
+ export function createEnvironmentTransition({ state, dom, actions, prepareQueueRecovery, onNavigationChange, onFailure = () => {} }) {
3
+ let revision = 0;
4
+ let changing = false;
5
+ let notifying = false;
6
+ let prepareAdditional = () => true;
7
+ let refreshAdditional = () => {};
8
+ function refreshSubmissionState() {
9
+ actions.refreshComposerSubmissionState?.();
10
+ refreshAdditional();
11
+ }
12
+ let committedEnvironment = dom.environmentSelect.value;
13
+
14
+ function notifySubscribers() {
15
+ const ChangeEvent = dom.environmentSelect.ownerDocument?.defaultView?.Event ?? Event;
16
+ notifying = true;
17
+ try { dom.environmentSelect.dispatchEvent(new ChangeEvent("change")); }
18
+ finally { notifying = false; }
19
+ }
20
+
21
+ function hasCurrentEnvironmentSelection(operation, target) {
22
+ if (operation !== revision) return false;
23
+ return dom.environmentSelect.value === target;
24
+ }
25
+
26
+ async function changeEnvironment(target, { restoreSession = true, notifyEnvironmentChange = true, commitEnvironmentOptions } = {}) {
27
+ const operation = ++revision;
28
+ const previous = committedEnvironment;
29
+ let committed = false;
30
+ const restoreSelection = () => {
31
+ dom.environmentSelect.value = previous;
32
+ state.agentPickerOpen = false;
33
+ actions.renderAgentPicker();
34
+ };
35
+ changing = true;
36
+ state.environmentChangePending = true;
37
+ try {
38
+ // Consumers read the selector, so expose only the committed environment.
39
+ dom.environmentSelect.value = previous;
40
+ refreshSubmissionState();
41
+ if (target === previous) { restoreSelection(); return true; }
42
+ let preparedAdditional = prepareAdditional();
43
+ if (isPendingPreparation(preparedAdditional)) {
44
+ preparedAdditional = await preparedAdditional;
45
+ }
46
+ if (!hasCurrentEnvironmentSelection(operation, previous)) return false;
47
+ if (environmentChangeWasDeclined(preparedAdditional)) { restoreSelection(); return false; }
48
+ let preparedQueue = prepareQueueRecovery();
49
+ if (isPendingPreparation(preparedQueue)) {
50
+ preparedQueue = await preparedQueue;
51
+ }
52
+ if (!hasCurrentEnvironmentSelection(operation, previous)) return false;
53
+ if (environmentChangeWasDeclined(preparedQueue)) { restoreSelection(); return false; }
54
+ if (!canCommitEnvironmentPreparations([preparedAdditional, preparedQueue, commitEnvironmentOptions])) { restoreSelection(); return false; }
55
+ const preparedConfig = actions.beforeEnvironmentChange
56
+ ? actions.beforeEnvironmentChange({ from: previous, to: target }) : true;
57
+ if (environmentChangeWasDeclined(preparedConfig)) { restoreSelection(); return false; }
58
+ if (!hasCurrentEnvironmentSelection(operation, previous)) return false;
59
+ if (!canCommitEnvironmentPreparations([preparedAdditional, preparedQueue, preparedConfig, commitEnvironmentOptions])) { restoreSelection(); return false; }
60
+ if (typeof preparedAdditional === "function") preparedAdditional();
61
+ if (typeof preparedQueue === "function") preparedQueue();
62
+ if (typeof preparedConfig === "function") preparedConfig();
63
+ commitEnvironmentOptions?.();
64
+ actions.invalidateSessionLoads?.();
65
+ committedEnvironment = target;
66
+ dom.environmentSelect.value = target;
67
+ committed = true;
68
+ state.agentPickerOpen = false;
69
+ actions.renderAgentPicker();
70
+ state.environmentChangePending = false;
71
+ state.currentSessionId = "";
72
+ state.messages = [];
73
+ actions.resetLiveRequestView();
74
+ dom.sessionTitle.textContent = "New conversation";
75
+ actions.applyConversationChrome();
76
+ actions.renderMessages();
77
+ // Persistence errors are visible but never roll back an already committed route.
78
+ try { void Promise.resolve(actions.saveEnvironmentId(target)).catch(onFailure); }
79
+ catch (error) { onFailure(error); }
80
+ const loading = Promise.allSettled([
81
+ actions.loadModels(), actions.loadAgentMode(),
82
+ actions.loadRuntimeConfig({ protectUnsaved: false, clearBeforeLoad: true }),
83
+ ]);
84
+ if (notifyEnvironmentChange) notifySubscribers();
85
+ await loading;
86
+ if (!hasCurrentEnvironmentSelection(operation, target)) return false;
87
+ if (restoreSession) await actions.restoreLastSession();
88
+ return hasCurrentEnvironmentSelection(operation, target);
89
+ } catch (error) {
90
+ const currentEnvironment = committed ? target : previous;
91
+ if (!hasCurrentEnvironmentSelection(operation, currentEnvironment)) return false;
92
+ if (!committed) restoreSelection();
93
+ onFailure(error);
94
+ return committed;
95
+ } finally {
96
+ if (operation === revision) {
97
+ changing = false;
98
+ state.environmentChangePending = false;
99
+ refreshSubmissionState();
100
+ onNavigationChange();
101
+ }
102
+ }
103
+ }
104
+
105
+ function onSelectChange(event) {
106
+ if (notifying) return;
107
+ const target = dom.environmentSelect.value;
108
+ // The transition emits one event when the environment actually commits.
109
+ event.stopImmediatePropagation();
110
+ void changeEnvironment(target);
111
+ }
112
+
113
+ return {
114
+ changeEnvironment, onSelectChange,
115
+ initializeEnvironment: () => { committedEnvironment = dom.environmentSelect.value; },
116
+ setEnvironmentChangePreparation: (prepare, refresh = () => {}) => { prepareAdditional = prepare; refreshAdditional = refresh; },
117
+ isEnvironmentChanging: () => changing,
118
+ };
119
+ }
120
+
121
+ function isPendingPreparation(value) { return typeof value?.then === "function"; }
122
+ export function environmentChangeWasDeclined(value) { return value === false || value === null; }
123
+
124
+ function canCommitEnvironmentPreparations(preparations) {
125
+ return preparations.every((prepared) => prepared?.canCommit?.() !== false);
126
+ }
@@ -0,0 +1,18 @@
1
+ import { environmentChangeWasDeclined } from "./environment-transition.js";
2
+
3
+ /** Discard configuration and schedule drafts only after both preparations remain current. */
4
+ export function prepareEnvironmentWorkspaceChanges(schedules, configuration) {
5
+ const schedule = schedules.prepareEnvironmentChange();
6
+ if (environmentChangeWasDeclined(schedule)) return null;
7
+ const config = configuration.prepareDiscardChanges("change environment");
8
+ if (environmentChangeWasDeclined(config)) return null;
9
+ const commit = () => {
10
+ if (typeof schedule === "function") schedule();
11
+ if (typeof config === "function") config();
12
+ };
13
+ commit.canCommit = () => {
14
+ if (schedule?.canCommit?.() === false) return false;
15
+ return config?.canCommit?.() !== false;
16
+ };
17
+ return commit;
18
+ }
@@ -1,40 +1,18 @@
1
- import type {
2
- ComposerAttachmentsClient,
3
- ComposerAttachmentControlEvent,
4
- ComposerAttachmentsController,
5
- ComposerAttachmentsShell,
6
- ComposerUploadFile,
7
- } from "./composer-attachments-controller.js";
8
- import type {
9
- ComposerSubmissionBlock,
10
- ComposerSubmitActions,
11
- ComposerSubmitController,
12
- } from "./composer-submit-controller.js";
13
- import type {
14
- ComposerWorkspaceController,
15
- HomeComposerDraft,
16
- } from "./composer-workspace-controller.js";
1
+ import type { ComposerFeature, ComposerSurface, ComposerSurfaceDom } from "./composer-feature.js";
2
+ import type { ComposerWorkspaceController, ComposerWorkspaceDom } from "./composer-workspace-controller.js";
3
+ import type { ComposerUploadFile } from "./composer-attachments-controller.js";
4
+ import type { ComposerScope } from "./composer-drafts.js";
5
+ import type { ComposerSubmitController } from "./composer-submit-controller.js";
17
6
 
18
- export declare function createHomeComposerFeature(options: {
19
- workspace: ComposerWorkspaceController;
20
- shell: ComposerAttachmentsShell;
21
- client: ComposerAttachmentsClient;
22
- composerActions: ComposerSubmitActions;
23
- selectedEnvironmentId(): string;
24
- selectedModelSupportsImageInput(): boolean;
25
- isComposerAvailable?(): boolean;
26
- getSubmissionBlock?(): ComposerSubmissionBlock | null;
27
- onSubmissionBlocked?(block: ComposerSubmissionBlock): void;
28
- onControlEvent(event: ComposerAttachmentControlEvent): void;
29
- onStateChange(): void;
30
- activateHomeSession(draft: HomeComposerDraft): boolean | void;
31
- sendMessage(text: string): Promise<void>;
32
- }): {
33
- attachments: ComposerAttachmentsController;
34
- submit: ComposerSubmitController;
7
+ export interface HomeComposerFeature extends ComposerSurface {
35
8
  setWorkspace(destination: string): void;
36
9
  environmentChanged(): void;
37
- dispatch(): void;
10
+ dispatch(): ReturnType<ComposerSubmitController["dispatch"]>;
38
11
  upload(file: ComposerUploadFile): Promise<void>;
39
- render(): void;
40
- };
12
+ }
13
+ export declare function createHomeComposerFeature<T extends ComposerWorkspaceDom & ComposerSurfaceDom>(options: {
14
+ workspace: ComposerWorkspaceController<T>;
15
+ composer: Pick<ComposerFeature, "createSurface">;
16
+ selectedModelSupportsImageInput(): boolean;
17
+ activateHomeSession(scope: ComposerScope): boolean | Promise<boolean>;
18
+ }): HomeComposerFeature;