@abot-ai/runtime 1.7.0 → 1.8.1

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 (532) hide show
  1. package/README.md +216 -222
  2. package/dist/src/capabilities/tool-definition-validator/definition-parser.js +8 -0
  3. package/dist/src/capabilities/tool-request-resources.d.ts +3 -0
  4. package/dist/src/capabilities/tool-types.d.ts +4 -0
  5. package/dist/src/cli/abot.js +2 -0
  6. package/dist/src/cli/host-companion-bundle.mjs +751 -333
  7. package/dist/src/computer-access/collection-consent.d.ts +9 -0
  8. package/dist/src/computer-access/collection-consent.js +47 -0
  9. package/dist/src/computer-access/command-output-capture.d.ts +17 -6
  10. package/dist/src/computer-access/command-output-capture.js +134 -68
  11. package/dist/src/computer-access/command-output-protection.d.ts +17 -0
  12. package/dist/src/computer-access/command-output-protection.js +59 -0
  13. package/dist/src/computer-access/companion/command-output.d.ts +1 -0
  14. package/dist/src/computer-access/companion/command-output.js +23 -6
  15. package/dist/src/computer-access/companion/install-link-macos.js +2 -1
  16. package/dist/src/computer-access/companion/native-notifications.js +3 -2
  17. package/dist/src/computer-access/companion/native-session.js +6 -2
  18. package/dist/src/computer-access/companion/observation-filter.js +2 -26
  19. package/dist/src/computer-access/companion/observation-process.d.ts +2 -0
  20. package/dist/src/computer-access/companion/observation-process.js +51 -25
  21. package/dist/src/computer-access/companion/observation-redaction.d.ts +2 -7
  22. package/dist/src/computer-access/companion/observation-redaction.js +2 -111
  23. package/dist/src/computer-access/companion/secret-protection-protocol.d.ts +6 -0
  24. package/dist/src/computer-access/companion/secret-protection-protocol.js +6 -0
  25. package/dist/src/computer-access/computer/companion-sessions.js +7 -6
  26. package/dist/src/computer-access/computer/unix-native-process.js +23 -11
  27. package/dist/src/computer-access/handlers.d.ts +2 -1
  28. package/dist/src/computer-access/handlers.js +79 -11
  29. package/dist/src/computer-access/host-observation.d.ts +3 -3
  30. package/dist/src/computer-access/native-observation-connection.d.ts +12 -0
  31. package/dist/src/computer-access/native-observation-connection.js +78 -0
  32. package/dist/src/computer-access/native-observation-ownership.d.ts +6 -0
  33. package/dist/src/computer-access/native-observation-ownership.js +55 -0
  34. package/dist/src/computer-access/native-observation-shutdown.d.ts +7 -0
  35. package/dist/src/computer-access/native-observation-shutdown.js +58 -0
  36. package/dist/src/computer-access/observation-source.d.ts +6 -0
  37. package/dist/src/computer-access/observation-source.js +10 -0
  38. package/dist/src/computer-access/security/desktop-result.d.ts +8 -0
  39. package/dist/src/computer-access/security/desktop-result.js +146 -0
  40. package/dist/src/computer-access/security/observed-error.d.ts +2 -0
  41. package/dist/src/computer-access/security/observed-error.js +10 -0
  42. package/dist/src/computer-access/security/secret-text.d.ts +7 -0
  43. package/dist/src/computer-access/security/secret-text.js +111 -0
  44. package/dist/src/computer-access/security/system-results.d.ts +2 -0
  45. package/dist/src/computer-access/security/system-results.js +53 -0
  46. package/dist/src/computer-access/system-result-protection.d.ts +11 -0
  47. package/dist/src/computer-access/system-result-protection.js +1 -0
  48. package/dist/src/model-gateway/observability/provider-response-capture.d.ts +60 -0
  49. package/dist/src/model-gateway/observability/provider-response-capture.js +68 -0
  50. package/dist/src/model-gateway/observability/provider-response-prefix.d.ts +7 -0
  51. package/dist/src/model-gateway/observability/provider-response-prefix.js +14 -0
  52. package/dist/src/model-gateway/observability/provider-response-tail.d.ts +8 -0
  53. package/dist/src/model-gateway/observability/provider-response-tail.js +28 -0
  54. package/dist/src/model-gateway/observability/provider-sse-diagnostics.d.ts +30 -0
  55. package/dist/src/model-gateway/observability/provider-sse-diagnostics.js +119 -0
  56. package/dist/src/model-gateway/observability/provider-trace.js +30 -8
  57. package/dist/src/model-gateway/protocol/message-contract.d.ts +1 -0
  58. package/dist/src/model-gateway/protocol/message-contract.js +1 -1
  59. package/dist/src/model-gateway/providers/ollama/adapter.js +8 -2
  60. package/dist/src/model-gateway/providers/ollama/stream-normalizer.js +70 -50
  61. package/dist/src/model-gateway/providers/ollama/stream-termination.d.ts +6 -0
  62. package/dist/src/model-gateway/providers/ollama/stream-termination.js +20 -0
  63. package/dist/src/model-gateway/providers/openai/adapter.js +9 -7
  64. package/dist/src/model-gateway/providers/openai/diagnostics.d.ts +0 -1
  65. package/dist/src/model-gateway/providers/openai/diagnostics.js +0 -9
  66. package/dist/src/model-gateway/providers/openai/function-output.d.ts +11 -0
  67. package/dist/src/model-gateway/providers/openai/function-output.js +37 -0
  68. package/dist/src/model-gateway/providers/openai/function-result.d.ts +7 -0
  69. package/dist/src/model-gateway/providers/openai/function-result.js +35 -0
  70. package/dist/src/model-gateway/providers/openai/message-output-policy.d.ts +3 -0
  71. package/dist/src/model-gateway/providers/openai/message-output-policy.js +16 -0
  72. package/dist/src/model-gateway/providers/openai/payload.d.ts +0 -2
  73. package/dist/src/model-gateway/providers/openai/payload.js +6 -23
  74. package/dist/src/model-gateway/providers/openai/response-lifetime.d.ts +2 -0
  75. package/dist/src/model-gateway/providers/openai/response-lifetime.js +64 -0
  76. package/dist/src/model-gateway/providers/openai/sse-data.d.ts +9 -0
  77. package/dist/src/model-gateway/providers/openai/sse-data.js +67 -0
  78. package/dist/src/model-gateway/providers/openai/stream-normalizer.d.ts +10 -22
  79. package/dist/src/model-gateway/providers/openai/stream-normalizer.js +78 -79
  80. package/dist/src/model-gateway/providers/openai/stream.js +13 -41
  81. package/dist/src/model-gateway/providers/openai/structured-message-output.d.ts +42 -0
  82. package/dist/src/model-gateway/providers/openai/structured-message-output.js +175 -0
  83. package/dist/src/model-gateway/server/chat-handler.js +5 -7
  84. package/dist/src/model-gateway/server/chat-stream-response.d.ts +7 -0
  85. package/dist/src/model-gateway/server/chat-stream-response.js +25 -0
  86. package/dist/src/model-gateway/server.js +5 -1
  87. package/dist/src/plugin-contract/index.d.ts +1 -0
  88. package/dist/src/plugin-contract/index.js +1 -0
  89. package/dist/src/plugin-contract/manifest.d.ts +2 -0
  90. package/dist/src/plugin-contract/manifest.js +1 -0
  91. package/dist/src/plugin-contract/platform-compatibility.d.ts +16 -0
  92. package/dist/src/plugin-contract/platform-compatibility.js +3 -0
  93. package/dist/src/plugin-sdk/computer-access.d.ts +4 -0
  94. package/dist/src/plugin-sdk/computer-access.js +1 -0
  95. package/dist/src/plugin-sdk/files-windows/process.d.ts +3 -0
  96. package/dist/src/plugin-sdk/files-windows/process.js +93 -0
  97. package/dist/src/plugin-sdk/files-windows/read-script.d.ts +1 -0
  98. package/dist/src/plugin-sdk/files-windows/read-script.js +43 -0
  99. package/dist/src/plugin-sdk/files-windows/read.d.ts +6 -0
  100. package/dist/src/plugin-sdk/files-windows/read.js +56 -0
  101. package/dist/src/plugin-sdk/files-windows/result.d.ts +4 -0
  102. package/dist/src/plugin-sdk/files-windows/result.js +67 -0
  103. package/dist/src/plugin-sdk/files.js +4 -0
  104. package/dist/src/plugin-sdk/index.d.ts +1 -0
  105. package/dist/src/plugin-sdk/index.js +1 -0
  106. package/dist/src/plugin-sdk/mutation-result.d.ts +7 -0
  107. package/dist/src/plugin-sdk/mutation-result.js +11 -0
  108. package/dist/src/runtime/adapters/long-term-memory/file-lock/acquisition.js +20 -3
  109. package/dist/src/runtime/adapters/long-term-memory/file-lock/owner-record.js +3 -1
  110. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.d.ts +3 -0
  111. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.js +20 -0
  112. package/dist/src/runtime/adapters/long-term-memory/file-lock/snapshot.js +7 -3
  113. package/dist/src/runtime/adapters/passive-learning-runtime.d.ts +1 -1
  114. package/dist/src/runtime/adapters/passive-learning-runtime.js +3 -3
  115. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.d.ts +2 -2
  116. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.js +2 -2
  117. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/prepared-execution.js +17 -11
  118. package/dist/src/runtime/adapters/runtime-observation-connection.d.ts +5 -0
  119. package/dist/src/runtime/adapters/runtime-observation-connection.js +13 -0
  120. package/dist/src/runtime/capabilities/tool-availability.js +6 -0
  121. package/dist/src/runtime/context/capability-brief.d.ts +2 -2
  122. package/dist/src/runtime/context/capability-brief.js +3 -3
  123. package/dist/src/runtime/context/capability-descriptions.d.ts +3 -2
  124. package/dist/src/runtime/context/capability-descriptions.js +57 -20
  125. package/dist/src/runtime/local-host/windows-private-access.js +2 -0
  126. package/dist/src/runtime/long-term-memory/conversation-authoring/context.d.ts +6 -1
  127. package/dist/src/runtime/long-term-memory/conversation-authoring/context.js +51 -25
  128. package/dist/src/runtime/long-term-memory/initial-context.d.ts +17 -0
  129. package/dist/src/runtime/long-term-memory/initial-context.js +57 -0
  130. package/dist/src/runtime/long-term-memory/projection.js +1 -1
  131. package/dist/src/runtime/orchestration/role-calls/candidate-validation.js +2 -1
  132. package/dist/src/runtime/orchestration/role-calls/checkpoint-state.d.ts +1 -1
  133. package/dist/src/runtime/orchestration/role-calls/checkpoint-state.js +5 -2
  134. package/dist/src/runtime/orchestration/role-calls/contracts.d.ts +2 -1
  135. package/dist/src/runtime/orchestration/role-calls/ledger.d.ts +2 -1
  136. package/dist/src/runtime/orchestration/role-calls/ledger.js +2 -2
  137. package/dist/src/runtime/orchestration/role-calls/memory-recall-contract.d.ts +7 -0
  138. package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.d.ts +2 -0
  139. package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.js +88 -0
  140. package/dist/src/runtime/orchestration/role-calls/reducer.d.ts +1 -1
  141. package/dist/src/runtime/orchestration/role-calls/reducer.js +2 -1
  142. package/dist/src/runtime/orchestration/worker-capabilities/contracts.d.ts +3 -1
  143. package/dist/src/runtime/orchestration/worker-capabilities/contracts.js +1 -1
  144. package/dist/src/runtime/orchestration/worker-capabilities/execution/approval-group.js +5 -1
  145. package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.d.ts +5 -0
  146. package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.js +31 -0
  147. package/dist/src/runtime/passive-learning/application-catalog.js +3 -1
  148. package/dist/src/runtime/passive-learning/collection-source.js +7 -0
  149. package/dist/src/runtime/passive-learning/service.js +2 -3
  150. package/dist/src/runtime/passive-learning/status-projection.d.ts +2 -0
  151. package/dist/src/runtime/passive-learning/status-projection.js +9 -0
  152. package/dist/src/runtime/plugins/installation/package.d.ts +8 -0
  153. package/dist/src/runtime/plugins/installation/package.js +2 -0
  154. package/dist/src/runtime/plugins/installation/service.d.ts +7 -0
  155. package/dist/src/runtime/plugins/loader.js +24 -14
  156. package/dist/src/runtime/plugins/manifest-platform-compatibility.d.ts +2 -0
  157. package/dist/src/runtime/plugins/manifest-platform-compatibility.js +39 -0
  158. package/dist/src/runtime/plugins/manifest-projection.js +3 -0
  159. package/dist/src/runtime/plugins/manifest-validator.js +9 -1
  160. package/dist/src/runtime/plugins/platform-compatibility.d.ts +4 -0
  161. package/dist/src/runtime/plugins/platform-compatibility.js +44 -0
  162. package/dist/src/runtime/request/approval-wait/activation-events.js +19 -7
  163. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.d.ts +20 -0
  164. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.js +118 -0
  165. package/dist/src/runtime/request/approval-wait/super-compaction-restore.js +2 -1
  166. package/dist/src/runtime/request/capability-execution-freshness.js +6 -1
  167. package/dist/src/runtime/request/execution-agent-root-execution.js +11 -1
  168. package/dist/src/runtime/request/prepared-execution.js +3 -0
  169. package/dist/src/runtime/request/root-contract.d.ts +2 -0
  170. package/dist/src/runtime/request/root-execution-kernel.js +1 -0
  171. package/dist/src/runtime/request/runner.js +9 -3
  172. package/dist/src/runtime/request/supervisor-root-execution.js +6 -0
  173. package/dist/src/runtime/steps/execution-agent/capability-result-context.d.ts +6 -0
  174. package/dist/src/runtime/steps/execution-agent/capability-result-context.js +29 -0
  175. package/dist/src/runtime/steps/execution-agent/contracts.d.ts +10 -0
  176. package/dist/src/runtime/steps/execution-agent/decision-parsing.js +13 -1
  177. package/dist/src/runtime/steps/execution-agent/direct-response-configuration.d.ts +3 -0
  178. package/dist/src/runtime/steps/execution-agent/direct-response-configuration.js +64 -0
  179. package/dist/src/runtime/steps/execution-agent/direct-response-contract.d.ts +7 -0
  180. package/dist/src/runtime/steps/execution-agent/direct-response-contract.js +56 -0
  181. package/dist/src/runtime/steps/execution-agent/direct-response-policy.d.ts +9 -0
  182. package/dist/src/runtime/steps/execution-agent/direct-response-policy.js +30 -0
  183. package/dist/src/runtime/steps/execution-agent/direct-response-prompt.d.ts +7 -0
  184. package/dist/src/runtime/steps/execution-agent/direct-response-prompt.js +43 -0
  185. package/dist/src/runtime/steps/execution-agent/format.js +4 -3
  186. package/dist/src/runtime/steps/execution-agent/input.d.ts +2 -0
  187. package/dist/src/runtime/steps/execution-agent/input.js +22 -1
  188. package/dist/src/runtime/steps/execution-agent/plugin-catalog.d.ts +4 -0
  189. package/dist/src/runtime/steps/execution-agent/plugin-catalog.js +8 -0
  190. package/dist/src/runtime/steps/execution-agent/prompt.d.ts +1 -0
  191. package/dist/src/runtime/steps/execution-agent/prompt.js +7 -8
  192. package/dist/src/runtime/steps/execution-agent/response-prompt.js +1 -0
  193. package/dist/src/runtime/steps/execution-agent/response-run.js +5 -11
  194. package/dist/src/runtime/steps/execution-agent/run.js +4 -1
  195. package/dist/src/runtime/steps/execution-agent/state-context.d.ts +3 -5
  196. package/dist/src/runtime/steps/execution-agent/state-context.js +5 -51
  197. package/dist/src/runtime/steps/execution-agent/work-plan-contract.d.ts +1 -3
  198. package/dist/src/runtime/steps/execution-agent/work-plan-contract.js +0 -55
  199. package/dist/src/runtime/steps/execution-agent/work-plan-schema.d.ts +3 -0
  200. package/dist/src/runtime/steps/execution-agent/work-plan-schema.js +61 -0
  201. package/dist/src/runtime/steps/planner-decision/capability-brief.d.ts +2 -0
  202. package/dist/src/runtime/steps/planner-decision/prompt.js +26 -49
  203. package/dist/src/runtime/steps/supervisor-decision/input.d.ts +1 -0
  204. package/dist/src/runtime/steps/supervisor-decision/input.js +5 -0
  205. package/dist/src/runtime/steps/supervisor-decision/prompt.d.ts +1 -0
  206. package/dist/src/runtime/steps/supervisor-decision/prompt.js +6 -2
  207. package/dist/src/runtime/steps/supervisor-decision/run.d.ts +1 -0
  208. package/dist/src/runtime/steps/supervisor-decision/run.js +4 -0
  209. package/dist/src/runtime/steps/supervisor-response/run.d.ts +2 -0
  210. package/dist/src/runtime/steps/supervisor-response/run.js +3 -6
  211. package/dist/src/sessions/durable-session-commit.js +3 -3
  212. package/dist/src/sessions/prepared-session-replacement.d.ts +6 -0
  213. package/dist/src/sessions/prepared-session-replacement.js +46 -0
  214. package/dist/src/sessions/session-store.js +3 -3
  215. package/dist/src/shared/passive-observation-self-exclusion.d.ts +5 -0
  216. package/dist/src/shared/passive-observation-self-exclusion.js +37 -0
  217. package/dist/src/shared/windows-file-io/authority-script.d.ts +1 -0
  218. package/dist/src/shared/windows-file-io/authority-script.js +94 -0
  219. package/dist/src/shared/windows-file-io/native-script.d.ts +2 -0
  220. package/dist/src/shared/windows-file-io/native-script.js +120 -0
  221. package/dist/src/shared/windows-file-io/read-bytes-script.d.ts +1 -0
  222. package/dist/src/shared/windows-file-io/read-bytes-script.js +18 -0
  223. package/dist/src/shared/windows-job-object.d.ts +2 -0
  224. package/dist/src/shared/windows-job-object.js +66 -0
  225. package/dist/src/web-ui/app/ARCHITECTURE.md +1 -1
  226. package/dist/src/web-ui/app/app-bootstrap.js +14 -1
  227. package/dist/src/web-ui/app/app-state.js +0 -7
  228. package/dist/src/web-ui/app/app.js +54 -156
  229. package/dist/src/web-ui/app/components/automations/node-inspector.js +3 -2
  230. package/dist/src/web-ui/app/components/automations/step-editor-dialog.js +3 -0
  231. package/dist/src/web-ui/app/components/automations/timeline.js +3 -2
  232. package/dist/src/web-ui/app/components/composer-submission-notice.js +50 -0
  233. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +7 -1
  234. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +22 -2
  235. package/dist/src/web-ui/app/components/dashboard/compact-layout.js +137 -0
  236. package/dist/src/web-ui/app/components/dashboard/icons.js +5 -0
  237. package/dist/src/web-ui/app/components/dashboard/widget-card.js +85 -0
  238. package/dist/src/web-ui/app/components/dashboard/widget-dialog.js +83 -0
  239. package/dist/src/web-ui/app/components/dashboard/widget-summaries.js +155 -0
  240. package/dist/src/web-ui/app/components/dashboard/workspace.js +28 -4
  241. package/dist/src/web-ui/app/components/home-guidance/daily-review.js +2 -2
  242. package/dist/src/web-ui/app/components/home-guidance/home-guidance.js +20 -6
  243. package/dist/src/web-ui/app/components/model-setup/context-window-feedback.js +53 -0
  244. package/dist/src/web-ui/app/components/model-setup/save-flow.js +3 -1
  245. package/dist/src/web-ui/app/components/model-setup/save-outcome.js +1 -0
  246. package/dist/src/web-ui/app/components/model-setup/wizard.js +12 -0
  247. package/dist/src/web-ui/app/components/operations-summary.js +2 -1
  248. package/dist/src/web-ui/app/components/passive-learning/activity-controls.js +4 -0
  249. package/dist/src/web-ui/app/components/passive-learning/collection-access.js +35 -0
  250. package/dist/src/web-ui/app/components/passive-learning/collection-consent-dialog.js +59 -0
  251. package/dist/src/web-ui/app/components/passive-learning/collection-consent-gate.js +94 -0
  252. package/dist/src/web-ui/app/components/passive-learning/computer-update-notice.js +6 -0
  253. package/dist/src/web-ui/app/components/passive-learning/failure-copy.js +1 -0
  254. package/dist/src/web-ui/app/components/passive-learning/home-widget-preview.js +32 -0
  255. package/dist/src/web-ui/app/components/passive-learning/home.js +11 -3
  256. package/dist/src/web-ui/app/components/passive-learning/macos-collection-restart-notice.js +1 -0
  257. package/dist/src/web-ui/app/components/passive-learning/memory.js +2 -4
  258. package/dist/src/web-ui/app/components/passive-learning/workspace-view.js +2 -2
  259. package/dist/src/web-ui/app/components/plugins/compatibility.js +13 -0
  260. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +9 -1
  261. package/dist/src/web-ui/app/components/plugins/installation-compatibility.js +7 -0
  262. package/dist/src/web-ui/app/components/plugins/installation.js +2 -1
  263. package/dist/src/web-ui/app/components/plugins/rendering.js +3 -0
  264. package/dist/src/web-ui/app/components/reasoning-override-prompt.js +82 -0
  265. package/dist/src/web-ui/app/components/runtime-config-activation.js +22 -8
  266. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +7 -4
  267. package/dist/src/web-ui/app/components/runtime-setup/plugins.js +3 -1
  268. package/dist/src/web-ui/app/components/runtime-setup/rendering.js +6 -4
  269. package/dist/src/web-ui/app/components/runtime-setup-guide.d.ts +1 -0
  270. package/dist/src/web-ui/app/components/schedules/details.js +3 -2
  271. package/dist/src/web-ui/app/components/schedules/form.js +10 -8
  272. package/dist/src/web-ui/app/components/schedules/workspace.js +23 -4
  273. package/dist/src/web-ui/app/components/session-sidebar-sections.js +2 -2
  274. package/dist/src/web-ui/app/components/spark-chat/handoff-actions.js +9 -3
  275. package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -1
  276. package/dist/src/web-ui/app/components/spark-chat/placement.js +4 -7
  277. package/dist/src/web-ui/app/components/spark-chat/settings.js +8 -4
  278. package/dist/src/web-ui/app/components/system-host/home-widget-permission-preview.js +75 -0
  279. package/dist/src/web-ui/app/components/system-host/home-widget-summary.js +93 -0
  280. package/dist/src/web-ui/app/components/system-host/macos-permission-rendering.js +2 -2
  281. package/dist/src/web-ui/app/components/system-host/macos-permissions.js +2 -0
  282. package/dist/src/web-ui/app/components/system-host/native-windows-access.js +50 -0
  283. package/dist/src/web-ui/app/components/system-host/rendering.js +6 -3
  284. package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +2 -2
  285. package/dist/src/web-ui/app/components/workspace-storage-notice.js +37 -0
  286. package/dist/src/web-ui/app/computer-access-feature.js +13 -1
  287. package/dist/src/web-ui/app/configuration-environment-refresh.js +27 -34
  288. package/dist/src/web-ui/app/configuration-feature.js +11 -1
  289. package/dist/src/web-ui/app/controllers/app-event-bindings.js +38 -105
  290. package/dist/src/web-ui/app/controllers/chat-request-controller.d.ts +28 -0
  291. package/dist/src/web-ui/app/controllers/chat-request-controller.js +34 -66
  292. package/dist/src/web-ui/app/controllers/composer-attachments-controller.d.ts +15 -40
  293. package/dist/src/web-ui/app/controllers/composer-attachments-controller.js +26 -69
  294. package/dist/src/web-ui/app/controllers/composer-draft-view.d.ts +27 -0
  295. package/dist/src/web-ui/app/controllers/composer-draft-view.js +48 -0
  296. package/dist/src/web-ui/app/controllers/composer-drafts.d.ts +55 -0
  297. package/dist/src/web-ui/app/controllers/composer-drafts.js +120 -0
  298. package/dist/src/web-ui/app/controllers/composer-feature.d.ts +65 -0
  299. package/dist/src/web-ui/app/controllers/composer-feature.js +124 -0
  300. package/dist/src/web-ui/app/controllers/composer-queue-controller.d.ts +33 -94
  301. package/dist/src/web-ui/app/controllers/composer-queue-controller.js +185 -251
  302. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.d.ts +48 -0
  303. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.js +97 -0
  304. package/dist/src/web-ui/app/controllers/composer-submit-controller.d.ts +30 -61
  305. package/dist/src/web-ui/app/controllers/composer-submit-controller.js +56 -138
  306. package/dist/src/web-ui/app/controllers/composer-surface-controller.js +6 -0
  307. package/dist/src/web-ui/app/controllers/composer-workspace-controller.d.ts +22 -40
  308. package/dist/src/web-ui/app/controllers/composer-workspace-controller.js +49 -165
  309. package/dist/src/web-ui/app/controllers/conversation-navigation-intent.js +15 -0
  310. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +20 -17
  311. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +1 -2
  312. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +49 -22
  313. package/dist/src/web-ui/app/controllers/conversation-workspace-activation.js +27 -0
  314. package/dist/src/web-ui/app/controllers/daily-memory-review.js +15 -16
  315. package/dist/src/web-ui/app/controllers/environment-transition.js +126 -0
  316. package/dist/src/web-ui/app/controllers/environment-workspace-preparation.js +18 -0
  317. package/dist/src/web-ui/app/controllers/home-composer-feature.d.ts +14 -36
  318. package/dist/src/web-ui/app/controllers/home-composer-feature.js +17 -114
  319. package/dist/src/web-ui/app/controllers/home-conversation-activation.js +6 -8
  320. package/dist/src/web-ui/app/controllers/operations-controller.js +2 -1
  321. package/dist/src/web-ui/app/controllers/passive-learning-controller.js +56 -0
  322. package/dist/src/web-ui/app/controllers/projects-controller.d.ts +1 -1
  323. package/dist/src/web-ui/app/controllers/projects-controller.js +6 -1
  324. package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +174 -0
  325. package/dist/src/web-ui/app/controllers/runtime-selection-controller.d.ts +7 -0
  326. package/dist/src/web-ui/app/controllers/runtime-selection-controller.js +20 -155
  327. package/dist/src/web-ui/app/controllers/session-controller.js +33 -17
  328. package/dist/src/web-ui/app/controllers/session-pin-updates.js +14 -0
  329. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +12 -14
  330. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +2 -2
  331. package/dist/src/web-ui/app/controllers/steer-controller.js +9 -7
  332. package/dist/src/web-ui/app/controllers/tool-permission-mode-controller.js +1 -1
  333. package/dist/src/web-ui/app/controllers/workspace-conversation-opener.js +34 -0
  334. package/dist/src/web-ui/app/dashboard-feature.js +12 -2
  335. package/dist/src/web-ui/app/lib/reasoning-controls.js +40 -0
  336. package/dist/src/web-ui/app/lib/session-composer-queue-ownership.js +58 -0
  337. package/dist/src/web-ui/app/lib/session-composer-queue.d.ts +12 -0
  338. package/dist/src/web-ui/app/lib/session-composer-queue.js +25 -6
  339. package/dist/src/web-ui/app/passive-learning-feature.js +18 -5
  340. package/dist/src/web-ui/app/schedules-feature.js +5 -3
  341. package/dist/src/web-ui/app/services/client-preferences.d.ts +18 -10
  342. package/dist/src/web-ui/app/services/client-preferences.js +25 -16
  343. package/dist/src/web-ui/app/services/home-guidance-preferences.js +13 -13
  344. package/dist/src/web-ui/app/services/reasoning-override.js +12 -0
  345. package/dist/src/web-ui/app/services/runtime-web-client/automations.js +10 -2
  346. package/dist/src/web-ui/app/services/runtime-web-client/memory.js +7 -2
  347. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  348. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +2 -0
  349. package/dist/src/web-ui/app/services/runtime-web-client.js +2 -0
  350. package/dist/src/web-ui/app/services/server-composer-queue.js +32 -0
  351. package/dist/src/web-ui/app/services/session-sidebar-preferences.js +5 -5
  352. package/dist/src/web-ui/app/services/workspace-state-storage.js +116 -0
  353. package/dist/src/web-ui/app/services/workspace-state.js +27 -0
  354. package/dist/src/web-ui/app/spark-chat-conversation.js +34 -45
  355. package/dist/src/web-ui/app/spark-chat-feature.js +10 -4
  356. package/dist/src/web-ui/app/styles/21-composer-controls.css +16 -0
  357. package/dist/src/web-ui/app/styles/41-plugin-management.css +8 -0
  358. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +1 -0
  359. package/dist/src/web-ui/app/styles/49-collection-consent.css +30 -0
  360. package/dist/src/web-ui/app/styles/64-workspace-storage.css +23 -0
  361. package/dist/src/web-ui/app/styles/95-home-widgets.css +109 -0
  362. package/dist/src/web-ui/app/styles.css +3 -0
  363. package/dist/src/web-ui/client-state/contracts.d.ts +15 -0
  364. package/dist/src/web-ui/client-state/contracts.js +13 -0
  365. package/dist/src/web-ui/client-state/preference-shapes.d.ts +2 -0
  366. package/dist/src/web-ui/client-state/preference-shapes.js +80 -0
  367. package/dist/src/web-ui/client-state/preferences.d.ts +3 -0
  368. package/dist/src/web-ui/client-state/preferences.js +84 -0
  369. package/dist/src/web-ui/client-state/queue.d.ts +3 -0
  370. package/dist/src/web-ui/client-state/queue.js +43 -0
  371. package/dist/src/web-ui/client-state/routes.d.ts +7 -0
  372. package/dist/src/web-ui/client-state/routes.js +58 -0
  373. package/dist/src/web-ui/client-state/store.d.ts +14 -0
  374. package/dist/src/web-ui/client-state/store.js +88 -0
  375. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +2 -0
  376. package/dist/src/web-ui/local-runtime/http.js +11 -2
  377. package/dist/src/web-ui/local-runtime/model-context-capacity-error.d.ts +14 -0
  378. package/dist/src/web-ui/local-runtime/model-context-capacity-error.js +28 -0
  379. package/dist/src/web-ui/local-runtime/model-setup-context-window.d.ts +15 -0
  380. package/dist/src/web-ui/local-runtime/model-setup-context-window.js +25 -0
  381. package/dist/src/web-ui/local-runtime/model-setup-routes.js +2 -0
  382. package/dist/src/web-ui/local-runtime/model-setup-service.js +5 -2
  383. package/dist/src/web-ui/local-runtime/model-setup-validation.d.ts +1 -0
  384. package/dist/src/web-ui/local-runtime/model-setup-validation.js +14 -7
  385. package/dist/src/web-ui/local-runtime/request-body-error.d.ts +11 -0
  386. package/dist/src/web-ui/local-runtime/request-body-error.js +14 -0
  387. package/dist/src/web-ui/local-runtime/request-control-observation.js +2 -2
  388. package/dist/src/web-ui/local-runtime/request-execution.js +18 -18
  389. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.d.ts +2 -0
  390. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.js +35 -22
  391. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +2 -9
  392. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +4 -27
  393. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.d.ts +15 -1
  394. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.js +30 -11
  395. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.d.ts +20 -0
  396. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.js +104 -0
  397. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.d.ts +29 -0
  398. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.js +151 -0
  399. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.d.ts +7 -0
  400. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.js +87 -0
  401. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.d.ts +3 -0
  402. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.js +37 -0
  403. package/dist/src/web-ui/local-runtime/runtime-setup-service.js +4 -0
  404. package/dist/src/web-ui/local-runtime-backend.js +14 -0
  405. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  406. package/dist/src/web-ui/plugin-management-catalog.js +3 -1
  407. package/dist/src/web-ui/plugin-management-service.d.ts +1 -0
  408. package/dist/src/web-ui/plugin-removal-service.d.ts +1 -0
  409. package/dist/src/web-ui/server-readiness.d.ts +3 -0
  410. package/dist/src/web-ui/server-readiness.js +36 -0
  411. package/dist/src/web-ui/server.d.ts +2 -0
  412. package/dist/src/web-ui/server.js +23 -1
  413. package/dist/src/web-ui/system-host-service.js +13 -2
  414. package/dist/src/web-ui/system-host-setup/collection-consent-route.d.ts +3 -0
  415. package/dist/src/web-ui/system-host-setup/collection-consent-route.js +30 -0
  416. package/docs/installation.md +44 -5
  417. package/docs/plugins.md +174 -28
  418. package/docs/tool-execution-result-evidence-contract.md +57 -0
  419. package/docs/windows-companion-store.md +5 -0
  420. package/package.json +4 -2
  421. package/plugins/capability-brief/plugin.json +5 -1
  422. package/plugins/code-outline/README.md +20 -0
  423. package/plugins/code-outline/plugin.json +2 -1
  424. package/plugins/code-outline/source/index.ts +16 -20
  425. package/plugins/code-outline/source/read-failure.ts +40 -0
  426. package/plugins/code-outline/src/index.cjs +614 -29
  427. package/plugins/document-reader/README.md +33 -0
  428. package/plugins/document-reader/plugin.json +2 -1
  429. package/plugins/document-reader/source/pdf-contract.ts +57 -0
  430. package/plugins/document-reader/source/pdf-parser.ts +139 -0
  431. package/plugins/document-reader/source/pdf-process-main.ts +56 -0
  432. package/plugins/document-reader/source/pdf-process.ts +207 -0
  433. package/plugins/document-reader/source/pdf-result.ts +79 -0
  434. package/plugins/document-reader/source/pdf-worker.ts +39 -303
  435. package/plugins/document-reader/source/pdf.ts +4 -1
  436. package/plugins/document-reader/source/read-failure.ts +37 -0
  437. package/plugins/document-reader/source/reader.ts +3 -19
  438. package/plugins/document-reader/src/index.cjs +995 -211
  439. package/plugins/exec/README.md +19 -0
  440. package/plugins/exec/plugin.json +4 -3
  441. package/plugins/exec/skills/exec_skill/SKILL.md +3 -2
  442. package/plugins/exec/source/filesystem-file-observer.ts +98 -0
  443. package/plugins/exec/source/filesystem-observer.ts +8 -79
  444. package/plugins/exec/source/output-files.ts +12 -6
  445. package/plugins/exec/source/paths.ts +3 -1
  446. package/plugins/exec/source/process-manager.ts +8 -24
  447. package/plugins/exec/source/shell-platform.ts +19 -3
  448. package/plugins/exec/source/shell-process.ts +55 -0
  449. package/plugins/exec/source/windows-job-source.ts +1 -0
  450. package/plugins/exec/source/windows-shell-bootstrap.ts +20 -0
  451. package/plugins/exec/src/index.cjs +252 -96
  452. package/plugins/filesystem/README.md +65 -0
  453. package/plugins/filesystem/plugin.json +7 -3
  454. package/plugins/filesystem/source/atomic-write.ts +2 -0
  455. package/plugins/filesystem/source/bounded-io.ts +80 -306
  456. package/plugins/filesystem/source/directory-sample.ts +2 -0
  457. package/plugins/filesystem/source/errors.ts +14 -0
  458. package/plugins/filesystem/source/file-observation.ts +151 -0
  459. package/plugins/filesystem/source/file-version.ts +41 -0
  460. package/plugins/filesystem/source/index.ts +6 -0
  461. package/plugins/filesystem/source/mutation-coordinator.ts +1 -0
  462. package/plugins/filesystem/source/windows/authority-script.ts +1 -0
  463. package/plugins/filesystem/source/windows/native-script.ts +1 -0
  464. package/plugins/filesystem/source/windows/operations.ts +197 -0
  465. package/plugins/filesystem/source/windows/process.ts +214 -0
  466. package/plugins/filesystem/source/windows/publication-script.ts +29 -0
  467. package/plugins/filesystem/source/windows/read-script.ts +63 -0
  468. package/plugins/filesystem/source/windows/request-availability.ts +67 -0
  469. package/plugins/filesystem/source/windows/source.ts +42 -0
  470. package/plugins/filesystem/source/windows/storage-script.ts +11 -0
  471. package/plugins/filesystem/source/windows/streams-script.ts +24 -0
  472. package/plugins/filesystem/source/windows/write-script.ts +86 -0
  473. package/plugins/filesystem/src/index.cjs +1208 -322
  474. package/plugins/json-inspector/README.md +18 -0
  475. package/plugins/json-inspector/plugin.json +2 -1
  476. package/plugins/json-inspector/source/index.ts +16 -19
  477. package/plugins/json-inspector/source/read-failure.ts +42 -0
  478. package/plugins/json-inspector/src/index.cjs +612 -27
  479. package/plugins/local-search/README.md +29 -0
  480. package/plugins/local-search/plugin.json +2 -1
  481. package/plugins/local-search/source/errors.ts +2 -0
  482. package/plugins/local-search/source/paths.ts +3 -0
  483. package/plugins/local-search/source/ripgrep-process.ts +31 -5
  484. package/plugins/local-search/source/ripgrep.ts +3 -3
  485. package/plugins/local-search/source/windows-authority.ts +99 -0
  486. package/plugins/local-search/source/windows-search-lease.ts +49 -0
  487. package/plugins/local-search/source/windows-search-process.ts +91 -0
  488. package/plugins/local-search/source/windows-search-script.ts +52 -0
  489. package/plugins/local-search/src/index.cjs +595 -26
  490. package/plugins/memory/plugin.json +5 -1
  491. package/plugins/memory/source/lock-directory-claim.ts +56 -0
  492. package/plugins/memory/source/lock-owner-file.ts +71 -0
  493. package/plugins/memory/source/lock-path-observation.ts +26 -0
  494. package/plugins/memory/source/prepared-memory-replacement.ts +40 -0
  495. package/plugins/memory/source/store-lock.ts +12 -7
  496. package/plugins/memory/source/store.ts +3 -2
  497. package/plugins/memory/src/index.cjs +174 -25
  498. package/plugins/project-orientation/README.md +23 -0
  499. package/plugins/project-orientation/plugin.json +2 -1
  500. package/plugins/project-orientation/source/index.ts +12 -9
  501. package/plugins/project-orientation/source/inspection-failure.ts +70 -0
  502. package/plugins/project-orientation/source/manifest-summary.ts +9 -2
  503. package/plugins/project-orientation/source/tree.ts +6 -0
  504. package/plugins/project-orientation/src/index.cjs +647 -31
  505. package/plugins/system/README.md +51 -15
  506. package/plugins/system/plugin.json +6 -2
  507. package/plugins/system/skills/system_actions/SKILL.md +1 -1
  508. package/plugins/system/source/command-working-directory.ts +47 -0
  509. package/plugins/system/source/computer/handlers.ts +13 -9
  510. package/plugins/system/source/computer/observation-result.ts +10 -5
  511. package/plugins/system/source/computer/request-computers.ts +10 -3
  512. package/plugins/system/source/computer/request-modules.ts +3 -6
  513. package/plugins/system/source/computer/runtime-platform.ts +18 -0
  514. package/plugins/system/source/host-dispatch.ts +18 -2
  515. package/plugins/system/source/index.ts +5 -3
  516. package/plugins/system/source/local-command-output-retention.ts +16 -0
  517. package/plugins/system/source/local-command-output.ts +16 -8
  518. package/plugins/system/source/request-system-modules.ts +12 -2
  519. package/plugins/system/source/request-target-snapshot.ts +2 -1
  520. package/plugins/system/source/security/desktop-result.ts +177 -0
  521. package/plugins/system/source/security/observed-error.ts +10 -0
  522. package/plugins/system/source/security/secret-text.ts +118 -0
  523. package/plugins/system/source/security/system-results.ts +62 -0
  524. package/plugins/system/source/security/windows-output-directory.ts +82 -0
  525. package/plugins/system/src/index.cjs +837 -151
  526. package/plugins/system-probe/plugin.json +9 -3
  527. package/plugins/system-probe/source/disk-path.ts +8 -0
  528. package/plugins/system-probe/source/index.ts +10 -5
  529. package/plugins/system-probe/source/machine-load.ts +33 -0
  530. package/plugins/system-probe/source/metrics.ts +6 -8
  531. package/plugins/system-probe/src/index.cjs +49 -16
  532. package/plugins/web/plugin.json +5 -1
