@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
@@ -36,6 +36,7 @@ export function createRuntimeWebClient({
36
36
  getEnvironmentId,
37
37
  fetchImpl = fetch,
38
38
  origin = window.location.origin,
39
+ onMemoryDeleted,
39
40
  }) {
40
41
  const environmentQuery = (environmentId = getEnvironmentId()) =>
41
42
  encodeURIComponent(environmentId);
@@ -98,6 +99,7 @@ export function createRuntimeWebClient({
98
99
  requestApi,
99
100
  getEnvironmentId,
100
101
  environmentQuery,
102
+ onMemoryDeleted,
101
103
  });
102
104
 
103
105
  return {
@@ -0,0 +1,32 @@
1
+ import { createSessionComposerQueue } from "../lib/session-composer-queue.js";
2
+
3
+ /** Reads use the latest server projection. Mutations are serialized by the server. */
4
+ export function createServerComposerQueue(storage) {
5
+ const ownerId = createWindowIdentity();
6
+ const view = () => createSessionComposerQueue({ storage: {
7
+ getItem: () => storage.snapshot()?.queue || null,
8
+ setItem() { throw new Error("Queue writes require server acknowledgement."); },
9
+ } });
10
+ const change = (scope, action, input = {}) =>
11
+ storage.execute({ kind: "queue", scope, action, ownerId, ...input });
12
+ return {
13
+ list: (scope) => view().list(scope),
14
+ peek: (scope) => view().peek(scope),
15
+ getBlockedRelease: (scope) => view().getBlockedRelease(scope),
16
+ claimBlockedRelease: (scope, releaseToken, options = {}) => change(scope, "claim", { releaseToken, takeover: options.takeover === true }),
17
+ beginBlockedSend: (scope, releaseToken) => change(scope, "begin", { releaseToken }),
18
+ markBlockedUncertain: (scope, releaseToken) => change(scope, "uncertain", { releaseToken }),
19
+ enqueue: (scope, item) => change(scope, "enqueue", { item }),
20
+ releaseForTerminal: (scope, requestId) => change(scope, "release", { requestId }),
21
+ bindReleasedSuccess: (scope, releaseToken, requestId) => change(scope, "bind", { releaseToken, requestId }),
22
+ rebindBlocked: (scope, requestId) => change(scope, "rebind", { requestId }),
23
+ updateBlockedRelease: (scope, releaseToken, item) => change(scope, "update", { releaseToken, item }),
24
+ refresh: () => storage.refresh(),
25
+ };
26
+ }
27
+
28
+ function createWindowIdentity() {
29
+ if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();
30
+ // getRandomValues is also available on HTTP LAN origins, unlike randomUUID.
31
+ return [...globalThis.crypto.getRandomValues(new Uint32Array(4))].join("-");
32
+ }
@@ -8,11 +8,11 @@ function sessionIds(value) {
8
8
  function readEnvironments(storage) {
9
9
  try {
10
10
  const value = JSON.parse(storage.getItem(storageKey) || "{}");
11
- if (!value || typeof value !== "object") return {};
12
- if (Array.isArray(value)) return {};
13
- return value;
11
+ if (!value || typeof value !== "object") return Object.create(null);
12
+ if (Array.isArray(value)) return Object.create(null);
13
+ return Object.assign(Object.create(null), value);
14
14
  } catch {
15
- return {};
15
+ return Object.create(null);
16
16
  }
17
17
  }
18
18
 
@@ -36,7 +36,7 @@ export function createSessionSidebarPreferences(storage) {
36
36
  configurable: true,
37
37
  writable: true,
38
38
  });
39
- storage.setItem(storageKey, JSON.stringify(environments));
39
+ return storage.setItem(storageKey, JSON.stringify(environments));
40
40
  },
41
41
  };
42
42
  }
