@abot-ai/runtime 1.9.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (506) hide show
  1. package/README.md +5 -1
  2. package/dist/scripts/add-runtime-model.js +11 -5
  3. package/dist/scripts/init-runtime.js +15 -10
  4. package/dist/scripts/runtime-model-addition.js +6 -1
  5. package/dist/scripts/runtime-setup-command-options.d.ts +11 -0
  6. package/dist/scripts/runtime-setup-command-options.js +41 -0
  7. package/dist/scripts/runtime-setup-files.d.ts +3 -2
  8. package/dist/scripts/runtime-setup-files.js +19 -4
  9. package/dist/scripts/runtime-setup-model-options.d.ts +8 -0
  10. package/dist/scripts/runtime-setup-model-options.js +40 -0
  11. package/dist/scripts/runtime-setup-presentation.js +2 -2
  12. package/dist/scripts/runtime-setup-provider-options.d.ts +4 -0
  13. package/dist/scripts/runtime-setup-provider-options.js +20 -0
  14. package/dist/src/model-gateway/client/contracts.d.ts +3 -0
  15. package/dist/src/model-gateway/client/input-token-count.js +36 -16
  16. package/dist/src/model-gateway/client/message-projection.d.ts +2 -0
  17. package/dist/src/model-gateway/client/message-projection.js +1 -0
  18. package/dist/src/model-gateway/client/options.js +1 -1
  19. package/dist/src/model-gateway/client/raw.js +1 -0
  20. package/dist/src/model-gateway/index.d.ts +1 -1
  21. package/dist/src/model-gateway/observability/input-token-count-diagnostics.d.ts +26 -0
  22. package/dist/src/model-gateway/observability/input-token-count-diagnostics.js +178 -0
  23. package/dist/src/model-gateway/policy/invocation-policy.d.ts +1 -3
  24. package/dist/src/model-gateway/policy/invocation-policy.js +3 -30
  25. package/dist/src/model-gateway/policy/reasoning-mode-budget.d.ts +5 -0
  26. package/dist/src/model-gateway/policy/reasoning-mode-budget.js +13 -0
  27. package/dist/src/model-gateway/policy/reasoning-policy.d.ts +10 -0
  28. package/dist/src/model-gateway/policy/reasoning-policy.js +124 -0
  29. package/dist/src/model-gateway/protocol/openai-embedding-response.d.ts +1 -0
  30. package/dist/src/model-gateway/protocol/openai-embedding-response.js +28 -0
  31. package/dist/src/model-gateway/protocol/sse-data.d.ts +9 -0
  32. package/dist/src/model-gateway/protocol/sse-data.js +67 -0
  33. package/dist/src/model-gateway/providers/envelope-budget.js +10 -1
  34. package/dist/src/model-gateway/providers/llamacpp/adapter.d.ts +2 -0
  35. package/dist/src/model-gateway/providers/llamacpp/adapter.js +79 -0
  36. package/dist/src/model-gateway/providers/llamacpp/connection.d.ts +9 -0
  37. package/dist/src/model-gateway/providers/llamacpp/connection.js +73 -0
  38. package/dist/src/model-gateway/providers/llamacpp/diagnostics.d.ts +2 -0
  39. package/dist/src/model-gateway/providers/llamacpp/diagnostics.js +17 -0
  40. package/dist/src/model-gateway/providers/llamacpp/embeddings.d.ts +2 -0
  41. package/dist/src/model-gateway/providers/llamacpp/embeddings.js +56 -0
  42. package/dist/src/model-gateway/providers/llamacpp/input-token-count.d.ts +3 -0
  43. package/dist/src/model-gateway/providers/llamacpp/input-token-count.js +59 -0
  44. package/dist/src/model-gateway/providers/llamacpp/message-projection.d.ts +2 -0
  45. package/dist/src/model-gateway/providers/llamacpp/message-projection.js +33 -0
  46. package/dist/src/model-gateway/providers/llamacpp/payload.d.ts +2 -0
  47. package/dist/src/model-gateway/providers/llamacpp/payload.js +44 -0
  48. package/dist/src/model-gateway/providers/llamacpp/response-lifetime.d.ts +1 -0
  49. package/dist/src/model-gateway/providers/llamacpp/response-lifetime.js +56 -0
  50. package/dist/src/model-gateway/providers/llamacpp/schema-format.d.ts +2 -0
  51. package/dist/src/model-gateway/providers/llamacpp/schema-format.js +29 -0
  52. package/dist/src/model-gateway/providers/llamacpp/settings.d.ts +9 -0
  53. package/dist/src/model-gateway/providers/llamacpp/settings.js +25 -0
  54. package/dist/src/model-gateway/providers/llamacpp/stream-normalizer.d.ts +10 -0
  55. package/dist/src/model-gateway/providers/llamacpp/stream-normalizer.js +85 -0
  56. package/dist/src/model-gateway/providers/llamacpp/stream.d.ts +9 -0
  57. package/dist/src/model-gateway/providers/llamacpp/stream.js +33 -0
  58. package/dist/src/model-gateway/providers/openai/embeddings.js +2 -29
  59. package/dist/src/model-gateway/providers/openai/sse-data.d.ts +1 -9
  60. package/dist/src/model-gateway/providers/openai/sse-data.js +1 -67
  61. package/dist/src/model-gateway/providers/registry.js +2 -0
  62. package/dist/src/model-gateway/server/input-token-count-handler.js +10 -1
  63. package/dist/src/model-gateway/types.d.ts +11 -1
  64. package/dist/src/runtime/adapters/long-term-memory/onboarding-provider-availability.d.ts +4 -0
  65. package/dist/src/runtime/adapters/long-term-memory/onboarding-provider-availability.js +11 -0
  66. package/dist/src/runtime/adapters/long-term-memory/onboarding-service.js +28 -1
  67. package/dist/src/runtime/adapters/registered-tool-payload-related-artifacts.d.ts +1 -0
  68. package/dist/src/runtime/adapters/registered-tool-payload-related-artifacts.js +6 -1
  69. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/contracts.d.ts +1 -0
  70. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/execution.d.ts +1 -0
  71. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/execution.js +2 -0
  72. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-lifecycle.d.ts +1 -0
  73. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-lifecycle.js +2 -0
  74. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-stages.d.ts +1 -0
  75. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-stages.js +1 -0
  76. package/dist/src/runtime/adapters/registered-tool-worker-capabilities.js +1 -0
  77. package/dist/src/runtime/adapters/scheduler-runtime.js +2 -0
  78. package/dist/src/runtime/automations/agent-step-executor.js +1 -0
  79. package/dist/src/runtime/automations/catalog.d.ts +3 -0
  80. package/dist/src/runtime/automations/catalog.js +2 -0
  81. package/dist/src/runtime/automations/definition-contracts.d.ts +2 -0
  82. package/dist/src/runtime/automations/definition-input.js +3 -1
  83. package/dist/src/runtime/automations/draft-mutations.js +5 -1
  84. package/dist/src/runtime/automations/model-dependency-projection.d.ts +3 -1
  85. package/dist/src/runtime/automations/model-dependency-projection.js +4 -2
  86. package/dist/src/runtime/automations/publication-validation.js +7 -0
  87. package/dist/src/runtime/automations/saved-agent-management.js +1 -0
  88. package/dist/src/runtime/automations/service.d.ts +3 -0
  89. package/dist/src/runtime/capabilities/automation-builder/payload-schema.js +7 -5
  90. package/dist/src/runtime/capabilities/automations/authoring-catalog.d.ts +9 -0
  91. package/dist/src/runtime/capabilities/automations/authoring-catalog.js +1 -0
  92. package/dist/src/runtime/capabilities/automations/authoring-preparation.d.ts +3 -0
  93. package/dist/src/runtime/capabilities/automations/tool-contract.js +3 -2
  94. package/dist/src/runtime/capabilities/automations/tool-module.js +16 -7
  95. package/dist/src/runtime/capabilities/model-reasoning-controls.d.ts +23 -0
  96. package/dist/src/runtime/capabilities/model-reasoning-controls.js +56 -0
  97. package/dist/src/runtime/capabilities/scheduling/create-operations.js +2 -0
  98. package/dist/src/runtime/capabilities/scheduling/job-list-page.d.ts +1 -0
  99. package/dist/src/runtime/capabilities/scheduling/tool-module.js +5 -2
  100. package/dist/src/runtime/capabilities/scheduling/update-operations.js +2 -0
  101. package/dist/src/runtime/config/builders.js +6 -0
  102. package/dist/src/runtime/config/effective-model-config-validation.js +4 -0
  103. package/dist/src/runtime/config/llamacpp-profile-validation.d.ts +3 -0
  104. package/dist/src/runtime/config/llamacpp-profile-validation.js +15 -0
  105. package/dist/src/runtime/config/model-reasoning-schema.d.ts +40 -0
  106. package/dist/src/runtime/config/model-reasoning-schema.js +38 -0
  107. package/dist/src/runtime/config/model-reasoning-validation.d.ts +3 -0
  108. package/dist/src/runtime/config/model-reasoning-validation.js +37 -0
  109. package/dist/src/runtime/config/runner/step-instructions.d.ts +4 -0
  110. package/dist/src/runtime/config/runner/step-instructions.js +10 -6
  111. package/dist/src/runtime/config/schema.js +3 -0
  112. package/dist/src/runtime/config/validation/model-invocation-config-validation.js +14 -0
  113. package/dist/src/runtime/context/compacted-capability-result-receipt.d.ts +2 -0
  114. package/dist/src/runtime/context/compacted-capability-result-receipt.js +8 -7
  115. package/dist/src/runtime/context/execution-compacted-evidence.d.ts +4 -0
  116. package/dist/src/runtime/context/execution-compacted-evidence.js +2 -23
  117. package/dist/src/runtime/context/execution-compaction-checkpoint-selection.d.ts +19 -0
  118. package/dist/src/runtime/context/execution-compaction-checkpoint-selection.js +104 -0
  119. package/dist/src/runtime/context/model-step-compaction-inheritance.d.ts +12 -0
  120. package/dist/src/runtime/context/model-step-compaction-inheritance.js +28 -0
  121. package/dist/src/runtime/context/model-step-compaction-projection.d.ts +12 -0
  122. package/dist/src/runtime/context/model-step-compaction-projection.js +322 -0
  123. package/dist/src/runtime/context/model-step-compaction.d.ts +2 -1
  124. package/dist/src/runtime/context/model-step-compaction.js +25 -316
  125. package/dist/src/runtime/context/operation-supervision-compacted-evidence.js +7 -1
  126. package/dist/src/runtime/context/request-context.d.ts +2 -0
  127. package/dist/src/runtime/context/request-context.js +16 -0
  128. package/dist/src/runtime/context/request-tool-results-checkpoint.d.ts +2 -1
  129. package/dist/src/runtime/context/request-tool-results-checkpoint.js +35 -6
  130. package/dist/src/runtime/context/request-tool-results.js +3 -1
  131. package/dist/src/runtime/context/semantic-compaction/checkpoint-message.d.ts +5 -1
  132. package/dist/src/runtime/context/semantic-compaction/checkpoint-message.js +10 -4
  133. package/dist/src/runtime/context/semantic-compaction/execution-evidence-instructions.d.ts +4 -0
  134. package/dist/src/runtime/context/semantic-compaction/execution-evidence-instructions.js +38 -0
  135. package/dist/src/runtime/context/semantic-compaction/generation-contracts.d.ts +3 -1
  136. package/dist/src/runtime/context/semantic-compaction/generation-input.js +15 -10
  137. package/dist/src/runtime/context/semantic-compaction/inherited-source-digests.d.ts +8 -0
  138. package/dist/src/runtime/context/semantic-compaction/inherited-source-digests.js +76 -0
  139. package/dist/src/runtime/context/semantic-compaction/replacement-budget.js +3 -1
  140. package/dist/src/runtime/context/semantic-compaction/run.js +6 -12
  141. package/dist/src/runtime/knowledge-skills/builtins/computer-use.js +1 -1
  142. package/dist/src/runtime/knowledge-skills/builtins/technical-work.js +20 -2
  143. package/dist/src/runtime/knowledge-skills/builtins/what-can-i-do.d.ts +2 -0
  144. package/dist/src/runtime/knowledge-skills/builtins/what-can-i-do.js +27 -0
  145. package/dist/src/runtime/knowledge-skills/catalog.js +2 -0
  146. package/dist/src/runtime/local-application.d.ts +5 -0
  147. package/dist/src/runtime/local-host/app-service-dispatch.d.ts +1 -1
  148. package/dist/src/runtime/local-host/app-service-dispatch.js +2 -0
  149. package/dist/src/runtime/local-host/client-services.d.ts +5 -0
  150. package/dist/src/runtime/local-host/saved-approvals.js +1 -0
  151. package/dist/src/runtime/long-term-memory/onboarding/configuration.js +5 -7
  152. package/dist/src/runtime/long-term-memory/onboarding/contracts.d.ts +26 -0
  153. package/dist/src/runtime/long-term-memory/onboarding/embedding-profile-id.d.ts +1 -0
  154. package/dist/src/runtime/long-term-memory/onboarding/embedding-profile-id.js +8 -0
  155. package/dist/src/runtime/long-term-memory/onboarding/saved-profiles.d.ts +17 -0
  156. package/dist/src/runtime/long-term-memory/onboarding/saved-profiles.js +77 -0
  157. package/dist/src/runtime/long-term-memory/onboarding/service.js +40 -10
  158. package/dist/src/runtime/model/input-token-count.js +1 -0
  159. package/dist/src/runtime/model/invoke-step.js +12 -0
  160. package/dist/src/runtime/model/invoke-structured-step.d.ts +4 -1
  161. package/dist/src/runtime/model/invoke-structured-step.js +4 -0
  162. package/dist/src/runtime/model/model-catalog.d.ts +3 -0
  163. package/dist/src/runtime/model/model-catalog.js +2 -0
  164. package/dist/src/runtime/model/model-context-budget.d.ts +5 -0
  165. package/dist/src/runtime/model/model-context-budget.js +2 -0
  166. package/dist/src/runtime/model/model-step-port.d.ts +7 -0
  167. package/dist/src/runtime/model/optional-context-admission.d.ts +18 -0
  168. package/dist/src/runtime/model/optional-context-admission.js +23 -0
  169. package/dist/src/runtime/ports.d.ts +3 -1
  170. package/dist/src/runtime/projects/contracts.d.ts +6 -0
  171. package/dist/src/runtime/projects/registry-format.d.ts +3 -0
  172. package/dist/src/runtime/projects/registry-format.js +50 -0
  173. package/dist/src/runtime/projects/repository.d.ts +6 -3
  174. package/dist/src/runtime/projects/repository.js +26 -19
  175. package/dist/src/runtime/projects/service.js +11 -0
  176. package/dist/src/runtime/request/approval-wait/preflight.js +1 -0
  177. package/dist/src/runtime/request/approval-wait/snapshot.d.ts +1 -1
  178. package/dist/src/runtime/request/approval-wait/snapshot.js +1 -0
  179. package/dist/src/runtime/request/contracts.d.ts +5 -1
  180. package/dist/src/runtime/request/execution-facets.js +2 -0
  181. package/dist/src/runtime/request/execution-payload-artifact-policy.d.ts +3 -0
  182. package/dist/src/runtime/request/execution-payload-artifact-policy.js +6 -0
  183. package/dist/src/runtime/request/execution-payload-compacted-evidence.js +1 -0
  184. package/dist/src/runtime/request/execution-scope-surfaces.d.ts +2 -0
  185. package/dist/src/runtime/request/execution-scope-surfaces.js +3 -0
  186. package/dist/src/runtime/request/execution-scope.d.ts +2 -0
  187. package/dist/src/runtime/request/execution-scope.js +2 -0
  188. package/dist/src/runtime/request/input.d.ts +1 -0
  189. package/dist/src/runtime/request/input.js +1 -0
  190. package/dist/src/runtime/request/prepared-execution.d.ts +1 -0
  191. package/dist/src/runtime/request/prepared-execution.js +3 -0
  192. package/dist/src/runtime/request/reasoning-preference.d.ts +10 -0
  193. package/dist/src/runtime/request/reasoning-preference.js +29 -0
  194. package/dist/src/runtime/request/root-reference-action.js +3 -3
  195. package/dist/src/runtime/request/root-skill-read-admission.d.ts +4 -0
  196. package/dist/src/runtime/request/root-skill-read-admission.js +14 -0
  197. package/dist/src/runtime/request/root-skill-read.js +13 -5
  198. package/dist/src/runtime/request/supervisor-skill-selection-window.d.ts +16 -0
  199. package/dist/src/runtime/request/supervisor-skill-selection-window.js +17 -0
  200. package/dist/src/runtime/request/worker-capability-composition.js +2 -0
  201. package/dist/src/runtime/scheduler/contracts.d.ts +7 -1
  202. package/dist/src/runtime/scheduler/job-management.js +7 -1
  203. package/dist/src/runtime/scheduler/run-records.js +2 -0
  204. package/dist/src/runtime/scheduler/schedule-validation.js +2 -0
  205. package/dist/src/runtime/scheduler/scheduler-engine.js +1 -0
  206. package/dist/src/runtime/scheduler/snapshot-validation.js +2 -0
  207. package/dist/src/runtime/steps/auditor-decision/projection.js +2 -0
  208. package/dist/src/runtime/steps/execution-agent/capability-controls-partition.d.ts +9 -0
  209. package/dist/src/runtime/steps/execution-agent/capability-controls-partition.js +29 -0
  210. package/dist/src/runtime/steps/execution-agent/capability-scope.d.ts +17 -0
  211. package/dist/src/runtime/steps/execution-agent/capability-scope.js +54 -0
  212. package/dist/src/runtime/steps/execution-agent/compaction.js +22 -6
  213. package/dist/src/runtime/steps/execution-agent/controls-compacted-evidence.js +2 -0
  214. package/dist/src/runtime/steps/execution-agent/evidence-reuse-instructions.d.ts +6 -0
  215. package/dist/src/runtime/steps/execution-agent/evidence-reuse-instructions.js +13 -0
  216. package/dist/src/runtime/steps/execution-agent/format.js +3 -6
  217. package/dist/src/runtime/steps/execution-agent/input.d.ts +5 -1
  218. package/dist/src/runtime/steps/execution-agent/input.js +10 -36
  219. package/dist/src/runtime/steps/execution-agent/observation-guidance.d.ts +11 -0
  220. package/dist/src/runtime/steps/execution-agent/observation-guidance.js +33 -0
  221. package/dist/src/runtime/steps/execution-agent/prompt.js +2 -0
  222. package/dist/src/runtime/steps/execution-agent/refinement.d.ts +3 -2
  223. package/dist/src/runtime/steps/execution-agent/refinement.js +17 -6
  224. package/dist/src/runtime/steps/execution-agent/run.js +7 -1
  225. package/dist/src/runtime/steps/skill-read-decision.d.ts +1 -0
  226. package/dist/src/runtime/steps/skill-read-decision.js +9 -4
  227. package/dist/src/runtime/steps/supervisor-decision/artifact-paths.d.ts +6 -1
  228. package/dist/src/runtime/steps/supervisor-decision/artifact-paths.js +15 -0
  229. package/dist/src/runtime/steps/supervisor-decision/contracts.d.ts +1 -1
  230. package/dist/src/runtime/steps/supervisor-decision/contracts.js +2 -0
  231. package/dist/src/runtime/steps/supervisor-decision/decision-phases.d.ts +3 -0
  232. package/dist/src/runtime/steps/supervisor-decision/decision-phases.js +22 -3
  233. package/dist/src/runtime/steps/supervisor-decision/delegation-contract.d.ts +9 -0
  234. package/dist/src/runtime/steps/supervisor-decision/delegation-contract.js +82 -0
  235. package/dist/src/runtime/steps/supervisor-decision/delegation-input.d.ts +7 -0
  236. package/dist/src/runtime/steps/supervisor-decision/delegation-input.js +105 -0
  237. package/dist/src/runtime/steps/supervisor-decision/delegation-prompt.d.ts +7 -0
  238. package/dist/src/runtime/steps/supervisor-decision/delegation-prompt.js +13 -0
  239. package/dist/src/runtime/steps/supervisor-decision/input.d.ts +1 -0
  240. package/dist/src/runtime/steps/supervisor-decision/preparation-input.d.ts +3 -5
  241. package/dist/src/runtime/steps/supervisor-decision/preparation-input.js +5 -21
  242. package/dist/src/runtime/steps/supervisor-decision/preparation.d.ts +4 -1
  243. package/dist/src/runtime/steps/supervisor-decision/preparation.js +58 -6
  244. package/dist/src/runtime/steps/supervisor-decision/procedure-entry.d.ts +22 -0
  245. package/dist/src/runtime/steps/supervisor-decision/procedure-entry.js +61 -0
  246. package/dist/src/runtime/steps/supervisor-decision/procedure-gate.d.ts +39 -0
  247. package/dist/src/runtime/steps/supervisor-decision/procedure-gate.js +146 -0
  248. package/dist/src/runtime/steps/supervisor-decision/procedure-memory.d.ts +9 -0
  249. package/dist/src/runtime/steps/supervisor-decision/procedure-memory.js +100 -0
  250. package/dist/src/runtime/steps/supervisor-decision/procedure-recall.d.ts +10 -0
  251. package/dist/src/runtime/steps/supervisor-decision/procedure-recall.js +52 -0
  252. package/dist/src/runtime/steps/supervisor-decision/prompt.js +3 -16
  253. package/dist/src/runtime/steps/supervisor-decision/response-recommendation.js +2 -2
  254. package/dist/src/runtime/steps/supervisor-decision/role-guidance.d.ts +3 -0
  255. package/dist/src/runtime/steps/supervisor-decision/role-guidance.js +20 -0
  256. package/dist/src/runtime/steps/supervisor-decision/run.js +50 -7
  257. package/dist/src/runtime/steps/supervisor-decision/skill-read-state.d.ts +10 -0
  258. package/dist/src/runtime/steps/supervisor-decision/skill-read-state.js +45 -0
  259. package/dist/src/runtime/steps/supervisor-decision/skill-selection-candidates.d.ts +15 -0
  260. package/dist/src/runtime/steps/supervisor-decision/skill-selection-candidates.js +25 -0
  261. package/dist/src/runtime/steps/supervisor-decision/skill-selection-catalog.d.ts +3 -0
  262. package/dist/src/runtime/steps/supervisor-decision/skill-selection-catalog.js +15 -0
  263. package/dist/src/runtime/steps/supervisor-decision/skill-selection-continuation.d.ts +10 -0
  264. package/dist/src/runtime/steps/supervisor-decision/skill-selection-continuation.js +65 -0
  265. package/dist/src/runtime/steps/supervisor-decision/skill-selection-input.d.ts +3 -1
  266. package/dist/src/runtime/steps/supervisor-decision/skill-selection-input.js +20 -22
  267. package/dist/src/runtime/steps/supervisor-decision/skill-selection.d.ts +3 -2
  268. package/dist/src/runtime/steps/supervisor-decision/skill-selection.js +62 -15
  269. package/dist/src/runtime/steps/supervisor-response/prompt.js +18 -4
  270. package/dist/src/shared/model-reasoning-modes.d.ts +5 -0
  271. package/dist/src/shared/model-reasoning-modes.js +20 -0
  272. package/dist/src/shared/model-reasoning-schema.d.ts +38 -0
  273. package/dist/src/shared/model-reasoning-schema.js +29 -0
  274. package/dist/src/shared/model-reasoning.d.ts +35 -0
  275. package/dist/src/shared/model-reasoning.js +100 -0
  276. package/dist/src/web-ui/app/ARCHITECTURE.md +13 -0
  277. package/dist/src/web-ui/app/app-bootstrap.js +9 -12
  278. package/dist/src/web-ui/app/app-dom.js +6 -1
  279. package/dist/src/web-ui/app/app-state.js +1 -0
  280. package/dist/src/web-ui/app/app.js +8 -3
  281. package/dist/src/web-ui/app/appearance-feature.js +28 -0
  282. package/dist/src/web-ui/app/automations-feature.js +20 -11
  283. package/dist/src/web-ui/app/components/appearance-dialog.js +79 -0
  284. package/dist/src/web-ui/app/components/automations/archive-actions.js +5 -3
  285. package/dist/src/web-ui/app/components/automations/authoring-entry.js +26 -7
  286. package/dist/src/web-ui/app/components/automations/confirmation-actions.js +78 -0
  287. package/dist/src/web-ui/app/components/automations/draft-recovery-actions.js +1 -0
  288. package/dist/src/web-ui/app/components/automations/node-inspector.js +5 -1
  289. package/dist/src/web-ui/app/components/automations/step-editor-dialog.js +4 -2
  290. package/dist/src/web-ui/app/components/automations/timeline.js +2 -2
  291. package/dist/src/web-ui/app/components/automations/workspace-navigation.js +37 -0
  292. package/dist/src/web-ui/app/components/automations/workspace.js +31 -46
  293. package/dist/src/web-ui/app/components/config-workspace/config-model.js +6 -0
  294. package/dist/src/web-ui/app/components/config-workspace/model-removal.js +4 -2
  295. package/dist/src/web-ui/app/components/config-workspace/model-rendering.js +8 -16
  296. package/dist/src/web-ui/app/components/config-workspace/reasoning-budget-edit.js +113 -0
  297. package/dist/src/web-ui/app/components/config-workspace/reasoning-budget.d.ts +16 -0
  298. package/dist/src/web-ui/app/components/config-workspace/reasoning-budget.js +67 -0
  299. package/dist/src/web-ui/app/components/config-workspace/reasoning-mode-budgets.d.ts +7 -0
  300. package/dist/src/web-ui/app/components/config-workspace/reasoning-mode-budgets.js +25 -0
  301. package/dist/src/web-ui/app/components/config-workspace/workspace-events.js +15 -7
  302. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +32 -12
  303. package/dist/src/web-ui/app/components/config-workspace/workspace-persistence.js +1 -1
  304. package/dist/src/web-ui/app/components/config-workspace.js +2 -1
  305. package/dist/src/web-ui/app/components/confirmation-dialog.js +88 -0
  306. package/dist/src/web-ui/app/components/conversation-activity.d.ts +2 -0
  307. package/dist/src/web-ui/app/components/conversation-activity.js +32 -3
  308. package/dist/src/web-ui/app/components/conversation-memory-activity.js +31 -0
  309. package/dist/src/web-ui/app/components/conversation-role-cards.d.ts +2 -0
  310. package/dist/src/web-ui/app/components/conversation-role-cards.js +14 -11
  311. package/dist/src/web-ui/app/components/conversation-skill-activity.js +67 -0
  312. package/dist/src/web-ui/app/components/conversation-tools.js +5 -5
  313. package/dist/src/web-ui/app/components/conversation-view.js +6 -0
  314. package/dist/src/web-ui/app/components/dashboard/approvals.js +13 -1
  315. package/dist/src/web-ui/app/components/long-term-memory/embedding-connection-dialog.d.ts +38 -0
  316. package/dist/src/web-ui/app/components/long-term-memory/embedding-connection-dialog.js +289 -0
  317. package/dist/src/web-ui/app/components/long-term-memory/embedding-connection-feature.js +75 -0
  318. package/dist/src/web-ui/app/components/long-term-memory/embedding-connection-rendering.js +31 -0
  319. package/dist/src/web-ui/app/components/long-term-memory/manager.js +15 -5
  320. package/dist/src/web-ui/app/components/long-term-memory/saved-embedding-profiles.js +114 -0
  321. package/dist/src/web-ui/app/components/long-term-memory/setup-rendering.js +55 -0
  322. package/dist/src/web-ui/app/components/long-term-memory-setup.js +141 -76
  323. package/dist/src/web-ui/app/components/model-setup/rendering.js +3 -2
  324. package/dist/src/web-ui/app/components/model-setup/validation.js +6 -2
  325. package/dist/src/web-ui/app/components/model-setup/wizard.d.ts +1 -0
  326. package/dist/src/web-ui/app/components/model-setup/wizard.js +28 -5
  327. package/dist/src/web-ui/app/components/passive-learning/memory.js +12 -5
  328. package/dist/src/web-ui/app/components/plugins/manager.js +14 -0
  329. package/dist/src/web-ui/app/components/plugins/removal.js +10 -2
  330. package/dist/src/web-ui/app/components/project-group-actions.js +35 -0
  331. package/dist/src/web-ui/app/components/project-session-groups.js +17 -31
  332. package/dist/src/web-ui/app/components/runtime-setup/commands.js +1 -1
  333. package/dist/src/web-ui/app/components/runtime-setup/connection-form.d.ts +15 -0
  334. package/dist/src/web-ui/app/components/runtime-setup/connection-form.js +32 -9
  335. package/dist/src/web-ui/app/components/runtime-setup/connection-input.js +23 -0
  336. package/dist/src/web-ui/app/components/runtime-setup/connection-inspection.js +57 -0
  337. package/dist/src/web-ui/app/components/runtime-setup/connection-state.js +18 -4
  338. package/dist/src/web-ui/app/components/runtime-setup/embedding-credential-status.js +3 -0
  339. package/dist/src/web-ui/app/components/runtime-setup/embedding-provider-options.js +54 -0
  340. package/dist/src/web-ui/app/components/runtime-setup/embedding-provider-receipt.js +3 -0
  341. package/dist/src/web-ui/app/components/runtime-setup/embedding-rendering.js +22 -22
  342. package/dist/src/web-ui/app/components/runtime-setup/embedding.js +60 -16
  343. package/dist/src/web-ui/app/components/runtime-setup/reasoning-fields.d.ts +17 -0
  344. package/dist/src/web-ui/app/components/runtime-setup/reasoning-fields.js +54 -0
  345. package/dist/src/web-ui/app/components/runtime-setup/validation.js +5 -1
  346. package/dist/src/web-ui/app/components/runtime-setup-guide.d.ts +9 -3
  347. package/dist/src/web-ui/app/components/runtime-setup-guide.js +20 -29
  348. package/dist/src/web-ui/app/components/schedules/details.js +2 -2
  349. package/dist/src/web-ui/app/components/schedules/form.js +12 -5
  350. package/dist/src/web-ui/app/components/schedules/workspace.js +30 -18
  351. package/dist/src/web-ui/app/components/session-list-viewport.js +49 -0
  352. package/dist/src/web-ui/app/components/session-search-disclosure.js +27 -0
  353. package/dist/src/web-ui/app/components/skills/workspace.js +7 -3
  354. package/dist/src/web-ui/app/components/spark-chat/panel.js +7 -3
  355. package/dist/src/web-ui/app/components/spark-chat/settings.js +57 -15
  356. package/dist/src/web-ui/app/components/tool-approval-card.d.ts +2 -1
  357. package/dist/src/web-ui/app/components/tool-approval-card.js +10 -2
  358. package/dist/src/web-ui/app/components/tool-approval-rejection-input.js +116 -0
  359. package/dist/src/web-ui/app/components/workspace-shell.js +30 -38
  360. package/dist/src/web-ui/app/components/workspace-transitions.js +42 -0
  361. package/dist/src/web-ui/app/configuration-feature.js +34 -4
  362. package/dist/src/web-ui/app/controllers/app-event-bindings.js +45 -29
  363. package/dist/src/web-ui/app/controllers/appearance-controller.js +105 -0
  364. package/dist/src/web-ui/app/controllers/automations-controller.js +9 -1
  365. package/dist/src/web-ui/app/controllers/composer-feature.d.ts +1 -1
  366. package/dist/src/web-ui/app/controllers/composer-feature.js +10 -3
  367. package/dist/src/web-ui/app/controllers/composer-queue-controller.d.ts +1 -1
  368. package/dist/src/web-ui/app/controllers/composer-queue-controller.js +9 -3
  369. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.d.ts +1 -1
  370. package/dist/src/web-ui/app/controllers/conversation-workspace-activation.js +8 -2
  371. package/dist/src/web-ui/app/controllers/dashboard-approvals-controller.js +10 -9
  372. package/dist/src/web-ui/app/controllers/environment-transition.js +2 -2
  373. package/dist/src/web-ui/app/controllers/environment-workspace-preparation.js +9 -7
  374. package/dist/src/web-ui/app/controllers/preference-view-sync.js +35 -0
  375. package/dist/src/web-ui/app/controllers/projects-controller.d.ts +4 -0
  376. package/dist/src/web-ui/app/controllers/projects-controller.js +64 -3
  377. package/dist/src/web-ui/app/controllers/reasoning-budget-controller.d.ts +17 -0
  378. package/dist/src/web-ui/app/controllers/reasoning-budget-controller.js +80 -0
  379. package/dist/src/web-ui/app/controllers/reasoning-budget-menu-events.js +45 -0
  380. package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +35 -40
  381. package/dist/src/web-ui/app/controllers/runtime-selection-controller.d.ts +6 -1
  382. package/dist/src/web-ui/app/controllers/runtime-selection-controller.js +16 -3
  383. package/dist/src/web-ui/app/controllers/session-controller.js +34 -9
  384. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +4 -3
  385. package/dist/src/web-ui/app/controllers/skills-controller.js +33 -16
  386. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +1 -1
  387. package/dist/src/web-ui/app/controllers/spark-handoff-navigation.js +7 -1
  388. package/dist/src/web-ui/app/controllers/tool-approval-controller.d.ts +2 -1
  389. package/dist/src/web-ui/app/controllers/tool-approval-controller.js +36 -3
  390. package/dist/src/web-ui/app/controllers/workspace-conversation-opener.js +8 -2
  391. package/dist/src/web-ui/app/controllers/workspace-route-controller.js +41 -10
  392. package/dist/src/web-ui/app/index.html +38 -32
  393. package/dist/src/web-ui/app/lib/color-palettes.d.ts +17 -0
  394. package/dist/src/web-ui/app/lib/color-palettes.js +20 -0
  395. package/dist/src/web-ui/app/lib/memory-activity-model.d.ts +12 -0
  396. package/dist/src/web-ui/app/lib/memory-activity-model.js +61 -0
  397. package/dist/src/web-ui/app/lib/navigation-display.d.ts +8 -0
  398. package/dist/src/web-ui/app/lib/navigation-display.js +12 -0
  399. package/dist/src/web-ui/app/lib/reasoning-controls.js +47 -6
  400. package/dist/src/web-ui/app/lib/reasoning-preference.d.ts +9 -0
  401. package/dist/src/web-ui/app/lib/reasoning-preference.js +75 -0
  402. package/dist/src/web-ui/app/lib/session-composer-queue.d.ts +4 -0
  403. package/dist/src/web-ui/app/lib/session-composer-queue.js +4 -0
  404. package/dist/src/web-ui/app/lib/session-project-groups.js +28 -0
  405. package/dist/src/web-ui/app/lib/session-sidebar-order.js +7 -5
  406. package/dist/src/web-ui/app/lib/tool-activity-event.d.ts +1 -0
  407. package/dist/src/web-ui/app/lib/tool-activity-event.js +1 -0
  408. package/dist/src/web-ui/app/lib/tool-activity-model.d.ts +1 -0
  409. package/dist/src/web-ui/app/lib/tool-activity-model.js +1 -0
  410. package/dist/src/web-ui/app/lib/tool-approval-rejection-drafts.js +45 -0
  411. package/dist/src/web-ui/app/lib/tool-skill-activity-fields.js +1 -1
  412. package/dist/src/web-ui/app/notifications-feature.js +10 -2
  413. package/dist/src/web-ui/app/passive-learning-feature.js +2 -2
  414. package/dist/src/web-ui/app/projects-feature.js +40 -10
  415. package/dist/src/web-ui/app/runtime-onboarding-feature.js +1 -0
  416. package/dist/src/web-ui/app/schedules-feature.js +28 -5
  417. package/dist/src/web-ui/app/services/client-preferences.d.ts +4 -1
  418. package/dist/src/web-ui/app/services/client-preferences.js +2 -0
  419. package/dist/src/web-ui/app/services/conversation-reasoning-preferences.d.ts +11 -0
  420. package/dist/src/web-ui/app/services/conversation-reasoning-preferences.js +30 -0
  421. package/dist/src/web-ui/app/services/runtime-web-client/automations.js +6 -4
  422. package/dist/src/web-ui/app/services/runtime-web-client/configuration.js +5 -0
  423. package/dist/src/web-ui/app/services/runtime-web-client/memory.js +21 -0
  424. package/dist/src/web-ui/app/services/runtime-web-client/projects.d.ts +2 -1
  425. package/dist/src/web-ui/app/services/runtime-web-client/projects.js +4 -0
  426. package/dist/src/web-ui/app/services/runtime-web-client/tool-approvals.js +2 -0
  427. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +16 -0
  428. package/dist/src/web-ui/app/services/runtime-web-client.js +2 -0
  429. package/dist/src/web-ui/app/services/session-sidebar-preferences.js +33 -13
  430. package/dist/src/web-ui/app/skills-feature.js +2 -3
  431. package/dist/src/web-ui/app/spark-chat-conversation.js +29 -3
  432. package/dist/src/web-ui/app/spark-chat-feature.js +13 -7
  433. package/dist/src/web-ui/app/styles/01-color-palettes.css +90 -0
  434. package/dist/src/web-ui/app/styles/11-product-links.css +6 -2
  435. package/dist/src/web-ui/app/styles/11-workspace-header-width.css +37 -25
  436. package/dist/src/web-ui/app/styles/12-conversation-sidebar.css +56 -22
  437. package/dist/src/web-ui/app/styles/13-projects.css +56 -19
  438. package/dist/src/web-ui/app/styles/19-runtime-setup.css +16 -0
  439. package/dist/src/web-ui/app/styles/22-reasoning-budget.css +39 -0
  440. package/dist/src/web-ui/app/styles/27-conversation-memory.css +45 -0
  441. package/dist/src/web-ui/app/styles/27-conversation-skills.css +96 -0
  442. package/dist/src/web-ui/app/styles/28-tool-approval-card.css +38 -1
  443. package/dist/src/web-ui/app/styles/35-embedding-profiles.css +159 -0
  444. package/dist/src/web-ui/app/styles/54-spark-chat.css +62 -46
  445. package/dist/src/web-ui/app/styles/65-appearance.css +60 -0
  446. package/dist/src/web-ui/app/styles/66-navigation-display.css +30 -0
  447. package/dist/src/web-ui/app/styles/67-confirmation-dialog.css +32 -0
  448. package/dist/src/web-ui/app/styles.css +8 -0
  449. package/dist/src/web-ui/client-state/preference-shapes.js +6 -1
  450. package/dist/src/web-ui/client-state/preferences.js +8 -2
  451. package/dist/src/web-ui/client-state/reasoning-preference-shape.d.ts +1 -0
  452. package/dist/src/web-ui/client-state/reasoning-preference-shape.js +18 -0
  453. package/dist/src/web-ui/local-runtime/api-router.d.ts +1 -0
  454. package/dist/src/web-ui/local-runtime/api-router.js +11 -0
  455. package/dist/src/web-ui/local-runtime/memory-embedding-connection-input.d.ts +7 -0
  456. package/dist/src/web-ui/local-runtime/memory-embedding-connection-input.js +22 -0
  457. package/dist/src/web-ui/local-runtime/memory-embedding-connection-service.d.ts +20 -0
  458. package/dist/src/web-ui/local-runtime/memory-embedding-connection-service.js +47 -0
  459. package/dist/src/web-ui/local-runtime/memory-onboarding-routes.js +32 -0
  460. package/dist/src/web-ui/local-runtime/model-connection-inspection.d.ts +7 -0
  461. package/dist/src/web-ui/local-runtime/model-connection-inspection.js +48 -0
  462. package/dist/src/web-ui/local-runtime/model-setup-catalog.d.ts +2 -1
  463. package/dist/src/web-ui/local-runtime/model-setup-catalog.js +3 -1
  464. package/dist/src/web-ui/local-runtime/model-setup-identity.js +1 -1
  465. package/dist/src/web-ui/local-runtime/model-setup-input.d.ts +5 -2
  466. package/dist/src/web-ui/local-runtime/model-setup-input.js +29 -6
  467. package/dist/src/web-ui/local-runtime/model-setup-provider.d.ts +1 -1
  468. package/dist/src/web-ui/local-runtime/model-setup-provider.js +9 -6
  469. package/dist/src/web-ui/local-runtime/model-setup-retry.js +4 -1
  470. package/dist/src/web-ui/local-runtime/model-setup-service.d.ts +2 -1
  471. package/dist/src/web-ui/local-runtime/pending-tool-approvals.js +4 -1
  472. package/dist/src/web-ui/local-runtime/project-routes.js +10 -2
  473. package/dist/src/web-ui/local-runtime/request-execution.js +1 -0
  474. package/dist/src/web-ui/local-runtime/runtime-setup-auth.d.ts +2 -0
  475. package/dist/src/web-ui/local-runtime/runtime-setup-auth.js +20 -0
  476. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.js +3 -2
  477. package/dist/src/web-ui/local-runtime/runtime-setup-credential-completion.js +6 -1
  478. package/dist/src/web-ui/local-runtime/runtime-setup-input.d.ts +3 -2
  479. package/dist/src/web-ui/local-runtime/runtime-setup-input.js +17 -5
  480. package/dist/src/web-ui/local-runtime/runtime-setup-provider.d.ts +4 -1
  481. package/dist/src/web-ui/local-runtime/runtime-setup-provider.js +6 -2
  482. package/dist/src/web-ui/local-runtime/runtime-setup-routes.d.ts +11 -2
  483. package/dist/src/web-ui/local-runtime/runtime-setup-routes.js +11 -2
  484. package/dist/src/web-ui/local-runtime/runtime-setup-scaffold.js +3 -2
  485. package/dist/src/web-ui/local-runtime/runtime-setup-service.d.ts +25 -4
  486. package/dist/src/web-ui/local-runtime/runtime-setup-service.js +19 -9
  487. package/dist/src/web-ui/local-runtime/setup-embedding-input.d.ts +3 -1
  488. package/dist/src/web-ui/local-runtime/setup-embedding-input.js +38 -6
  489. package/dist/src/web-ui/local-runtime/setup-embedding-llamacpp.d.ts +11 -0
  490. package/dist/src/web-ui/local-runtime/setup-embedding-llamacpp.js +53 -0
  491. package/dist/src/web-ui/local-runtime/setup-embedding-provider.js +23 -9
  492. package/dist/src/web-ui/local-runtime/setup-embedding-routes.d.ts +7 -2
  493. package/dist/src/web-ui/local-runtime/setup-embedding-routes.js +5 -3
  494. package/dist/src/web-ui/local-runtime/setup-embedding-service.d.ts +1 -0
  495. package/docs/configuration.md +10 -8
  496. package/docs/installation.md +11 -5
  497. package/docs/llamacpp.md +248 -0
  498. package/docs/long-term-memory.md +12 -0
  499. package/docs/running-locally.md +7 -1
  500. package/package.json +2 -1
  501. package/plugins/project-orientation/source/index.ts +2 -3
  502. package/plugins/project-orientation/source/inspection-failure.ts +1 -1
  503. package/plugins/project-orientation/source/project-target.ts +29 -0
  504. package/plugins/project-orientation/src/index.cjs +21 -2
  505. package/runtime.config.schema.json +140 -0
  506. package/src/runtime/README.md +50 -4