@@ -1,8 +1,10 @@
1
+ import { beginConversationNavigation, canNavigateConversation } from "./conversation-navigation-intent.js";
1
2
  import {
2
3
  focusSelectedMenuItem,
3
4
  handleMenuNavigation,
4
5
  } from "../components/menu-navigation.js";
5
6
  import { createWebSessionId, textOf } from "../lib/text-format.js";
7
+ import { createEnvironmentTransition, environmentChangeWasDeclined } from "./environment-transition.js";
6
8
 
7
9
  export function createAppEventBindings({
8
10
  state,
@@ -15,103 +17,44 @@ export function createAppEventBindings({
15
17
  onSessionCreated = () => {},
16
18
  onNavigationChange = () => {},
17
19
  }) {
18
- let environmentChangeRevision = 0;
19
- let environmentChanging = false;
20
- let prepareAdditionalEnvironmentChange = () => true;
20
+ const environmentTransition = createEnvironmentTransition({
21
+ state, dom, actions, prepareQueueRecovery, onNavigationChange,
22
+ onFailure: (error) => shell.showToast?.(error instanceof Error ? error.message : String(error), "failed"),
23
+ });
21
24
 
22
25
  function prepareQueueRecovery() {
23
26
  if (actions.prepareQueueRecovery) return actions.prepareQueueRecovery();
24
27
  return actions.suspendQueueRecovery();
25
28
  }
26
29
 
27
- function suspendQueueRecovery() {
28
- const prepared = prepareQueueRecovery();
29
- if (environmentChangeWasDeclined(prepared)) return false;
30
- if (typeof prepared === "function") prepared();
31
- return true;
32
- }
33
-
34
- async function changeEnvironment(
35
- nextEnvironmentId,
36
- { restoreSession = true, notifyEnvironmentChange = true } = {},
37
- ) {
38
- const previousEnvironmentId = actions.savedEnvironmentId?.() || "";
39
- const recoveryEnvironmentId =
40
- state.activeComposerQueueRecovery?.scope.environmentId ?? "";
41
- const restoreEnvironmentSelection = () => {
42
- dom.environmentSelect.value =
43
- previousEnvironmentId || recoveryEnvironmentId;
44
- state.agentPickerOpen = false;
45
- actions.renderAgentPicker();
46
- };
47
- if (nextEnvironmentId === previousEnvironmentId) {
48
- state.agentPickerOpen = false;
49
- actions.renderAgentPicker();
50
- return true;
51
- }
52
- dom.environmentSelect.value = nextEnvironmentId;
53
- const preparedEnvironmentChange = actions.beforeEnvironmentChange
54
- ? actions.beforeEnvironmentChange({
55
- from: previousEnvironmentId,
56
- to: nextEnvironmentId,
57
- })
58
- : true;
59
- if (environmentChangeWasDeclined(preparedEnvironmentChange)) {
60
- restoreEnvironmentSelection();
61
- return false;
62
- }
63
- const preparedAdditionalChange = prepareAdditionalEnvironmentChange();
64
- if (environmentChangeWasDeclined(preparedAdditionalChange)) {
65
- restoreEnvironmentSelection();
30
+ async function prepareCurrentQueueRecovery() {
31
+ if (!canNavigateConversation(state)) {
32
+ shell.showToast?.("Wait for the environment change to finish before starting a conversation.", "neutral");
66
33
  return false;
67
34
  }
68
- const preparedQueueRecovery = prepareQueueRecovery();
69
- if (environmentChangeWasDeclined(preparedQueueRecovery)) {
70
- restoreEnvironmentSelection();
71
- return false;
72
- }
73
- const revision = ++environmentChangeRevision;
74
- environmentChanging = true;
75
- if (typeof preparedAdditionalChange === "function") preparedAdditionalChange();
76
- if (typeof preparedQueueRecovery === "function") preparedQueueRecovery();
77
- if (typeof preparedEnvironmentChange === "function")
78
- preparedEnvironmentChange();
79
- actions.invalidateSessionLoads?.();
80
- state.agentPickerOpen = false;
81
- actions.renderAgentPicker();
82
- actions.saveEnvironmentId(nextEnvironmentId);
83
- state.currentSessionId = "";
84
- state.messages = [];
85
- actions.clearAttachments();
86
- actions.resetLiveRequestView();
87
- dom.sessionTitle.textContent = "New conversation";
88
- actions.applyConversationChrome();
89
- actions.renderMessages();
90
- try {
91
- const loading = Promise.allSettled([
92
- actions.loadModels(),
93
- actions.loadAgentMode(),
94
- actions.loadRuntimeConfig({
95
- protectUnsaved: false,
96
- clearBeforeLoad: true,
97
- }),
98
- ]);
99
- if (notifyEnvironmentChange) {
100
- const ChangeEvent =
101
- dom.environmentSelect.ownerDocument?.defaultView?.Event ?? Event;
102
- dom.environmentSelect.dispatchEvent(new ChangeEvent("change"));
103
- }
104
- await loading;
105
- if (revision !== environmentChangeRevision) return false;
106
- if (dom.environmentSelect.value !== nextEnvironmentId) return false;
107
- if (restoreSession) await actions.restoreLastSession();
108
- return dom.environmentSelect.value === nextEnvironmentId;
109
- } finally {
110
- if (revision === environmentChangeRevision) {
111
- environmentChanging = false;
112
- onNavigationChange();
113
- }
114
- }
35
+ const isCurrentNavigation = beginConversationNavigation(state);
36
+ const navigationRevision = shell.navigationRevision?.();
37
+ const environment = actions.selectedEnvironmentId?.();
38
+ const session = state.currentSessionId;
39
+ const prepared = await prepareQueueRecovery();
40
+ if (environmentChangeWasDeclined(prepared)) return false;
41
+ if (!canNavigateConversation(state)) return false;
42
+ if (!isCurrentNavigation()) return false;
43
+ if (prepared?.canCommit?.() === false) return false;
44
+ const hasCurrentWorkspaceNavigation = navigationRevision === shell.navigationRevision?.();
45
+ if (!hasCurrentWorkspaceNavigation) return false;
46
+ if (actions.selectedEnvironmentId?.() !== environment) return false;
47
+ if (state.currentSessionId !== session) return false;
48
+ return () => {
49
+ if (!canNavigateConversation(state)) return false;
50
+ if (!isCurrentNavigation()) return false;
51
+ if (navigationRevision !== shell.navigationRevision?.()) return false;
52
+ if (actions.selectedEnvironmentId?.() !== environment) return false;
53
+ if (state.currentSessionId !== session) return false;
54
+ if (prepared?.canCommit?.() === false) return false;
55
+ if (typeof prepared === "function") prepared();
56
+ return true;
57
+ };
115
58
  }
116
59
 
117
60
  function bind() {
@@ -126,13 +69,15 @@ export function createAppEventBindings({
126
69
  "click",
127
70
  () => void actions.loadSessions(),
128
71
  );
129
- dom.newSessionButton.addEventListener("click", () => {
72
+ dom.newSessionButton.addEventListener("click", async () => {
73
+ const recovery = await prepareCurrentQueueRecovery();
74
+ if (!recovery) return;
130
75
  const preparedWorkspaceActivation = shell.prepareWorkspaceActivation(
131
76
  "chat",
132
77
  { focus: false },
133
78
  );
134
79
  if (!preparedWorkspaceActivation) return;
135
- if (!suspendQueueRecovery()) return;
80
+ if (recovery() === false) return;
136
81
  if (preparedWorkspaceActivation() === false) return;
137
82
  state.currentSessionId = createWebSessionId();
138
83
  onSessionCreated(state.currentSessionId);
@@ -142,7 +87,6 @@ export function createAppEventBindings({
142
87
  );
143
88
  actions.rememberModelSelection();
144
89
  state.messages = [];
145
- actions.clearAttachments();
146
90
  actions.resetLiveRequestView();
147
91
  actions.setCurrentSessionTitle(state.currentSessionId);
148
92
  actions.applyConversationChrome();
@@ -152,11 +96,7 @@ export function createAppEventBindings({
152
96
  shell.setSessionsDrawerOpen(false);
153
97
  dom.composerInput.focus();
154
98
  });
155
- dom.environmentSelect.addEventListener("change", () => {
156
- void changeEnvironment(dom.environmentSelect.value, {
157
- notifyEnvironmentChange: false,
158
- });
159
- }, true);
99
+ dom.environmentSelect.addEventListener("change", environmentTransition.onSelectChange, true);
160
100
  dom.agentPickerButton.addEventListener("click", (event) => {
161
101
  event.stopPropagation();
162
102
  state.agentPickerOpen = !state.agentPickerOpen;
@@ -366,13 +306,6 @@ export function createAppEventBindings({
366
306
 
367
307
  return {
368
308
  bind,
369
- changeEnvironment,
370
- setEnvironmentChangePreparation(prepare) { prepareAdditionalEnvironmentChange = prepare; },
371
- isEnvironmentChanging: () => environmentChanging,
309
+ ...environmentTransition,
372
310
  };
373
311
  }
374
-
375
- function environmentChangeWasDeclined(preparedChange) {
376
- if (preparedChange === false) return true;
377
- return preparedChange === null;
378
- }
@@ -0,0 +1,28 @@
1
+ import type { createRuntimeWebClient } from "../services/runtime-web-client.js";
2
+ import type { createConversationSessionController } from "./conversation-session-controller.js";
3
+ import type { ComposerScope } from "./composer-drafts.js";
4
+ import type { ComposerSubmissionAttempt, ComposerSubmissionSettings } from "./composer-submission-lifecycle.js";
5
+
6
+ type RuntimeWebClient = ReturnType<typeof createRuntimeWebClient>;
7
+ export type ComposerChatClient = Pick<RuntimeWebClient, "postChatMessage" | "stopChatRequest">;
8
+ export type ComposerChatSession = Pick<ReturnType<typeof createConversationSessionController>, "appendLocalUserMessage" | "activateRequestForScope">;
9
+ export type ComposerChatAttempt = ComposerSubmissionAttempt<ComposerSubmissionSettings>;
10
+
11
+ export interface ChatRequestControllerOptions {
12
+ client: ComposerChatClient;
13
+ conversationView: { reset(): void };
14
+ conversationSession: ComposerChatSession;
15
+ isCurrentComposerScope(scope: ComposerScope): boolean;
16
+ applyConversationChrome(): void;
17
+ renderSessions(): void;
18
+ }
19
+
20
+ export interface ChatRequestController {
21
+ prepareView(attempt: ComposerSubmissionAttempt): void;
22
+ postChatMessage: RuntimeWebClient["postChatMessage"];
23
+ send(attempt: ComposerChatAttempt): Promise<string>;
24
+ activate(attempt: ComposerSubmissionAttempt, requestId: string): void;
25
+ stopRequest: RuntimeWebClient["stopChatRequest"];
26
+ }
27
+
28
+ export declare function createChatRequestController(options: ChatRequestControllerOptions): ChatRequestController;
@@ -1,79 +1,47 @@
1
+ import { ComposerSubmissionRefused, isDefiniteSubmissionRefusal } from "./composer-submission-lifecycle.js";
2
+
3
+ /** Request effects use an immutable captured payload, never the currently visible draft. */
1
4
  export function createChatRequestController({
2
- state,
3
- client,
4
- sessionQueue,
5
- conversationView,
6
- conversationSession,
7
- attachments,
8
- currentComposerScope,
9
- isCurrentComposerScope,
10
- rememberModelSelection,
11
- applyConversationChrome,
12
- renderSessions,
13
- renderAttachments,
14
- getToolPermissionMode,
15
- getModelPreference,
16
- clearQueueRecovery,
17
- reportQueueFailure,
5
+ client, conversationView, conversationSession, isCurrentComposerScope,
6
+ applyConversationChrome, renderSessions,
18
7
  }) {
19
- function postChatMessage(request) {
20
- return client.postChatMessage(request);
21
- }
22
-
23
- async function sendMessage(text) {
24
- conversationSession.ensureSession();
25
- const scope = currentComposerScope();
8
+ const optimisticRows = new WeakMap();
9
+ function prepareView(attempt) {
10
+ if (!isCurrentComposerScope(attempt.payload.scope)) return;
26
11
  conversationView.reset();
27
- rememberModelSelection();
28
12
  applyConversationChrome();
29
13
  renderSessions();
14
+ optimisticRows.set(attempt, conversationSession.appendLocalUserMessage(attempt.payload));
15
+ }
30
16
 
31
- const submittedAttachments = [...state.pendingAttachments];
32
- attachments.invalidateCompletions();
33
- state.pendingAttachments = [];
34
- renderAttachments();
35
-
36
- conversationSession.appendLocalUserMessage({
37
- text,
38
- attachments: submittedAttachments,
39
- });
40
-
41
- let requestId;
42
- try {
43
- requestId = await postChatMessage({
44
- text,
45
- attachments: submittedAttachments,
46
- environmentId: scope.environmentId,
47
- sessionId: scope.sessionId,
48
- agentMode: state.agentMode,
49
- toolPermissionMode: getToolPermissionMode(),
50
- modelPreference: getModelPreference(),
51
- });
52
- } catch (error) {
53
- if (isCurrentComposerScope(scope)) {
54
- state.pendingAttachments = [
55
- ...submittedAttachments,
56
- ...state.pendingAttachments,
57
- ];
58
- renderAttachments();
59
- }
17
+ async function postChatMessage(request) {
18
+ try { return await client.postChatMessage(request); }
19
+ catch (error) {
20
+ if (hasDefiniteChatRejection(error))
21
+ throw new ComposerSubmissionRefused(error.message, { cause: error });
60
22
  throw error;
61
23
  }
24
+ }
62
25
 
63
- try {
64
- const rebound = sessionQueue.rebindBlocked(scope, requestId);
65
- if (rebound) clearQueueRecovery(scope);
66
- } catch (error) {
67
- reportQueueFailure(
68
- scope,
69
- `The request started, but the remaining Send next queue is paused: ${
70
- error instanceof Error ? error.message : String(error)
71
- }`,
72
- );
73
- }
26
+ async function send(attempt) {
27
+ try { return await postChatMessage({ ...attempt.payload, ...attempt.payload.scope, ...attempt.settings }); }
28
+ catch (error) {
29
+ const removeLocalRow = optimisticRows.get(attempt);
30
+ if (isDefiniteSubmissionRefusal(error) && typeof removeLocalRow === "function") removeLocalRow();
31
+ throw error;
32
+ } finally { optimisticRows.delete(attempt); }
33
+ }
74
34
 
75
- conversationSession.activateRequestForScope(scope, requestId);
35
+ function hasDefiniteChatRejection(error) {
36
+ if (["unsupported_tool_permission_mode", "full_plus_not_supported"].includes(error?.code)) return true;
37
+ return Number.isFinite(error?.status) && error.status >= 400 && error.status < 500;
76
38
  }
77
39
 
78
- return { postChatMessage, sendMessage, stopRequest: (scope) => client.stopChatRequest(scope) };
40
+ return {
41
+ prepareView,
42
+ postChatMessage,
43
+ send,
44
+ activate: (attempt, requestId) => conversationSession.activateRequestForScope(attempt.payload.scope, requestId),
45
+ stopRequest: (scope) => client.stopChatRequest(scope),
46
+ };
79
47
  }
@@ -1,33 +1,11 @@
1
- export type ComposerAttachment = Record<string, unknown> & {
2
- id?: string;
3
- kind?: string;
4
- name?: string;
5
- mimeType?: string;
6
- sessionId?: string;
7
- storageRef?: string;
8
- environment?: string;
9
- };
1
+ import type { ComposerAttachment, ComposerDraft } from "./composer-drafts.js";
2
+ export type { ComposerAttachment } from "./composer-drafts.js";
10
3
 
11
- export type ComposerUploadFile = Blob & {
12
- name?: string;
13
- };
14
-
15
- export interface ComposerAttachmentsState {
16
- currentSessionId: string;
17
- pendingAttachments: ComposerAttachment[];
18
- pendingAttachmentUploadCounts: Map<number, number>;
19
- composerAttachmentGeneration: number;
20
- }
4
+ export type ComposerUploadFile = Blob & { name?: string };
21
5
 
22
6
  export interface ComposerAttachmentsDom {
23
- attachmentButton: {
24
- disabled: boolean;
25
- title: string;
26
- };
27
- attachmentPreview: {
28
- innerHTML: string;
29
- appendChild(child: unknown): unknown;
30
- };
7
+ attachmentButton: { disabled: boolean; title: string };
8
+ attachmentPreview: { innerHTML: string; appendChild(child: HTMLElement): unknown };
31
9
  }
32
10
 
33
11
  export interface ComposerAttachmentsShell {
@@ -62,17 +40,18 @@ export interface ComposerAttachmentControlEvent {
62
40
  }
63
41
 
64
42
  export interface ComposerAttachmentsControllerOptions {
65
- state: ComposerAttachmentsState;
43
+ getDraft(): ComposerDraft;
44
+ canDeleteAttachment?(attachment: ComposerAttachment): boolean;
66
45
  dom: ComposerAttachmentsDom;
67
46
  shell: ComposerAttachmentsShell;
68
47
  client: ComposerAttachmentsClient;
69
- selectedEnvironmentId: () => string;
70
- selectedModelSupportsImageInput: () => boolean;
71
- ensureSession: () => void;
72
- onSendStateChange: () => void;
73
- onControlEvent: (event: ComposerAttachmentControlEvent) => void;
74
- isComposerAvailable?: () => boolean;
75
- isComposerVisible?: () => boolean;
48
+ selectedEnvironmentId(): string;
49
+ selectedModelSupportsImageInput(): boolean;
50
+ ensureSession(): void;
51
+ onSendStateChange(): void;
52
+ onControlEvent(event: ComposerAttachmentControlEvent): void;
53
+ isComposerAvailable?(): boolean;
54
+ isComposerVisible?(): boolean;
76
55
  }
77
56
 
78
57
  export interface ComposerAttachmentsController {
@@ -80,14 +59,10 @@ export interface ComposerAttachmentsController {
80
59
  clear(options?: { cleanup?: boolean }): void;
81
60
  cleanup(attachments: readonly ComposerAttachment[]): void;
82
61
  deletePending(attachment: ComposerAttachment): Promise<void>;
83
- invalidateCompletions(): void;
84
62
  previewUrl(attachment: ComposerAttachment): string;
85
63
  removeUnsupportedImages(): void;
86
64
  render(): void;
87
- setUploadInProgress(uploading: boolean, generation?: number): void;
88
65
  upload(file: ComposerUploadFile): Promise<void>;
89
66
  }
90
67
 
91
- export declare function createComposerAttachmentsController(
92
- options: ComposerAttachmentsControllerOptions,
93
- ): ComposerAttachmentsController;
68
+ export declare function createComposerAttachmentsController(options: ComposerAttachmentsControllerOptions): ComposerAttachmentsController;
@@ -5,7 +5,8 @@ import {
5
5
  import { escapeHtml, textOf } from "../lib/text-format.js";
6
6
 
7
7
  export function createComposerAttachmentsController({
8
- state,
8
+ getDraft,
9
+ canDeleteAttachment = () => true,
9
10
  dom,
10
11
  shell,
11
12
  client,
@@ -31,7 +32,7 @@ export function createComposerAttachmentsController({
31
32
  const storageRef = textOf(attachment.storageRef).trim();
32
33
  const id = textOf(attachment.id).trim();
33
34
  const mimeType = textOf(attachment.mimeType).trim().toLowerCase();
34
- const sessionId = attachmentSessionId(attachment) || state.currentSessionId;
35
+ const sessionId = attachmentSessionId(attachment) || getDraft().scope.sessionId;
35
36
  if (!storageRef || !id || !mimeType || !sessionId) return "";
36
37
  return client.attachmentPreviewUrl({
37
38
  environmentId: attachmentEnvironmentId(attachment),
@@ -48,6 +49,7 @@ export function createComposerAttachmentsController({
48
49
  const mimeType = textOf(attachment.mimeType).trim();
49
50
  const sessionId = attachmentSessionId(attachment);
50
51
  if (!storageRef || !id || !mimeType || !sessionId) return;
52
+ if (!canDeleteAttachment(attachment)) return;
51
53
  try {
52
54
  await client.deleteAttachment({
53
55
  environmentId: attachmentEnvironmentId(attachment),
@@ -70,43 +72,7 @@ export function createComposerAttachmentsController({
70
72
  for (const attachment of attachments) void deletePending(attachment);
71
73
  }
72
74
 
73
- function activeUploadCount() {
74
- return (
75
- state.pendingAttachmentUploadCounts.get(
76
- state.composerAttachmentGeneration,
77
- ) ?? 0
78
- );
79
- }
80
-
81
- function pruneUploadCounts() {
82
- for (const generation of state.pendingAttachmentUploadCounts.keys()) {
83
- if (generation !== state.composerAttachmentGeneration) {
84
- state.pendingAttachmentUploadCounts.delete(generation);
85
- }
86
- }
87
- }
88
-
89
- function invalidateCompletions() {
90
- state.composerAttachmentGeneration += 1;
91
- pruneUploadCounts();
92
- onSendStateChange();
93
- }
94
-
95
- function setUploadInProgress(uploading, generation) {
96
- const uploadGeneration =
97
- Number.isFinite(generation) && generation >= 0
98
- ? generation
99
- : state.composerAttachmentGeneration;
100
- const nextCount = Math.max(
101
- 0,
102
- (state.pendingAttachmentUploadCounts.get(uploadGeneration) ?? 0) +
103
- (uploading ? 1 : -1),
104
- );
105
- if (nextCount === 0)
106
- state.pendingAttachmentUploadCounts.delete(uploadGeneration);
107
- else state.pendingAttachmentUploadCounts.set(uploadGeneration, nextCount);
108
- onSendStateChange();
109
- }
75
+ function activeUploadCount() { return getDraft().uploading; }
110
76
 
111
77
  function render() {
112
78
  if (!isComposerVisible()) return;
@@ -118,7 +84,7 @@ export function createComposerAttachmentsController({
118
84
  ? "Attach a file or image"
119
85
  : "Attach a document (this model does not accept images)";
120
86
  dom.attachmentPreview.innerHTML = "";
121
- for (const attachment of state.pendingAttachments) {
87
+ for (const attachment of getDraft().attachments) {
122
88
  const chip = document.createElement("span");
123
89
  chip.className = "attachment-chip";
124
90
  chip.innerHTML = `
@@ -126,7 +92,7 @@ export function createComposerAttachmentsController({
126
92
  <button type="button" aria-label="Remove attachment">×</button>
127
93
  `;
128
94
  chip.querySelector("button")?.addEventListener("click", () => {
129
- state.pendingAttachments = state.pendingAttachments.filter(
95
+ getDraft().attachments = getDraft().attachments.filter(
130
96
  (item) => item.id !== attachment.id,
131
97
  );
132
98
  void deletePending(attachment);
@@ -139,7 +105,7 @@ export function createComposerAttachmentsController({
139
105
 
140
106
  function removeUnsupportedImages() {
141
107
  if (selectedModelSupportsImageInput()) return;
142
- const unsupported = state.pendingAttachments.filter(
108
+ const unsupported = getDraft().attachments.filter(
143
109
  (attachment) =>
144
110
  attachment.kind === "image" ||
145
111
  isImageAttachmentMimeType(attachment.mimeType),
@@ -148,7 +114,7 @@ export function createComposerAttachmentsController({
148
114
  const unsupportedIds = new Set(
149
115
  unsupported.map((attachment) => attachment.id),
150
116
  );
151
- state.pendingAttachments = state.pendingAttachments.filter(
117
+ getDraft().attachments = getDraft().attachments.filter(
152
118
  (attachment) => !unsupportedIds.has(attachment.id),
153
119
  );
154
120
  cleanup(unsupported);
@@ -158,19 +124,15 @@ export function createComposerAttachmentsController({
158
124
  }
159
125
 
160
126
  function clear(options = {}) {
161
- invalidateCompletions();
162
- if (state.pendingAttachments.length === 0) return;
163
- const attachments = [...state.pendingAttachments];
164
- state.pendingAttachments = [];
127
+ const draft = getDraft();
128
+ const attachments = draft.clearAttachments();
165
129
  render();
166
130
  if (options.cleanup !== false) cleanup(attachments);
167
131
  }
168
132
 
169
- function canRetainUploadedAttachment(scope) {
170
- if (state.currentSessionId !== scope.sessionId) return false;
171
- if (selectedEnvironmentId() !== scope.environmentId) return false;
172
- if (state.composerAttachmentGeneration !== scope.generation) return false;
173
- if (!scope.imageAttachment) return true;
133
+ function canRetainUploadedAttachment(draft, imageAttachment) {
134
+ if (!imageAttachment) return true;
135
+ if (draft !== getDraft()) return true;
174
136
  return selectedModelSupportsImageInput();
175
137
  }
176
138
 
@@ -184,15 +146,14 @@ export function createComposerAttachmentsController({
184
146
  if (imageAttachment && !selectedModelSupportsImageInput()) {
185
147
  throw new Error("Selected model does not support image input");
186
148
  }
187
- if (state.pendingAttachments.length >= 4) {
149
+ if (getDraft().attachments.length + getDraft().uploading >= 4) {
188
150
  throw new Error("You can attach up to 4 files to one request");
189
151
  }
190
152
  ensureSession();
191
- const uploadEnvironmentId = selectedEnvironmentId();
192
- const uploadSessionId = state.currentSessionId;
193
- invalidateCompletions();
194
- const uploadGeneration = state.composerAttachmentGeneration;
195
- setUploadInProgress(true, uploadGeneration);
153
+ const draft = getDraft();
154
+ const uploadEnvironmentId = draft.scope.environmentId;
155
+ const uploadSessionId = draft.scope.sessionId;
156
+ const uploadGeneration = draft.startUpload();
196
157
  try {
197
158
  const uploadedAttachment = await client.uploadAttachment({
198
159
  environmentId: uploadEnvironmentId,
@@ -206,20 +167,18 @@ export function createComposerAttachmentsController({
206
167
  sessionId: uploadSessionId,
207
168
  environment: uploadEnvironmentId,
208
169
  };
209
- const uploadScope = {
210
- sessionId: uploadSessionId,
211
- environmentId: uploadEnvironmentId,
212
- generation: uploadGeneration,
213
- imageAttachment,
214
- };
215
- if (!canRetainUploadedAttachment(uploadScope)) {
170
+ if (!canRetainUploadedAttachment(draft, imageAttachment)) {
171
+ void deletePending(attachment);
172
+ return;
173
+ }
174
+ if (!draft.acceptUpload(uploadGeneration, attachment)) {
216
175
  void deletePending(attachment);
217
176
  return;
218
177
  }
219
- state.pendingAttachments = [...state.pendingAttachments, attachment];
220
178
  render();
221
179
  } finally {
222
- setUploadInProgress(false, uploadGeneration);
180
+ draft.finishUpload(uploadGeneration);
181
+ onSendStateChange();
223
182
  }
224
183
  }
225
184
 
@@ -228,11 +187,9 @@ export function createComposerAttachmentsController({
228
187
  clear,
229
188
  cleanup,
230
189
  deletePending,
231
- invalidateCompletions,
232
190
  previewUrl,
233
191
  removeUnsupportedImages,
234
192
  render,
235
- setUploadInProgress,
236
193
  upload,
237
194
  };
238
195
  }
@@ -0,0 +1,27 @@
1
+ import type { ComposerDraft } from "./composer-drafts.js";
2
+
3
+ export interface ComposerInputSurface {
4
+ value: string;
5
+ readonly style: { height: string };
6
+ readonly scrollHeight: number;
7
+ focus(): void;
8
+ }
9
+
10
+ export interface ComposerDraftInput extends ComposerInputSurface {
11
+ addEventListener?(type: "input", listener: () => void): void;
12
+ }
13
+
14
+ export interface ComposerDraftView {
15
+ surface: ComposerInputSurface;
16
+ current(): ComposerDraft;
17
+ display(): ComposerDraft;
18
+ saveDisplayed(): void;
19
+ refresh(draft: ComposerDraft): void;
20
+ detach(): void;
21
+ }
22
+
23
+ export declare function createComposerDraftView(options: {
24
+ input: ComposerDraftInput;
25
+ getDraft(): ComposerDraft;
26
+ isVisible?(): boolean;
27
+ }): ComposerDraftView;