@@ -0,0 +1,116 @@
1
+ /** The in-memory view is a projection; only the server acknowledges persistence. */
2
+ export function createWorkspaceStateStorage({ fetchImpl = fetch, onError = () => {} } = {}) {
3
+ let snapshot = null;
4
+ const lanes = new Map();
5
+ const failures = new Map();
6
+ const pending = [];
7
+ const listeners = new Set();
8
+
9
+ async function request(input) {
10
+ let response;
11
+ let result;
12
+ try {
13
+ response = await fetchImpl("/web-ui-state", input ? {
14
+ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(input),
15
+ } : { cache: "no-store" });
16
+ result = await response.json();
17
+ } catch (error) { throw uncertainMutationError(error, input); }
18
+ if (!response.ok) throw workspaceResponseFailure(response, result, input);
19
+ if (result.state?.version !== 1 || !Number.isSafeInteger(result.state.revision) ||
20
+ !result.state.preferences || typeof result.state.queue !== "string")
21
+ throw uncertainMutationError(new Error("The server returned invalid workspace state."), input);
22
+ if (!snapshot || result.state.revision >= snapshot.revision) snapshot = result.state;
23
+ return result.result;
24
+ }
25
+ function laneFor(input) {
26
+ if (input.kind === "preference") return `preference:${input.key}`;
27
+ if (input.kind === "queue") return `queue:${JSON.stringify([input.scope.environmentId, input.scope.sessionId])}`;
28
+ return input.kind;
29
+ }
30
+ function report(error, lane) {
31
+ failures.set(lane, error);
32
+ onError(error);
33
+ }
34
+ function execute(input, completed = () => {}) {
35
+ const lane = laneFor(input);
36
+ const result = (lanes.get(lane) || Promise.resolve()).then(async () => {
37
+ if (failures.has(lane)) throw failures.get(lane);
38
+ const previousPreferences = JSON.stringify(snapshot?.preferences);
39
+ const value = await request(input);
40
+ try {
41
+ completed();
42
+ if (JSON.stringify(snapshot.preferences) !== previousPreferences)
43
+ for (const listener of listeners) listener();
44
+ } catch (error) { throw uncertainMutationError(error, input); }
45
+ return value;
46
+ });
47
+ // Ordering/failure belongs to this preference or queue scope. The acknowledged
48
+ // server snapshot remains shared; an unrelated failure is never permission to retry.
49
+ lanes.set(lane, result.then(() => undefined, (error) => report(error, lane)));
50
+ return result;
51
+ }
52
+ function getItem(key) {
53
+ const queued = pending.findLast((entry) => entry.key === key);
54
+ if (queued) return queued.value;
55
+ return snapshot?.preferences[key] ?? null;
56
+ }
57
+ function write(key, value) {
58
+ if (!snapshot) throw new Error("Workspace settings have not loaded.");
59
+ if (failures.has(`preference:${key}`)) {
60
+ const rejected = Promise.reject(failures.get(`preference:${key}`));
61
+ void rejected.catch(() => {});
62
+ return rejected;
63
+ }
64
+ const before = getItem(key);
65
+ if (before === value) return Promise.resolve();
66
+ const entry = { key, before, value };
67
+ pending.push(entry);
68
+ const discardPending = () => {
69
+ const index = pending.indexOf(entry);
70
+ if (index >= 0) pending.splice(index, 1);
71
+ };
72
+ const result = execute({ kind: "preference", ...entry }, discardPending);
73
+ void result.catch(() => {
74
+ discardPending();
75
+ for (const listener of listeners) listener();
76
+ });
77
+ return result;
78
+ }
79
+ return {
80
+ getItem,
81
+ setItem: (key, value) => write(key, String(value)),
82
+ removeItem: (key) => write(key, null),
83
+ execute,
84
+ async flush() {
85
+ await Promise.all(lanes.values());
86
+ if (failures.size) throw failures.values().next().value;
87
+ },
88
+ async refresh() {
89
+ try {
90
+ const previous = snapshot?.revision;
91
+ await request();
92
+ if (snapshot.revision !== previous) for (const listener of listeners) listener();
93
+ } catch (error) { report(error, "refresh"); throw error; }
94
+ },
95
+ subscribe(listener) { listeners.add(listener); return () => listeners.delete(listener); },
96
+ snapshot: () => snapshot,
97
+ error: () => failures.values().next().value ?? null,
98
+ };
99
+ }
100
+
101
+ function uncertainMutationError(error, input) {
102
+ if (!input) return error;
103
+ const failure = error instanceof Error ? error : new Error(String(error));
104
+ // An absent acknowledgement cannot prove a POST had no durable effect.
105
+ failure.workspaceMutationMayHaveCommitted = true;
106
+ return failure;
107
+ }
108
+
109
+ function workspaceResponseFailure(response, result, input) {
110
+ const error = new Error(result.message || "Workspace state is unavailable.");
111
+ error.status = response.status;
112
+ error.code = result.error;
113
+ if (response.status < 500) return error;
114
+ // A server failure may follow durable publication, such as lock cleanup failure.
115
+ return uncertainMutationError(error, input);
116
+ }
@@ -0,0 +1,27 @@
1
+ import { createWorkspaceStateStorage } from "./workspace-state-storage.js";
2
+ import { createServerComposerQueue } from "./server-composer-queue.js";
3
+ import { acknowledgeWorkspaceStorage, showWorkspaceStorageFailure } from "../components/workspace-storage-notice.js";
4
+ import { createStartupScreen } from "../components/startup-screen.js";
5
+
6
+ let storage;
7
+ let queue;
8
+ export const workspaceStorage = () => storage;
9
+ export const workspaceQueue = () => queue;
10
+ export function observeWorkspaceStateChange(message) {
11
+ if (message.type !== "workspace_changed" || !message.resources?.includes("client-state")) return;
12
+ void storage?.refresh().catch(showWorkspaceStorageFailure);
13
+ }
14
+
15
+ export async function initializeWorkspaceState() {
16
+ storage = createWorkspaceStateStorage({ onError: showWorkspaceStorageFailure });
17
+ try {
18
+ await storage.refresh();
19
+ await acknowledgeWorkspaceStorage(storage);
20
+ queue = createServerComposerQueue(storage);
21
+ window.addEventListener("focus", () => void storage.refresh().catch(showWorkspaceStorageFailure));
22
+ document.addEventListener("visibilitychange", () => {
23
+ if (document.visibilityState === "visible") void storage.refresh().catch(showWorkspaceStorageFailure);
24
+ });
25
+ return storage;
26
+ } catch (error) { createStartupScreen().fail(error); throw error; }
27
+ }
@@ -1,16 +1,16 @@
1
+ import { canChooseReasoning } from "./lib/reasoning-controls.js";
2
+ import { createComposerFeature } from "./controllers/composer-feature.js";
3
+ import { createComposerDrafts } from "./controllers/composer-drafts.js";
4
+ import { createComposerDraftView } from "./controllers/composer-draft-view.js";
5
+ import { workspaceQueue } from "./services/workspace-state.js";
1
6
  import { createAppState } from "./app-state.js";