@@ -11,16 +11,22 @@ export function createConversationWorkspaceActivation({ state, shell, composerQu
11
11
  const session = state.currentSessionId;
12
12
  const version = state.sessionViewVersion;
13
13
  const navigationRevision = shell.navigationRevision?.();
14
+ const navigationRequest = shell.navigationRequestRevision?.();
14
15
  const recovery = await composerQueue.prepareRecoveryForNavigation();
15
16
  if (!recovery || recovery.canCommit?.() === false) return false;
16
17
  if (!canNavigateConversation(state)) return false;
17
18
  const hasCurrentWorkspaceNavigation = navigationRevision === shell.navigationRevision?.();
18
19
  if (!hasCurrentWorkspaceNavigation) return false;
20
+ if (navigationRequest !== shell.navigationRequestRevision?.()) return false;
19
21
  if (environment !== selectedEnvironmentId()) return false;
20
22
  if (session !== state.currentSessionId) return false;
21
23
  if (version !== state.sessionViewVersion) return false;
22
- const activate = shell.prepareWorkspaceActivation("chat", { focus: false });
23
- if (!activate) return false;
24
+ const activate = await shell.prepareWorkspaceActivation("chat", { focus: false });
25
+ if (!activate || activate.canCommit?.() === false) return false;
26
+ if (environment !== selectedEnvironmentId()) return false;
27
+ if (session !== state.currentSessionId) return false;
28
+ if (version !== state.sessionViewVersion) return false;
29
+ if (recovery.canCommit?.() === false) return false;
24
30
  recovery();
25
31
  return activate() !== false;
26
32
  };
@@ -1,11 +1,7 @@
1
- function approvalIdentity(approval) {
2
- return JSON.stringify([
3
- approval.environmentId,
4
- approval.sessionId,
5
- approval.requestId,
6
- approval.approvalId,
7
- ]);
8
- }
1
+ import {
2
+ approvalRejectionIdentity as approvalIdentity,
3
+ createApprovalRejectionDrafts,
4
+ } from "../lib/tool-approval-rejection-drafts.js";
9
5
 
10
6
  export function createDashboardApprovalsController({
11
7
  client,
@@ -21,6 +17,7 @@ export function createDashboardApprovalsController({
21
17
  let scopeRevision = 0;
22
18
  let readRevision = 0;
23
19
  const submitting = new Set();
20
+ const rejectionDrafts = createApprovalRejectionDrafts();
24
21
 
25
22
  function snapshot() {
26
23
  return {
@@ -29,6 +26,7 @@ export function createDashboardApprovalsController({
29
26
  ? approvals.map((approval) => ({
30
27
  ...approval,
31
28
  submitted: submitting.has(approvalIdentity(approval)),
29
+ rejectionDraft: rejectionDrafts.get(approval),
32
30
  }))
33
31
  : [],
34
32
  supportsToolApprovals: client.supportsToolApprovals(),
@@ -58,6 +56,7 @@ export function createDashboardApprovalsController({
58
56
  error = "";
59
57
  decisionError = "";
60
58
  submitting.clear();
59
+ rejectionDrafts.clear();
61
60
  }
62
61
 
63
62
  async function refresh() {
@@ -79,6 +78,7 @@ export function createDashboardApprovalsController({
79
78
  const result = await client.listToolApprovals(scope);
80
79
  if (!hasCurrentRead(scope, revision)) return;
81
80
  approvals = result.approvals;
81
+ rejectionDrafts.retain(approvals);
82
82
  error = "";
83
83
  } catch (failure) {
84
84
  if (!hasCurrentRead(scope, revision)) return;
@@ -99,7 +99,7 @@ export function createDashboardApprovalsController({
99
99
  return approvals.some((pending) => approvalIdentity(pending) === identity);
100
100
  }
101
101
 
102
- async function submit(approval, approved) {
102
+ async function submit(approval, approved, reason) {
103
103
  const identity = approvalIdentity(approval);
104
104
  if (!canSubmitApproval(approval, identity)) return false;
105
105
  const scope = approval.environmentId;
@@ -114,6 +114,7 @@ export function createDashboardApprovalsController({
114
114
  requestId: approval.requestId,
115
115
  approvalId: approval.approvalId,
116
116
  approved,
117
+ ...(reason !== undefined ? { reason } : {}),
117
118
  ...approvalDecisionCommand(approval, approved),
118
119
  });
119
120
  if (!hasCurrentScope(scope, revision)) return true;
@@ -53,9 +53,9 @@ export function createEnvironmentTransition({ state, dom, actions, prepareQueueR
53
53
  if (environmentChangeWasDeclined(preparedQueue)) { restoreSelection(); return false; }
54
54
  if (!canCommitEnvironmentPreparations([preparedAdditional, preparedQueue, commitEnvironmentOptions])) { restoreSelection(); return false; }
55
55
  const preparedConfig = actions.beforeEnvironmentChange
56
- ? actions.beforeEnvironmentChange({ from: previous, to: target }) : true;
57
- if (environmentChangeWasDeclined(preparedConfig)) { restoreSelection(); return false; }
56
+ ? await actions.beforeEnvironmentChange({ from: previous, to: target }) : true;
58
57
  if (!hasCurrentEnvironmentSelection(operation, previous)) return false;
58
+ if (environmentChangeWasDeclined(preparedConfig)) { restoreSelection(); return false; }
59
59
  if (!canCommitEnvironmentPreparations([preparedAdditional, preparedQueue, preparedConfig, commitEnvironmentOptions])) { restoreSelection(); return false; }
60
60
  if (typeof preparedAdditional === "function") preparedAdditional();
61
61
  if (typeof preparedQueue === "function") preparedQueue();
@@ -1,17 +1,19 @@
1
1
  import { environmentChangeWasDeclined } from "./environment-transition.js";
2
2
 
3
3
  /** Discard workspace drafts only after every preparation remains current. */
4
- export function prepareEnvironmentWorkspaceChanges(schedules, configuration, skills) {
5
- const schedule = schedules.prepareEnvironmentChange();
4
+ export async function prepareEnvironmentWorkspaceChanges(schedules, configuration, skills) {
5
+ const schedule = await schedules.prepareEnvironmentChange();
6
6
  if (environmentChangeWasDeclined(schedule)) return null;
7
- const config = configuration.prepareDiscardChanges("change environment");
7
+ const config = await configuration.prepareDiscardChanges("change environment");
8
8
  if (environmentChangeWasDeclined(config)) return null;
9
- const skill = skills ? skills.prepareEnvironmentChange() : true;
9
+ const skill = skills ? await skills.prepareEnvironmentChange() : true;
10
10
  if (environmentChangeWasDeclined(skill)) return null;
11
11
  const commit = () => {
12
- if (typeof skill === "function") skill();
13
- if (typeof schedule === "function") schedule();
14
- if (typeof config === "function") config();
12
+ if (!commit.canCommit()) return false;
13
+ for (const prepared of [skill, schedule, config]) {
14
+ if (typeof prepared === "function" && prepared() === false) return false;
15
+ }
16
+ return true;
15
17
  };
16
18
  commit.canCommit = () => {
17
19
  if (skill?.canCommit?.() === false) return false;
@@ -0,0 +1,35 @@
1
+ function sidebarPreferenceScope(preferences, environmentId) {
2
+ return JSON.stringify({
3
+ environmentId,
4
+ pinnedSessionIds: preferences.loadPinnedSessions(),
5
+ sidebar: preferences.loadSessionSidebar(environmentId),
6
+ });
7
+ }
8
+
9
+ /** Selection acknowledgements update controls, not the sidebar's loaded pages. */
10
+ export function createPreferenceViewSync({
11
+ preferences, selection, dashboard, getEnvironmentId, loadSessions,
12
+ }) {
13
+ let ready = false;
14
+ let sidebarScope;
15
+
16
+ function synchronize() {
17
+ selection.loadPreferences();
18
+ if (!ready) return;
19
+ selection.applyModelSelection();
20
+ selection.renderPermissionMode();
21
+ void dashboard.refresh();
22
+ const nextScope = sidebarPreferenceScope(preferences, getEnvironmentId());
23
+ if (nextScope === sidebarScope) return;
24
+ sidebarScope = nextScope;
25
+ void loadSessions();
26
+ }
27
+
28
+ return {
29
+ synchronize,
30
+ setReady() {
31
+ ready = true;
32
+ synchronize();
33
+ },
34
+ };
35
+ }
@@ -13,6 +13,7 @@ export type ProjectCreationDraft = {
13
13
 
14
14
  export type ProjectsControllerState = {
15
15
  projects: readonly RuntimeProject[];
16
+ deletedProjectIds: readonly string[];
16
17
  loading: boolean;
17
18
  error: string;
18
19
  draft: ProjectCreationDraft | null;
@@ -30,6 +31,7 @@ export declare function createProjectsController(options: {
30
31
  onChange: (state: ProjectsControllerState) => void;
31
32
  notify: (message: string, tone: "failed") => void;
32
33
  onSessionCreated?: (sessionId: string) => void;
34
+ confirmAction?: (message: string) => boolean | Promise<boolean>;
33
35
  }): {
34
36
  snapshot(): ProjectsControllerState;
35
37
  load(): Promise<void>;
@@ -44,4 +46,6 @@ export declare function createProjectsController(options: {
44
46
  browse(directory?: string, cursor?: string): Promise<void>;
45
47
  create(): Promise<void>;
46
48
  newConversation(projectId: string): Promise<void>;
49
+ deleteProject(projectId: string, projectName?: string): Promise<boolean>;
50
+ getDeletedProjectIds(): readonly string[];
47
51
  };
@@ -1,3 +1,4 @@
1
+ import { confirmDialog } from "../components/confirmation-dialog.js";
1
2
  function errorMessage(error) {
2
3
  return error instanceof Error ? error.message : String(error);
3
4
  }
@@ -13,6 +14,7 @@ export function createProjectsController({
13
14
  onChange,
14
15
  notify,
15
16
  onSessionCreated = () => {},
17
+ confirmAction = (message) => confirmDialog(message, { title: "Delete project", confirmLabel: "Delete project", tone: "danger" }),
16
18
  }) {
17
19
  let revision = 0;
18
20
  let currentEnvironment = getEnvironmentId();
@@ -22,6 +24,7 @@ export function createProjectsController({
22
24
  let activationRevision = 0;
23
25
  let state = {
24
26
  projects: [],
27
+ deletedProjectIds: [],
25
28
  loading: false,
26
29
  error: "",
27
30
  draft: null,
@@ -90,7 +93,7 @@ export function createProjectsController({
90
93
  const token = revision;
91
94
  const listToken = ++listRevision;
92
95
  if (!canUseProjects()) {
93
- state = { ...state, projects: [], loading: false, error: "" };
96
+ state = { ...state, projects: [], deletedProjectIds: [], loading: false, error: "" };
94
97
  publish();
95
98
  return;
96
99
  }
@@ -99,7 +102,8 @@ export function createProjectsController({
99
102
  try {
100
103
  const result = await client.listProjects(environmentId);
101
104
  if (!canApplyProjectList(environmentId, token, listToken)) return;
102
- state = { ...state, projects: result.projects ?? [], loading: false };
105
+ state = { ...state, projects: result.projects ?? [],
106
+ deletedProjectIds: result.deletedProjectIds ?? [], loading: false };
103
107
  } catch (error) {
104
108
  if (!canApplyProjectList(environmentId, token, listToken)) return;
105
109
  state = { ...state, loading: false, error: errorMessage(error) };
@@ -265,6 +269,61 @@ export function createProjectsController({
265
269
  }
266
270
  }
267
271
 
272
+ function getDeletedProjectIds() {
273
+ if (currentEnvironment !== getEnvironmentId()) return [];
274
+ if (!canUseProjects()) return [];
275
+ return state.deletedProjectIds;
276
+ }
277
+
278
+ function canDeleteProject(projectId) {
279
+ if (!projectId) return false;
280
+ if (!canUseProjects()) return false;
281
+ if (state.busyProjectId) return false;
282
+ return !state.deletedProjectIds.includes(projectId);
283
+ }
284
+
285
+ async function deleteProject(projectId, projectName = projectId) {
286
+ synchronizeProjectRuntime();
287
+ if (!canDeleteProject(projectId)) return false;
288
+ const environmentId = getEnvironmentId();
289
+ const token = revision;
290
+ const target = JSON.stringify(state.projects.find((project) => project.id === projectId));
291
+ const confirmed = await confirmAction(
292
+ 'Delete "' + projectName + '"? Its conversations will move to Conversations. The working folder and its files will not be deleted.',
293
+ );
294
+ if (!confirmed) return false;
295
+ if (!isCurrentEnvironment(environmentId, token)) return false;
296
+ if (!canDeleteProject(projectId)) return false;
297
+ if (JSON.stringify(state.projects.find((project) => project.id === projectId)) !== target) return false;
298
+ listRevision += 1;
299
+ state = { ...state, busyProjectId: projectId, loading: false };
300
+ publish();
301
+ let deleted = false;
302
+ try {
303
+ await client.deleteProject(projectId, environmentId);
304
+ if (!isCurrentEnvironment(environmentId, token)) return false;
305
+ deleted = true;
306
+ listRevision += 1;
307
+ state = { ...state,
308
+ projects: state.projects.filter((project) => project.id !== projectId),
309
+ deletedProjectIds: [...new Set([...state.deletedProjectIds, projectId])],
310
+ loading: false,
311
+ };
312
+ publish();
313
+ await loadSessions();
314
+ return isCurrentEnvironment(environmentId, token);
315
+ } catch (error) {
316
+ if (!isCurrentEnvironment(environmentId, token)) return false;
317
+ notify(errorMessage(error), "failed");
318
+ return deleted;
319
+ } finally {
320
+ if (isCurrentEnvironment(environmentId, token)) {
321
+ state = { ...state, busyProjectId: "" };
322
+ publish();
323
+ }
324
+ }
325
+ }
326
+
268
327
  function retainedProjectDraft(environmentChanged) {
269
328
  if (environmentChanged) return null;
270
329
  if (!state.draft) return null;
@@ -289,7 +348,7 @@ export function createProjectsController({
289
348
  listRevision += 1;
290
349
  browseRevision += 1;
291
350
  activationRevision += 1;
292
- state = { projects: [], loading: false, error: "", draft, busyProjectId: "" };
351
+ state = { projects: [], deletedProjectIds: [], loading: false, error: "", draft, busyProjectId: "" };
293
352
  publish();
294
353
  return true;
295
354
  }
@@ -314,5 +373,7 @@ export function createProjectsController({
314
373
  browse,
315
374
  create,
316
375
  newConversation,
376
+ deleteProject,
377
+ getDeletedProjectIds,
317
378
  };
318
379
  }
@@ -0,0 +1,17 @@
1
+ import type { ModelReasoningPreference } from "../../../shared/model-reasoning.js";
2
+ import type { ConversationReasoningPreferences, ReasoningPreferenceScope } from "../services/conversation-reasoning-preferences.js";
3
+ import type { ReasoningProfile } from "../lib/reasoning-preference.js";
4
+ export declare function createReasoningBudgetController(options: {
5
+ state: { reasoningBudgetMenuOpen?: boolean };
6
+ dom: { reasoningBudgetButton?: HTMLButtonElement; reasoningBudgetMenu?: HTMLElement; reasoningBudgetControl?: HTMLElement; agentModeButton?: HTMLButtonElement };
7
+ preferences: ConversationReasoningPreferences;
8
+ getScope(): ReasoningPreferenceScope;
9
+ getProfile(): ReasoningProfile | null;
10
+ onApplied?(): void;
11
+ isModeBusy?(): boolean;
12
+ recordControlEvent?(event: { type: string; name: string; tone: string; summary: string }): void;
13
+ }): {
14
+ render(): boolean;
15
+ isSaving(): boolean;
16
+ selectedPreference(): ModelReasoningPreference | undefined;
17
+ };
@@ -0,0 +1,80 @@
1
+ import { canChooseReasoningBudget, readReasoningPreferenceField, reasoningPreferenceLabel, renderReasoningPreferenceField, syncReasoningPreferenceField } from "../lib/reasoning-preference.js";
2
+
3
+ export function createReasoningBudgetController({ state, dom, preferences, getScope, getProfile, recordControlEvent, onApplied, isModeBusy = () => false }) {
4
+ let renderedKey;
5
+ let saving = false;
6
+ const isCurrentScope = (scope, profileId) => JSON.stringify(scope) === JSON.stringify(getScope()) && profileId === getProfile()?.id;
7
+ function selectedPreference() {
8
+ const profile = getProfile();
9
+ const preference = preferences?.loadReasoningPreference?.(getScope(), profile?.id || "");
10
+ if (preference && !canChooseReasoningBudget(profile))
11
+ throw new Error("The selected model no longer supports the saved thinking budget. Choose Profile default.");
12
+ return preference;
13
+ }
14
+ function syncControls() {
15
+ const busy = saving || isModeBusy();
16
+ dom.reasoningBudgetButton.disabled = busy;
17
+ if (dom.agentModeButton) dom.agentModeButton.disabled = busy;
18
+ const menu = dom.reasoningBudgetMenu;
19
+ const save = menu.querySelector("[data-save-budget]");
20
+ if (save) save.disabled = busy;
21
+ const mode = menu.querySelector("[data-reasoning-preference-mode]");
22
+ if (mode) mode.disabled = busy;
23
+ const input = menu.querySelector("[data-reasoning-budget]");
24
+ if (input) input.disabled = busy || mode?.value !== "budget";
25
+ }
26
+ function render() {
27
+ const button = dom.reasoningBudgetButton, menu = dom.reasoningBudgetMenu;
28
+ if (!button || !menu) return false;
29
+ const profile = getProfile();
30
+ const preference = preferences?.loadReasoningPreference?.(getScope(), profile?.id || "");
31
+ const available = canChooseReasoningBudget(profile) || Boolean(preference);
32
+ if (dom.reasoningBudgetControl) dom.reasoningBudgetControl.hidden = !available;
33
+ button.hidden = !available;
34
+ if (!available) { renderedKey = undefined; state.reasoningBudgetMenuOpen = false; menu.hidden = true; return false; }
35
+ const labels = { off: "Off", "server-default": "Server default" };
36
+ const label = preference?.mode === "budget" ? `${preference.budgetTokens} tokens` : labels[preference?.mode] || "Profile default";
37
+ button.title = `Thinking budget: ${reasoningPreferenceLabel(preference)}`;
38
+ button.setAttribute("aria-label", button.title);
39
+ button.setAttribute("aria-haspopup", "dialog");
40
+ button.setAttribute("aria-expanded", String(Boolean(state.reasoningBudgetMenuOpen)));
41
+ button.textContent = label;
42
+ button.classList.toggle("open", state.reasoningBudgetMenuOpen);
43
+ menu.classList.toggle("open", state.reasoningBudgetMenuOpen);
44
+ menu.hidden = !state.reasoningBudgetMenuOpen;
45
+ menu.setAttribute("role", "dialog");
46
+ menu.setAttribute("aria-label", "Thinking token budget");
47
+ const nextKey = JSON.stringify([getScope(), profile?.id, canChooseReasoningBudget(profile), preference]);
48
+ if (renderedKey === nextKey && menu.querySelector("[data-save-budget]")) { syncControls(); return true; }
49
+ renderedKey = nextKey;
50
+ menu.innerHTML = `${renderReasoningPreferenceField(profile, preference)}
51
+ <button type="button" data-save-budget>Apply to next message</button>
52
+ <p role="alert" data-budget-error hidden></p>`;
53
+ const scope = { ...getScope() };
54
+ menu.querySelector("[data-reasoning-preference-mode]").addEventListener("change", () => syncReasoningPreferenceField(menu, profile));
55
+ menu.querySelector("[data-save-budget]").addEventListener("click", async () => {
56
+ if (saving || isModeBusy()) return;
57
+ let applied = false;
58
+ try {
59
+ const next = readReasoningPreferenceField(menu);
60
+ saving = true; syncControls();
61
+ await preferences.saveReasoningPreference(scope, profile.id, next);
62
+ if (!isCurrentScope(scope, profile.id)) return;
63
+ state.reasoningBudgetMenuOpen = false;
64
+ if (onApplied) onApplied(); else render();
65
+ applied = true;
66
+ } catch (error) {
67
+ if (!isCurrentScope(scope, profile.id)) return;
68
+ const feedback = menu.querySelector("[data-budget-error]");
69
+ feedback.textContent = error.message; feedback.hidden = false;
70
+ recordControlEvent?.({ type: "control", name: "Thinking budget update failed", tone: "failed", summary: error.message });
71
+ } finally {
72
+ saving = false; syncControls();
73
+ if (applied && isCurrentScope(scope, profile.id)) (button.hidden ? dom.agentModeButton : button)?.focus();
74
+ }
75
+ });
76
+ syncControls();
77
+ return true;
78
+ }
79
+ return { render, selectedPreference, isSaving: () => saving };
80
+ }
@@ -0,0 +1,45 @@
1
+ /** Independent thinking-budget popup; effort keeps its own menu and selection. */
2
+ export function bindReasoningBudgetMenu({ state, dom, actions, modelSelector, documentRoot }) {
3
+ const button = dom.reasoningBudgetButton, menu = dom.reasoningBudgetMenu;
4
+ if (!button || !menu) return;
5
+ function close(restoreFocus = false) {
6
+ if (!state.reasoningBudgetMenuOpen) return;
7
+ state.reasoningBudgetMenuOpen = false;
8
+ actions.renderAgentMode();
9
+ if (restoreFocus) button.focus();
10
+ }
11
+ function open() {
12
+ if (button.disabled || dom.reasoningBudgetControl?.hidden) return;
13
+ modelSelector.close();
14
+ state.agentModeMenuOpen = false;
15
+ state.permissionModeMenuOpen = false;
16
+ state.reasoningBudgetMenuOpen = true;
17
+ actions.renderPermissionMode();
18
+ actions.renderAgentMode();
19
+ menu.querySelector("[data-reasoning-preference-mode]")?.focus();
20
+ }
21
+ button.addEventListener("click", (event) => {
22
+ event.stopPropagation();
23
+ if (state.reasoningBudgetMenuOpen) { close(); return; }
24
+ open();
25
+ });
26
+ button.addEventListener("keydown", (event) => {
27
+ if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
28
+ event.preventDefault(); open();
29
+ });
30
+ menu.addEventListener("click", (event) => event.stopPropagation());
31
+ for (const trigger of [dom.agentModeButton, dom.permissionModeButton]) {
32
+ trigger.addEventListener("click", () => close());
33
+ trigger.addEventListener("keydown", (event) => {
34
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") close();
35
+ });
36
+ }
37
+ documentRoot.addEventListener("click", (event) => {
38
+ if (event.target === button || button.contains(event.target) || menu.contains(event.target)) return;
39
+ close();
40
+ });
41
+ documentRoot.addEventListener("keydown", (event) => {
42
+ if (event.key !== "Escape" || event.defaultPrevented || !state.reasoningBudgetMenuOpen) return;
43
+ close(true); event.preventDefault();
44
+ });
45
+ }
@@ -1,5 +1,6 @@
1
- import { escapeAttribute, escapeHtml, textOf } from "../lib/text-format.js";
2
- import { canChooseReasoning } from "../lib/reasoning-controls.js";
1
+ import { escapeHtml, textOf } from "../lib/text-format.js";
2
+ import { agentModeMeta, canChooseReasoning, renderReasoningModeButtons } from "../lib/reasoning-controls.js";
3
+ import { createReasoningBudgetController } from "./reasoning-budget-controller.js";
3
4
  import { createReasoningOverridePrompt } from "../components/reasoning-override-prompt.js";
4
5
 
5
6
  export function normalizeAgentMode(mode) {
@@ -9,25 +10,10 @@ export function normalizeAgentMode(mode) {
9
10
  : "reasoning";
10
11
  }
11
12
 
12
- function agentModeMeta(mode) {
13
- const modes = {
14
- auto: { label: "Auto", description: "Lets the agent choose", icon: "*" },
15
- fast: { label: "Low", description: "Shorter and quicker", icon: "!" },
16
- deep: {
17
- label: "Deep analysis",
18
- description: "More careful responses",
19
- icon: "D",
20
- },
21
- reasoning: {
22
- label: "Reasoning",
23
- description: "Balanced speed and thinking",
24
- icon: "R",
25
- },
26
- };
27
- return modes[normalizeAgentMode(mode)] || modes.reasoning;
28
- }
29
-
30
- export function createReasoningModeController({ state, dom, client, selectedEnvironmentId, selectedModelProfile, reloadModels, recordControlEvent }) {
13
+ export function createReasoningModeController({ state, dom, client, selectedEnvironmentId, selectedModelProfile, reloadModels, recordControlEvent, preferences, getScope }) {
14
+ const budget = createReasoningBudgetController({ state, dom, preferences, getScope, getProfile: selectedModelProfile, recordControlEvent, onApplied: () => renderAgentMode(), isModeBusy: () => agentModeMutationInFlight });
15
+ let agentModeError = "";
16
+ let modeErrorScope;
31
17
  let agentModeLoadRevision = 0;
32
18
  const agentModeMutationRevisions = new Map();
33
19
  let agentModeMutationInFlight = false;
@@ -39,13 +25,14 @@ export function createReasoningModeController({ state, dom, client, selectedEnvi
39
25
  render: () => renderAgentMode(),
40
26
  });
41
27
  function renderAgentMode() {
28
+ budget.render();
42
29
  const allowed = canChooseReasoning(selectedModelProfile());
43
30
  const meta = allowed ? agentModeMeta(state.agentMode) : { label: "Provider default", icon: "—" };
44
31
  dom.agentModeButton.setAttribute("aria-haspopup", allowed ? "menu" : "dialog");
45
32
  dom.agentModeMenu.classList.toggle("reasoning-override-menu", !allowed);
46
33
  dom.agentModeButton.title = `Reasoning depth: ${meta.label}`;
47
34
  dom.agentModeButton.setAttribute("aria-label", `Reasoning depth: ${meta.label}`);
48
- dom.agentModeButton.disabled = agentModeMutationInFlight;
35
+ dom.agentModeButton.disabled = agentModeMutationInFlight || budget.isSaving();
49
36
  dom.agentModeButton.innerHTML = `
50
37
  <span class="agent-mode-icon">${escapeHtml(meta.icon)}</span>
51
38
  <span>${escapeHtml(meta.label)}</span>`;
@@ -61,19 +48,11 @@ export function createReasoningModeController({ state, dom, client, selectedEnvi
61
48
  if (!allowed) { prompt.render(state.agentModeMenuOpen); return; }
62
49
  const restoreFocus = Boolean(dom.agentModeMenu.contains?.(dom.agentModeMenu.ownerDocument?.activeElement));
63
50
  prompt.reset();
64
- dom.agentModeMenu.innerHTML = state.supportedAgentModes
65
- .map((mode) => {
66
- const item = agentModeMeta(mode);
67
- const selected = normalizeAgentMode(mode) === state.agentMode;
68
- return `
69
- <button class="agent-mode-option ${selected ? "selected" : ""}" type="button"
70
- role="menuitemradio" aria-checked="${selected ? "true" : "false"}"
71
- tabindex="${selected ? "0" : "-1"}" data-mode="${escapeAttribute(mode)}" ${agentModeMutationInFlight ? "disabled" : ""}>
72
- <span class="agent-mode-option-icon">${escapeHtml(item.icon)}</span>
73
- <span><strong>${escapeHtml(item.label)}</strong><small>${escapeHtml(item.description)}</small></span>
74
- </button>`;
75
- })
76
- .join("");
51
+ const thinkingOff = preferences?.loadReasoningPreference?.(getScope(), selectedModelProfile()?.id || "")?.mode === "off";
52
+ const modeError = modeErrorScope === JSON.stringify([getScope?.(), selectedModelProfile()?.id]) ? agentModeError : "";
53
+ dom.agentModeMenu.innerHTML = renderReasoningModeButtons(state.agentMode, state.supportedAgentModes, agentModeMutationInFlight || budget.isSaving())
54
+ + `<small class="reasoning-mode-default-note">${thinkingOff ? "Thinking is Off. Choosing a mode turns it back on. " : ""}Sets the default depth; model profile and calibration settings may override it. Token budgets are set separately.</small>
55
+ <p role="alert" data-mode-error${modeError ? "" : " hidden"}>${escapeHtml(modeError)}</p>`;
77
56
  dom.agentModeMenu
78
57
  .querySelectorAll(".agent-mode-option")
79
58
  .forEach((button) => {
@@ -121,10 +100,18 @@ export function createReasoningModeController({ state, dom, client, selectedEnvi
121
100
  }
122
101
 
123
102
  async function setAgentMode(mode) {
124
- if (agentModeMutationInFlight) return false;
103
+ if (agentModeMutationInFlight || budget.isSaving()) return false;
125
104
  if (!canChooseReasoning(selectedModelProfile())) return false;
126
105
  agentModeMutationInFlight = true;
106
+ agentModeError = "";
107
+ const scope = getScope ? { ...getScope() } : undefined;
108
+ const profileId = selectedModelProfile()?.id || "";
109
+ const manualOverride = scope && preferences?.loadReasoningPreference?.(scope, profileId);
110
+ let modeSaved = false;
127
111
  const environmentId = selectedEnvironmentId();
112
+ const isOriginatingSelection = () => environmentId === selectedEnvironmentId()
113
+ && profileId === selectedModelProfile()?.id
114
+ && (!scope || JSON.stringify(scope) === JSON.stringify(getScope()));
128
115
  const revision = agentModeMutationRevisionFor(environmentId) + 1;
129
116
  agentModeMutationRevisions.set(environmentId, revision);
130
117
  const loadRevisionAtStart = ++agentModeLoadRevision;
@@ -133,9 +120,11 @@ export function createReasoningModeController({ state, dom, client, selectedEnvi
133
120
  state.agentMode = requestedMode;
134
121
  state.agentModeMenuOpen = false;
135
122
  renderAgentMode();
136
- dom.agentModeButton.focus();
137
123
  try {
138
124
  const payload = await client.setAgentMode(requestedMode, environmentId);
125
+ modeSaved = true;
126
+ if (environmentId === selectedEnvironmentId()) state.agentMode = normalizeAgentMode(payload.mode);
127
+ if (manualOverride?.mode === "off") await preferences.saveReasoningPreference(scope, profileId, undefined);
139
128
  if (
140
129
  revision !== agentModeMutationRevisionFor(environmentId) ||
141
130
  environmentId !== selectedEnvironmentId()
@@ -153,22 +142,28 @@ export function createReasoningModeController({ state, dom, client, selectedEnvi
153
142
  ) {
154
143
  return false;
155
144
  }
156
- if (agentModeLoadRevision === loadRevisionAtStart) {
145
+ if (!modeSaved && agentModeLoadRevision === loadRevisionAtStart) {
157
146
  state.agentMode = previousMode;
158
147
  renderAgentMode();
159
148
  }
149
+ modeErrorScope = JSON.stringify([scope, profileId]);
150
+ agentModeError = modeSaved
151
+ ? "The reasoning mode was saved, but Thinking Off could not be cleared. " + (error instanceof Error ? error.message : String(error))
152
+ : (error instanceof Error ? error.message : String(error));
153
+ if (isOriginatingSelection()) state.agentModeMenuOpen = true;
160
154
  recordControlEvent({
161
155
  type: "control",
162
156
  name: "Reasoning mode update failed",
163
157
  tone: "failed",
164
- summary: error instanceof Error ? error.message : String(error),
158
+ summary: agentModeError,
165
159
  });
166
160
  return false;
167
161
  } finally {
168
162
  agentModeMutationInFlight = false;
169
163
  renderAgentMode();
164
+ if (isOriginatingSelection() && !state.agentModeMenuOpen) dom.agentModeButton.focus();
170
165
  }
171
166
  }
172
167
 
173
- return { renderAgentMode, loadAgentMode, setAgentMode };
168
+ return { renderAgentMode, loadAgentMode, setAgentMode, selectedReasoningPreference: budget.selectedPreference };
174
169
  }
@@ -93,6 +93,7 @@ export interface RuntimeSelectionControllerDependencies {
93
93
  agentMode: AgentMode;
94
94
  supportedAgentModes: AgentMode[];
95
95
  agentModeMenuOpen: boolean;
96
+ reasoningBudgetMenuOpen?: boolean;
96
97
  permissionModeMenuOpen: boolean;
97
98
  agentPickerOpen: boolean;
98
99
  modelProfiles: Array<
@@ -118,8 +119,11 @@ export interface RuntimeSelectionControllerDependencies {
118
119
  permissionModeMenu: RuntimeSelectionControlMenuSurface;
119
120
  agentModeButton: RuntimeSelectionAgentModeButtonSurface;
120
121
  agentModeMenu: RuntimeSelectionControlMenuSurface;
122
+ reasoningBudgetControl?: HTMLElement;
123
+ reasoningBudgetButton?: HTMLButtonElement;
124
+ reasoningBudgetMenu?: HTMLElement;
121
125
  }>;
122
- readonly preferences: Readonly<{
126
+ readonly preferences: Readonly<Partial<import("../services/conversation-reasoning-preferences.js").ConversationReasoningPreferences> & {
123
127
  loadPinnedSessions(): string[];
124
128
  loadSessionModes(
125
129
  normalize: (value: unknown) => ToolPermissionMode,
@@ -183,6 +187,7 @@ export declare function createRuntimeSelectionController(
183
187
  renderPermissionMode(): void;
184
188
  saveModelPreferences(): void;
185
189
  selectedEnvironmentId(): string;
190
+ selectedReasoningPreference(): import("../../../shared/model-reasoning.js").ModelReasoningPreference | undefined;
186
191
  selectedModelPreference(): Record<string, unknown> | null;
187
192
  selectedModelSupportsImageInput(profileId?: string): boolean;
188
193
  setAgentMode(mode: AgentMode): Promise<boolean>;