2
7
  import { createConversationViewFeature } from "./controllers/conversation-view-feature.js";
3
8
  import { createConversationSessionController } from "./controllers/conversation-session-controller.js";
4
- import { createChatRequestController } from "./controllers/chat-request-controller.js";
5
- import { createComposerQueueController } from "./controllers/composer-queue-controller.js";
6
- import { createComposerSubmitController } from "./controllers/composer-submit-controller.js";
7
- import { createComposerAttachmentsController } from "./controllers/composer-attachments-controller.js";
8
9
  import { createRealtimeEventController } from "./controllers/realtime-event-controller.js";
9
10
  import { createSteerController } from "./controllers/steer-controller.js";
10
11
  import { createToolApprovalController } from "./controllers/tool-approval-controller.js";
11
12
  import { createToolApprovalCard } from "./components/tool-approval-card.js";
12
13
  import { createComposerActions } from "./components/composer-actions.js";
13
- import { createSessionComposerQueue } from "./lib/session-composer-queue.js";
14
14
  import { normalizeRealtimeMessage } from "./lib/realtime-message.js";
15
15
  import { createSparkChatResults } from "./components/spark-chat/results.js";
16
16
  import { sparkMessageStatus, sparkWorkingStatus } from "./lib/spark-chat-presentation.js";
@@ -23,24 +23,29 @@ export function createSparkChatConversation({
23
23
  dom, client, shell, getEnvironmentId, getConfiguration, isOpen, isConnected,
24
24
  getSubmissionBlock, scrollBehavior, refresh, onReadState, onRender,
25
25
  onOpenSchedule = () => {}, onOpenModelSettings = () => {},
26
- sendRealtime, onComposerStateChange = () => {}, storage = localStorage,
26
+ sendRealtime, onComposerStateChange = () => {}, sessionQueue = workspaceQueue(),
27
27
  captureHandoffNavigation, onHandoffOpened,
28
28
  }) {
29
29
  const state = createAppState();
30
- const sessionQueue = createSessionComposerQueue({ storage });
30
+ const drafts = createComposerDrafts();
31
+ const draftView = createComposerDraftView({ input: dom.composerInput,
32
+ getDraft: () => drafts.open({ environmentId: getEnvironmentId(), sessionId: state.currentSessionId }), isVisible: isOpen });
33
+ drafts.subscribe(draftView.refresh);
34
+ draftView.display();
31
35
  const mascotActivity = createSparkMascotActivity({ state, dom, isConnected });
32
36
  let session;
33
37
  let view;
34
38
  let realtime;
35
39
  let queue;
36
40
  let submit;
41
+ let attachments;
37
42
  const status = (text, busy = false) => {
38
43
  dom.messagesList.setAttribute("aria-busy", String(busy));
39
44
  dom.messageStatusRegion.textContent = sparkMessageStatus(text);
40
45
  };
41
46
  const render = () => { view?.render(); mascotActivity.render(); onRender?.(); };
42
47
  const renderActivityStatus = () => { view?.renderActivityStatus(); mascotActivity.render(); };
43
- const updateSendState = () => { submit?.updateSendState(); mascotActivity.render(); onComposerStateChange(state.composerSending); };
48
+ const updateSendState = () => { draftView.display(); submit?.updateSendState(); mascotActivity.render(); onComposerStateChange(state.composerSending); };
44
49
  const recordControlEvent = (event) => realtime?.recordControlEvent(event);
45
50
  const getToolPermissionMode = () => getConfiguration()?.toolPermissionMode || "ask";
46
51
  const getModelPreference = () => {
@@ -56,13 +61,6 @@ export function createSparkChatConversation({
56
61
  onAccepted: (message) => session.insertSteerMessage(message),
57
62
  });
58
63
  const actions = createComposerActions({ dom, onSendNext: () => submit.dispatch("send_next") });
59
- const attachments = createComposerAttachmentsController({
60
- state, dom, shell, client, selectedEnvironmentId: getEnvironmentId,
61
- selectedModelSupportsImageInput: () => getConfiguration()?.supportsImageInput === true,
62
- ensureSession: () => session.ensureSession(), onSendStateChange: updateSendState,
63
- onControlEvent: recordControlEvent,
64
- isComposerAvailable: () => !getSubmissionBlock(), isComposerVisible: isOpen,
65
- });
66
64
  const approvals = createToolApprovalController({
67
65
  state, selectedEnvironmentId: getEnvironmentId, sendRealtime,
68
66
  renderMessages: render, recordControlEvent, createCard: createToolApprovalCard,
@@ -88,7 +86,7 @@ export function createSparkChatConversation({
88
86
  getPendingApproval: approvals.pendingEvent, getPendingApprovals: approvals.pendingEvents,
89
87
  createApprovalCard: approvals.createCard,
90
88
  copyText: (text) => navigator.clipboard.writeText(text),
91
- notify: shell.showToast, resolveAttachmentUrl: attachments.previewUrl,
89
+ notify: shell.showToast, resolveAttachmentUrl: (file) => attachments.previewUrl(file),
92
90
  onOpenSchedule, canOpenSchedule: () => client.supportsSchedules?.() === true,
93
91
  scrollBehavior,
94
92
  sparkActions: createSparkHandoffActions({
@@ -113,41 +111,32 @@ export function createSparkChatConversation({
113
111
  sessionQueue, conversationView: view, selectedEnvironmentId: getEnvironmentId,
114
112
  // Reading belongs to actual visible rows in the popup, never to session activation.
115
113
  isConversationVisible: () => false,
116
- clearPendingAttachments() {}, applyConversationChrome() {}, applyModelSelection() {}, renderSessions() {},
114
+ applyConversationChrome() {}, applyModelSelection() {}, renderSessions() {},
117
115
  renderMessages: render, updateComposerSendState: updateSendState, setMessageStatus: status,
118
116
  sendRealtime, handleRealtimeMessage: (message) => realtime.handle(message),
119
117
  recordEvent: (message) => realtime.recordEvent(message), recordControlEvent,
120
118
  reportQueueFailure: (...args) => queue.reportFailure(...args),
121
119
  drainQueuedMessage: (...args) => queue.drain(...args),
122
- suspendQueueRecovery: () => queue.suspendRecoveryForNavigation(),
120
+ suspendQueueRecovery: (canNavigate) => queue.suspendRecoveryForNavigation(canNavigate),
123
121
  recoverBlockedQueue: (...args) => queue.recoverForManualSend(...args),
124
122
  isCurrentComposerScope: isScopeCurrent,
125
123
  createSessionId() { throw new Error("SPARK conversation is not ready yet."); },
126
124
  });
127
- const requests = createChatRequestController({
128
- state, client, sessionQueue, conversationView: view, conversationSession: session,
129
- attachments, currentComposerScope: scope, isCurrentComposerScope: isScopeCurrent,
130
- rememberModelSelection() {}, applyConversationChrome() {}, renderSessions() {},
131
- renderAttachments: attachments.render, getToolPermissionMode, getModelPreference,
132
- clearQueueRecovery: (...args) => queue.clearRecovery(...args),
133
- reportQueueFailure: (...args) => queue.reportFailure(...args),
134
- });
135
- queue = createComposerQueueController({
136
- state, dom, queue: sessionQueue, selectedEnvironmentId: getEnvironmentId,
137
- getToolPermissionMode, getModelPreference, rememberModelSelection() {}, attachments,
138
- updateSendState, postChatMessage: requests.postChatMessage,
139
- appendLocalUserMessage: session.appendLocalUserMessage,
140
- activateRequestForScope: session.activateRequestForScope,
141
- renderMessages: render, setMessageStatus: status, recordControlEvent,
142
- resizeComposer: () => submit.resize(),
143
- });
144
- submit = createComposerSubmitController({
145
- state, dom, composerActions: actions, attachments, queue, steer: steer.steer,
146
- chatRequests: requests, conversationSession: session,
147
- selectedEnvironmentId: getEnvironmentId, setMessageStatus: status,
148
- getSubmissionBlock, onSubmissionBlocked: (block) => shell.showToast(block.message || "SPARK is not ready.", "failed"),
149
- isComposerVisible: isOpen,
125
+ const composer = createComposerFeature({
126
+ state, dom: { ...dom, composerInput: draftView.surface }, shell, client, sessionQueue,
127
+ drafts, getDraft: draftView.current, conversationSession: session, conversationView: view,
128
+ getEnvironmentId, ensureSession: () => session.ensureSession(),
129
+ getSettings: () => ({ agentMode: state.agentMode, toolPermissionMode: getToolPermissionMode(), modelPreference: getModelPreference() }),
130
+ steer: steer.steer, composerActions: actions,
131
+ selectedModelSupportsImageInput: () => getConfiguration()?.supportsImageInput === true,
132
+ isComposerAvailable: () => !getSubmissionBlock(), getSubmissionBlock,
133
+ onSubmissionBlocked: (block) => shell.showToast(block.message || "SPARK is not ready.", "failed"),
134
+ isVisible: isOpen, renderSessions() {}, renderMessages: render, applyConversationChrome() {},
135
+ setMessageStatus: status, recordControlEvent, onChange: () => onComposerStateChange(state.composerSending),
150
136
  });
137
+ attachments = composer.attachments;
138
+ queue = composer.queue;
139
+ submit = composer.submit;
151
140
  realtime = createRealtimeEventController({
152
141
  state, shell, selectedEnvironmentId: getEnvironmentId,
153
142
  handleSteerAcknowledgement: steer.handleAcknowledgement,
@@ -201,16 +190,16 @@ export function createSparkChatConversation({
201
190
  return {
202
191
  state, session, view, attachments, render, handleRealtime, bind, queue,
203
192
  prepareEnvironmentChange: () => queue.prepareRecoveryForNavigation(),
204
- setAgentMode(mode) { state.agentMode = mode; },
193
+ setAgentMode(mode) { if (canChooseReasoning(getConfiguration())) state.agentMode = mode; },
205
194
  update() {
206
195
  state.connected = isConnected();
207
- attachments.render(); updateSendState(); renderActivityStatus();
196
+ draftView.display(); composer.changed(); updateSendState(); renderActivityStatus();
208
197
  if (!state.messages.length) render();
209
198
  },
210
199
  reset() {
211
200
  steer.rejectAll("SPARK environment changed.");
212
- attachments.clear(); session.invalidateEnvironmentLoads(); session.clearCurrentSessionView();
213
- dom.composerInput.value = "";
201
+ draftView.saveDisplayed(); session.invalidateEnvironmentLoads(); session.clearCurrentSessionView();
202
+ draftView.display();
214
203
  },
215
204
  status,
216
205
  };
@@ -122,7 +122,11 @@ export function createSparkChatFeature({ dom, state: appState, client, shell, re
122
122
  });
123
123
  panel.dom.settingsButton.addEventListener("click", openSettings);
124
124
  panel.onToggle((opened) => {
125
- if (!opened) { conversation.view.closeFilePreview(); return; }
125
+ if (!opened) {
126
+ accessRevision += 1;
127
+ conversation.view.closeFilePreview();
128
+ return;
129
+ }
126
130
  if (!isSparkAvailable()) { panel.setOpen(false, { focus: false }); return; }
127
131
  if (!restoringOpen) void open();
128
132
  });
@@ -131,7 +135,7 @@ export function createSparkChatFeature({ dom, state: appState, client, shell, re
131
135
  if (!isSparkAvailable()) return false;
132
136
  const scope = getEnvironmentId();
133
137
  const revision = accessRevision;
134
- try { await sync.refresh({ wait: true }); }
138
+ try { await sync.refresh({ wait: true, consolidated: true }); }
135
139
  catch (error) {
136
140
  if (!canCompleteSparkOpening(scope, revision)) return false;
137
141
  shell.showToast(`SPARK could not be opened: ${error.message}`, "failed");
@@ -219,13 +223,15 @@ export function createSparkChatFeature({ dom, state: appState, client, shell, re
219
223
  const revision = accessRevision;
220
224
  try { if (!configuration) await sync.refresh({ wait: true }); }
221
225
  catch (error) {
222
- if (!canCompleteSparkOpening(scope, revision)) return false;
226
+ if (!canCompleteSparkOpening(scope, revision)) return true;
223
227
  shell.showToast(`SPARK could not be opened: ${error.message}`, "failed");
224
228
  return true;
225
229
  }
226
230
  if (!canCompleteSparkOpening(scope, revision)) return true;
227
231
  if (sessionId !== configuration?.sessionId) return false;
228
- return open(messageId, reference);
232
+ const opened = await open(messageId, reference);
233
+ if (!canCompleteSparkOpening(scope, revision)) return true;
234
+ return opened;
229
235
  },
230
236
  bind() {
231
237
  conversation.bind();
@@ -366,3 +366,19 @@
366
366
  display: none;
367
367
  }
368
368
  }
369
+
370
+ /* The reasoning permission prompt shares the composer's anchored menu surface. */
371
+ .agent-mode-menu.reasoning-override-menu {
372
+ width: min(340px, calc(100vw - 32px));
373
+ padding: 16px;
374
+ }
375
+ .reasoning-override-prompt { display: grid; gap: 12px; }
376
+ .reasoning-override-prompt p { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.55; }
377
+ .reasoning-override-prompt strong { font-size: 13px; }
378
+ .reasoning-override-prompt small { color: var(--muted); font-size: 11px; line-height: 1.5; }
379
+ .reasoning-override-actions { display: grid; gap: 8px; }
380
+ .reasoning-override-actions button { padding: 8px 12px; text-align: left; border: 1px solid var(--line); border-radius: 7px; background: transparent; color: var(--text); font: inherit; font-size: 12px; }
381
+ .reasoning-override-actions button:first-child { color: var(--accent); }
382
+ .reasoning-override-actions button:hover:not(:disabled) { background: var(--panel); }
383
+ .reasoning-override-actions button:disabled { opacity: .5; cursor: default; }
384
+ .reasoning-override-prompt .error-text { color: var(--danger); }
@@ -381,3 +381,11 @@
381
381
  gap: 8px;
382
382
  flex-wrap: wrap;
383
383
  }
384
+
385
+ .plugin-platform-notice {
386
+ margin: 8px 0;
387
+ color: var(--amber);
388
+ font-size: var(--font-size-xs);
389
+ line-height: 1.5;
390
+ overflow-wrap: anywhere;
391
+ }
@@ -37,6 +37,7 @@
37
37
  }
38
38
 
39
39
  .model-plugin-summary-count,
40
+ .model-plugin-platform-note,
40
41
  .model-plugin-global-note {
41
42
  color: var(--muted);
42
43
  font-size: var(--font-size-xs);
@@ -0,0 +1,30 @@
1
+ .collection-consent-dialog .collection-consent-acknowledgment {
2
+ display: flex;
3
+ align-items: flex-start;
4
+ gap: 10px;
5
+ margin-top: 18px;
6
+ color: var(--text);
7
+ font-size: 13px;
8
+ line-height: 1.5;
9
+ cursor: pointer;
10
+ }
11
+ .collection-consent-acknowledgment input[type="checkbox"] {
12
+ appearance: auto;
13
+ flex: 0 0 16px;
14
+ width: 16px;
15
+ height: 16px;
16
+ min-height: 16px;
17
+ margin: 2px 0 0;
18
+ border-radius: 2px;
19
+ accent-color: var(--accent);
20
+ cursor: pointer;
21
+ }
22
+ .collection-consent-acknowledgment span {
23
+ min-width: 0;
24
+ overflow-wrap: anywhere;
25
+ }
26
+ .collection-consent-acknowledgment a {
27
+ color: var(--accent);
28
+ text-decoration: underline;
29
+ text-underline-offset: 2px;
30
+ }
@@ -0,0 +1,23 @@
1
+ .workspace-storage-notice {
2
+ color: var(--text); background: var(--bg); border: 1px solid var(--line);
3
+ border-radius: 12px; padding: 24px; max-width: min(540px, calc(100vw - 40px));
4
+ line-height: 1.6;
5
+ }
6
+ .workspace-storage-notice::backdrop { background: #0009; }
7
+ .workspace-storage-notice h2 { margin-top: 0; }
8
+ .workspace-storage-notice button { margin-top: 8px; }
9
+ .workspace-storage-failure {
10
+ position: fixed; z-index: 10000; bottom: 16px; left: 16px; right: 16px;
11
+ padding: 12px 16px; color: var(--text); background: var(--panel);
12
+ border: 1px solid #ed9b91; border-radius: 8px;
13
+ }
14
+
15
+ .composer-submission-notice {
16
+ grid-column: 1 / -1; width: 100%; color: var(--text-muted); font-size: 12px;
17
+ }
18
+ .composer-submission-notice[hidden] { display: none; }
19
+ .composer-submission-notice > div {
20
+ display: flex; align-items: center; gap: 12px; justify-content: space-between;
21
+ padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px;
22
+ }
23
+ .composer-submission-notice button { flex-shrink: 0; }
@@ -0,0 +1,109 @@
1
+ /* Home-only small-screen summaries. Full live components retain their owners. */
2
+ .home-widget-grid[hidden] { display: none; }
3
+
4
+ .home-widget-dialog {
5
+ width: min(720px, calc(100vw - 32px));
6
+ max-height: calc(100dvh - 40px);
7
+ padding: 0;
8
+ border: 1px solid var(--line-strong);
9
+ border-radius: 12px;
10
+ background: var(--panel);
11
+ color: var(--text);
12
+ }
13
+ .home-widget-dialog[open] { display: flex; flex-direction: column; }
14
+ .home-widget-dialog::backdrop { background: color-mix(in srgb, var(--bg) 78%, transparent); }
15
+ .home-widget-dialog-header {
16
+ display: flex; align-items: center; justify-content: space-between;
17
+ gap: 16px; padding: 14px 20px; border-bottom: 1px solid var(--line); flex: none;
18
+ }
19
+ .home-widget-dialog-header h2 { margin: 0; font-size: var(--font-size-2xl); font-weight: 500; }
20
+ .home-widget-dialog-body { overflow: auto; min-height: 0; padding: 20px; overscroll-behavior: contain; }
21
+ .home-widget-dialog-body > .home-widget-source { width: 100%; margin: 0; }
22
+ .home-widget-dialog .home-panel-rows,
23
+ .home-widget-dialog .system-host-permission-details .system-host-permissions {
24
+ max-height: none; overflow: visible;
25
+ }
26
+ .home-widget-dialog .home-panel { border: 0; border-radius: 0; }
27
+ .home-widget-dialog .home-approval { max-height: none; }
28
+ .home-widget-dialog .home-automation-status { display: block; }
29
+ .home-widget-dialog .home-automation-runs { margin-top: 12px; flex-wrap: wrap; }
30
+
31
+ @media (max-width: 1440px) {
32
+ .home-widgets-compact .home-widget-source:not(.home-widget-expanded) { display: none !important; }
33
+ .home-widgets-compact .home-overview { display: contents; }
34
+ .home-widgets-compact .home-approval-dock { display: none; }
35
+ .home-widgets-compact .home-workspace-body { padding-block: 16px; }
36
+ .home-widgets-compact .home-widget-grid {
37
+ display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 12px; order: 1;
38
+ }
39
+ .home-widgets-compact .home-widget-grid[hidden] { display: none; }
40
+ .home-widget {
41
+ display: flex; flex-direction: column; align-items: stretch; gap: 12px;
42
+ min-width: 0; min-height: 160px; width: 100%; padding: 15px 16px;
43
+ text-align: start; background: var(--panel); color: var(--text);
44
+ border: 1px solid var(--line); border-radius: 10px; box-shadow: none;
45
+ }
46
+ .home-widget:hover { border-color: var(--line-strong); background: var(--panel-soft); }
47
+ .home-widget-heading {
48
+ display: flex; align-items: center; gap: 9px; padding-bottom: 11px;
49
+ border-bottom: 1px solid var(--line); color: var(--text-strong);
50
+ font-size: var(--font-size-lg); font-weight: 500; line-height: 1.4;
51
+ }
52
+ .home-widget-heading-icon {
53
+ display: flex; align-items: center; justify-content: center; flex: none;
54
+ width: 27px; height: 27px; border-radius: 6px; background: var(--control-fill); color: var(--muted);
55
+ }
56
+ .home-widget-heading-icon > svg, .home-widget-heading-icon > img { width: 17px; height: 17px; }
57
+ .home-widget svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
58
+ .home-widget [data-widget-label] { flex: 1; min-width: 0; }
59
+ .home-widget-arrow { margin-inline-start: auto; color: var(--muted-2); flex: none; }
60
+ .home-widget-badge { flex: none; }
61
+ .home-widget-badge .home-widget-symbol { font-size: var(--font-size-xs); }
62
+ .home-widget-preview { display: flex; flex-direction: column; justify-content: center; gap: 10px; min-width: 0; min-height: 74px; }
63
+ .home-widget-row { display: flex; align-items: center; gap: 10px; min-height: 31px; min-width: 0; }
64
+ .home-widget-copy { display: flex; flex: 1; flex-direction: column; gap: 3px; min-width: 0; }
65
+ .home-widget-item-title { display: block; font-size: var(--font-size-md); font-weight: 400; line-height: 1.4; }
66
+ .home-widget-row .home-widget-item-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
67
+ .home-widget-meta { font-size: var(--font-size-xs); color: var(--muted-2); line-height: 1.4; overflow-wrap: anywhere; }
68
+ .home-widget-meta:empty { display: none; }
69
+ .home-widget-row .home-widget-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
70
+ .home-widget-automation .home-widget-item-title, .home-widget-fallback .home-widget-title, .home-widget-fallback .home-widget-detail { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
71
+ .home-widget-symbol { display: inline-flex; align-items: center; justify-content: center; gap: 5px; flex: none; color: var(--muted); font-size: var(--font-size-sm); font-weight: 400; font-variant-numeric: tabular-nums; }
72
+ .home-widget-symbol svg { width: 16px; height: 16px; flex: none; }
73
+ .home-widget-symbol[data-tone="active"] { color: var(--accent); }
74
+ .home-widget-symbol[data-tone="success"] { color: var(--green); }
75
+ .home-widget-symbol[data-tone="attention"] { color: var(--amber); }
76
+ .home-widget-symbol[data-tone="failed"] { color: var(--danger); }
77
+ .home-widget-badge .home-widget-symbol[data-tone="attention"] { padding: 2px 6px; border-radius: 5px; background: color-mix(in srgb, var(--amber) 10%, var(--panel)); }
78
+ .home-widget-metrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: center; gap: 10px; min-height: 74px; }
79
+ .home-widget-metric { display: flex; flex-direction: column; align-items: center; gap: 9px; min-width: 0; color: var(--muted); font-size: var(--font-size-xs); }
80
+ .home-widget-metric .home-widget-symbol { min-height: 23px; font-size: var(--font-size-4xl); }
81
+ .home-widget-metric .home-widget-symbol svg { width: 20px; height: 20px; }
82
+ .home-widget-automation { display: flex; align-items: center; gap: 13px; min-height: 74px; }
83
+ .home-widget-automation > .home-widget-symbol { flex-direction: column; gap: 5px; min-width: 33px; font-size: var(--font-size-3xl); }
84
+ .home-widget-automation > .home-widget-symbol svg { width: 20px; height: 20px; }
85
+ .home-widget-computer { display: flex; flex-direction: column; justify-content: center; gap: 14px; min-height: 74px; }
86
+ .home-widget-device { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; min-width: 0; }
87
+ .home-widget-device .home-widget-item-title { overflow-wrap: anywhere; }
88
+ .home-widget-device .home-widget-meta { flex: none; }
89
+ .home-widget-checks { display: flex; flex-wrap: wrap; gap: 10px 16px; }
90
+ .home-widget-check { display: inline-flex; align-items: center; gap: 6px; font-size: var(--font-size-xs); color: var(--muted); }
91
+ .home-widget-fallback { display: flex; flex-direction: column; gap: 5px; }
92
+ .home-widget-title { font-size: var(--font-size-md); font-weight: 400; line-height: 1.4; }
93
+ .home-widget-detail { font-size: var(--font-size-xs); color: var(--muted); }
94
+ .home-widget-status { font-size: var(--font-size-xs); color: var(--muted-2); }
95
+ .home-widget-title, .home-widget-detail, .home-widget-status { overflow-wrap: anywhere; }
96
+ .home-widget[data-tone="success"] .home-widget-status { color: var(--green); }
97
+ .home-widget[data-tone="attention"] .home-widget-status { color: var(--amber); }
98
+ .home-widget[data-tone="failed"] .home-widget-status { color: var(--danger); }
99
+ .home-widget[data-tone="active"] .home-widget-status { color: var(--accent); }
100
+ }
101
+ @media (max-width: 1000px) {
102
+ .home-widgets-compact .home-widget-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
103
+ .home-widgets-compact .home-widget { padding: 14px; }
104
+ }
105
+ @media (max-width: 520px) {
106
+ .home-widgets-compact .home-widget-grid { grid-template-columns: minmax(0, 1fr); }
107
+ .home-widget-dialog-body { padding: 12px; }
108
+ .home-widget-dialog-header { padding: 12px; }
109
+ }
@@ -53,6 +53,7 @@
53
53
  @import url("./styles/43-co-worker-applications.css");
54
54
  @import url("./styles/48-notifications.css");
55
55
  @import url("./styles/49-macos-permission.css");
56
+ @import url("./styles/49-collection-consent.css");
56
57
  @import url("./styles/50-automations.css");
57
58
  @import url("./styles/51-automation-editor-actions.css");
58
59
  @import url("./styles/51-automation-templates.css");
@@ -61,3 +62,5 @@
61
62
  @import url("./styles/53-automation-schema-inputs.css");
62
63
  @import url("./styles/54-spark-chat.css");
63
64
  @import url("./styles/94-automations-responsive.css");
65
+ @import url("./styles/64-workspace-storage.css");
66
+ @import url("./styles/95-home-widgets.css");
@@ -0,0 +1,15 @@
1
+ /** Installation-owned UI state. These records never become model context. */
2
+ export type ClientPreferences = Record<string, string>;
3
+ export type ClientState = {
4
+ version: 1;
5
+ revision: number;
6
+ introductionSeen: boolean;
7
+ preferences: ClientPreferences;
8
+ queue: string;
9
+ };
10
+ export declare function emptyClientState(): ClientState;
11
+ export declare class ClientStateError extends Error {
12
+ readonly code: string;
13
+ readonly status: number;
14
+ constructor(code: string, message: string, status?: number);
15
+ }