mixdog 1.3.5 → 1.4.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 (515) hide show
  1. package/NOTICE.md +2 -2
  2. package/README.md +2 -2
  3. package/package.json +2 -11
  4. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  5. package/scripts/daemon-stub.mjs +1 -1
  6. package/scripts/gate-local.mjs +16 -5
  7. package/scripts/latest-guard.mjs +21 -9
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +37 -37
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +123 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/native-release-status.mjs +2 -2
  14. package/scripts/post-release-check.mjs +1 -6
  15. package/scripts/pptx-kit-index.mjs +17 -4
  16. package/scripts/recall-history-cases.json +1 -1
  17. package/scripts/suite-health.mjs +20 -2
  18. package/scripts/test-data-dir.mjs +10 -7
  19. package/scripts/test.mjs +7 -11
  20. package/src/agents/reviewer/AGENT.md +7 -11
  21. package/src/agents/reviewer/agent.json +1 -1
  22. package/src/app.mjs +4 -0
  23. package/src/defaults/shipped-history.json +22 -1
  24. package/src/defaults/skills/browser-use/SKILL.md +62 -12
  25. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  26. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  27. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  28. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  29. package/src/defaults/skills/computer-use/SKILL.md +35 -9
  30. package/src/defaults/skills/setup/SKILL.md +22 -0
  31. package/src/defaults/skills/setup/references/actions.md +39 -5
  32. package/src/defaults/skills/setup/references/surfaces.md +11 -2
  33. package/src/defaults/skills/visualize/SKILL.md +2 -1
  34. package/src/lib/rules-builder.cjs +39 -20
  35. package/src/output-styles/common.md +2 -2
  36. package/src/output-styles/simple.md +1 -1
  37. package/src/rules/agent/AGENT.md +11 -10
  38. package/src/rules/lead/LEAD.md +23 -20
  39. package/src/rules/shared/05-tool-calls.md +5 -6
  40. package/src/rules/shared/10-tool-workflow.md +4 -0
  41. package/src/rules/shared/45-destructive.md +0 -2
  42. package/src/rules/shared/50-execution.md +2 -0
  43. package/src/rules/shared/60-verification.md +7 -5
  44. package/src/rules/shared/70-delivery.md +7 -9
  45. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
  46. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  47. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  48. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  49. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  50. package/src/runtime/agent/orchestrator/config.mjs +17 -1
  51. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  52. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
  53. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
  54. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  55. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
  56. package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
  57. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
  58. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
  59. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
  60. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
  62. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  63. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  66. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  67. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  70. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
  71. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  72. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
  73. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  74. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  75. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
  76. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  77. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  78. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  79. package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
  80. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  82. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
  83. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  84. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  85. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  87. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  88. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  89. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  90. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  91. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  92. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  93. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  105. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  106. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  107. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
  109. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  110. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  111. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  112. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  113. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
  117. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  118. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  119. package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
  120. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  121. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  122. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
  123. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  124. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  125. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  126. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
  127. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  129. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  130. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
  131. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  132. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  133. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
  134. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  136. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  137. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  138. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
  139. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  140. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  141. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  142. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
  143. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
  144. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  145. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  146. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
  147. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
  148. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
  149. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
  150. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  151. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
  152. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
  153. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
  154. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
  155. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  158. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
  159. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
  160. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  161. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
  162. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  163. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  164. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
  165. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  166. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
  167. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  168. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  170. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  171. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  172. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  173. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  174. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
  175. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  176. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  177. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
  178. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
  179. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  181. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
  182. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
  183. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
  185. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  187. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
  188. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
  189. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
  190. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  191. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
  192. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  193. package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
  194. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  195. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  196. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  197. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  198. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  199. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  200. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  201. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  203. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  204. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
  209. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  210. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  211. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  212. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  213. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
  214. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  215. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  217. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  218. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  221. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  222. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  224. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  225. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
  226. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
  227. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  228. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
  229. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  231. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  232. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  233. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  234. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  235. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  236. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  237. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  238. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  239. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  240. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  241. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
  243. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  244. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  245. package/src/runtime/browser-bridge/client.mjs +73 -8
  246. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  247. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  248. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  249. package/src/runtime/channels/lib/config.mjs +6 -61
  250. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  251. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  252. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  253. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  254. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  255. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  256. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  257. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  258. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  259. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  260. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  261. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  262. package/src/runtime/channels/lib/scheduler.mjs +33 -147
  263. package/src/runtime/channels/lib/schedules-db.mjs +34 -11
  264. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  265. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
  266. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  267. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  268. package/src/runtime/channels/lib/whisper-port.mjs +10 -1
  269. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  270. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  271. package/src/runtime/channels/lib/worker-main.mjs +10 -34
  272. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  273. package/src/runtime/computer-bridge/actions.mjs +9 -1
  274. package/src/runtime/computer-bridge/client.mjs +180 -8
  275. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  276. package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
  277. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  278. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  279. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  280. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  281. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  282. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  283. package/src/runtime/connectors/google-mcp.mjs +10 -12
  284. package/src/runtime/local-provider/server-process.mjs +2 -1
  285. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  286. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  287. package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
  288. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  289. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  290. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  291. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  292. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  293. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  294. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  295. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  296. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  297. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  298. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  299. package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
  300. package/src/runtime/office/quality/design-review.mjs +1 -5
  301. package/src/runtime/office/quality/document-brief.mjs +1 -5
  302. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  303. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  304. package/src/runtime/session-search/session-search-db.mjs +73 -9
  305. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  306. package/src/runtime/shared/abort-race.mjs +89 -0
  307. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  308. package/src/runtime/shared/agent-kind.mjs +4 -3
  309. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  310. package/src/runtime/shared/bounded-download.mjs +8 -3
  311. package/src/runtime/shared/config.mjs +2 -13
  312. package/src/runtime/shared/connector-accounts.mjs +20 -10
  313. package/src/runtime/shared/connector-catalog.d.mts +29 -0
  314. package/src/runtime/shared/connector-catalog.mjs +150 -0
  315. package/src/runtime/shared/connector-triggers.mjs +22 -19
  316. package/src/runtime/shared/defaults-separation.mjs +2 -17
  317. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  318. package/src/runtime/shared/err-text.mjs +24 -15
  319. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  320. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  321. package/src/runtime/shared/file-permissions.d.mts +0 -8
  322. package/src/runtime/shared/file-permissions.mjs +0 -11
  323. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  324. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  325. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  326. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  327. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  328. package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
  329. package/src/runtime/shared/llm/cost.mjs +5 -1
  330. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  331. package/src/runtime/shared/loopback-listener.mjs +25 -2
  332. package/src/runtime/shared/mixy-presence.mjs +22 -0
  333. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  334. package/src/runtime/shared/model-route-chain.mjs +22 -4
  335. package/src/runtime/shared/open-url.mjs +10 -0
  336. package/src/runtime/shared/orchestration.d.mts +2 -0
  337. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  338. package/src/runtime/shared/profile-config.cjs +1 -1
  339. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  340. package/src/runtime/shared/prompt-origin.mjs +21 -0
  341. package/src/runtime/shared/provider-accounts.mjs +7 -1
  342. package/src/runtime/shared/provider-display-name.mjs +29 -0
  343. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  344. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  345. package/src/runtime/shared/routine-trigger.mjs +10 -0
  346. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  347. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  348. package/src/runtime/shared/session-activity-signal.mjs +48 -1
  349. package/src/runtime/shared/session-scratch.mjs +37 -0
  350. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  351. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  352. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  353. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  354. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  355. package/src/runtime/shared/tool-result-summary.mjs +2 -15
  356. package/src/runtime/shared/tool-surface.mjs +3 -0
  357. package/src/runtime/shared/tool-work-units.mjs +2 -0
  358. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  359. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  360. package/src/runtime/shared/worktrees/git.mjs +15 -0
  361. package/src/runtime/shared/worktrees/manager.mjs +87 -38
  362. package/src/runtime/shared/worktrees/test-support.mjs +14 -13
  363. package/src/runtime/terminal-bridge/client.mjs +10 -1
  364. package/src/runtime/visualize-bridge/client.mjs +29 -8
  365. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  366. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  367. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  368. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  369. package/src/session-runtime/agent-home-delivery.mjs +489 -185
  370. package/src/session-runtime/agent-task-sessions.mjs +467 -229
  371. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  372. package/src/session-runtime/boot/apis.mjs +9 -0
  373. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  374. package/src/session-runtime/boot/providers.mjs +3 -0
  375. package/src/session-runtime/boot/tools.mjs +11 -2
  376. package/src/session-runtime/bot-status.mjs +12 -6
  377. package/src/session-runtime/bot-target.mjs +38 -0
  378. package/src/session-runtime/channel-config-api.mjs +6 -1
  379. package/src/session-runtime/config-lifecycle.mjs +6 -0
  380. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  381. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  382. package/src/session-runtime/conversation-import/discovery.mjs +271 -25
  383. package/src/session-runtime/conversation-import/service.mjs +26 -5
  384. package/src/session-runtime/handoff-attachments.mjs +82 -31
  385. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
  386. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
  387. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  388. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
  389. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  390. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  391. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  392. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  393. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  394. package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
  395. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  396. package/src/session-runtime/mixy-heartbeat.mjs +153 -33
  397. package/src/session-runtime/model-route/set-route.mjs +11 -2
  398. package/src/session-runtime/notification-bus.mjs +31 -117
  399. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  400. package/src/session-runtime/notification-listeners.mjs +76 -0
  401. package/src/session-runtime/owned-automation-run.mjs +2 -1
  402. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  403. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  404. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  405. package/src/session-runtime/provider-models.mjs +4 -2
  406. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  407. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  408. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  409. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  410. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  411. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  412. package/src/session-runtime/resource-recall-api.mjs +6 -1
  413. package/src/session-runtime/routine-owner.mjs +40 -9
  414. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  415. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  416. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  417. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  418. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  419. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  420. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
  421. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  422. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  423. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  424. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  425. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  426. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  427. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  428. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  429. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  430. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  431. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  432. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  433. package/src/session-runtime/services/channel-admin.mjs +7 -13
  434. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  435. package/src/session-runtime/services/provider-admin.mjs +2 -1
  436. package/src/session-runtime/services/seeds.mjs +0 -28
  437. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  438. package/src/session-runtime/session-create/session-options.mjs +1 -0
  439. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  440. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  441. package/src/session-runtime/settings-system-api.mjs +13 -1
  442. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  443. package/src/session-runtime/setup-tool/executor.mjs +145 -22
  444. package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
  445. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  446. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
  447. package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
  448. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  449. package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
  450. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  451. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  452. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
  453. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  454. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  455. package/src/session-runtime/workspace/transitions.mjs +25 -0
  456. package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
  457. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  458. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  459. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  460. package/src/standalone/channel-transport.mjs +1 -1
  461. package/src/standalone/daemon-channels-loader.mjs +10 -8
  462. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  463. package/src/standalone/daemon-session-control/request.mjs +51 -0
  464. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  465. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  466. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  467. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  468. package/src/standalone/daemon-session-control.mjs +142 -190
  469. package/src/standalone/daemon.mjs +26 -3
  470. package/src/standalone/session-client.mjs +7 -3
  471. package/src/standalone/session-protocol.mjs +5 -0
  472. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  473. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  474. package/src/standalone/session-service/quota-resume.mjs +3 -0
  475. package/src/standalone/session-service/retention/busy.mjs +65 -1
  476. package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
  477. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  478. package/src/standalone/session-tool-output.mjs +15 -7
  479. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  480. package/src/tui/app/app-view/floating-panel.jsx +7 -4
  481. package/src/tui/app/model-options.mjs +3 -28
  482. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  483. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  484. package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
  485. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  486. package/src/tui/app/provider-setup-picker.mjs +9 -5
  487. package/src/tui/components/QuestionPanel.jsx +13 -4
  488. package/src/tui/dist/index.mjs +133 -92
  489. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  490. package/src/tui/session/initial-state.mjs +3 -0
  491. package/src/tui/session/notice-surface.mjs +7 -1
  492. package/src/tui/session/queue-helpers.mjs +3 -42
  493. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  494. package/src/tui/session/session-api/routes-write.mjs +5 -1
  495. package/src/tui/session/session-api/routes.mjs +1 -0
  496. package/src/tui/session/session-api/settings.mjs +17 -1
  497. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  498. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  499. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  500. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  501. package/src/tui/session/session-flow/drain.mjs +118 -149
  502. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  503. package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
  504. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  505. package/src/tui/session/tool-approval-request.mjs +39 -0
  506. package/src/tui/session/tool-approval-settle.mjs +62 -0
  507. package/src/tui/session/tool-approval.mjs +69 -115
  508. package/src/tui/session/tui-steering-persist.mjs +8 -1
  509. package/src/tui/session/turn-stream.mjs +19 -2
  510. package/src/tui/session/turn.mjs +1 -0
  511. package/src/ui/statusline-agents.mjs +1 -3
  512. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  513. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  514. package/scripts/code-graph-description-contract.mjs +0 -188
  515. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -27,6 +27,7 @@ export const SESSION_READ_ACTIONS = Object.freeze([
27
27
  'getChannelSettings',
28
28
  'getChannelSetup',
29
29
  'getChannelWorkerStatus',
30
+ 'getCacheWarmingSettings',
30
31
  'getCompactionSettings',
31
32
  'getConversationImportJobs',
32
33
  'getDeveloperSettings',
@@ -40,6 +41,7 @@ export const SESSION_READ_ACTIONS = Object.freeze([
40
41
  'getOAuthProviderLoginStatus',
41
42
  'getOutputStyle',
42
43
  'getOrchestrationMode',
44
+ 'getConfiguredOrchestrationMode',
43
45
  'getProfile',
44
46
  'getProviderSetup',
45
47
  'getProviderAccounts',
@@ -211,6 +213,7 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
211
213
  'setAgentRoute',
212
214
  'setAutoClear',
213
215
  'setAutoUpdate',
216
+ 'setCacheWarmingEnabled',
214
217
  'setCompactionSettings',
215
218
  'setCwd',
216
219
  'setDeveloperOption',
@@ -242,6 +245,8 @@ export const SESSION_CONFIGURE_ACTIONS = Object.freeze([
242
245
  'setRecapEnabled',
243
246
  'setAiSessionTitles',
244
247
  'setHeartbeatEnabled',
248
+ 'setHeartbeatInterval',
249
+ 'noteUserInput',
245
250
  'setReactionsEnabled',
246
251
  'setLeadAppearance',
247
252
  'setBotOrder',
@@ -31,6 +31,7 @@ export function createAgentChildFactory({ registry, rehydrateAgentSessions, crea
31
31
  sourceName: spec.sourceName || spec.agent || 'agent',
32
32
  clientHostPid: spec.clientHostPid || null,
33
33
  ...(preset.fallbacks !== undefined ? { routeFallbacks: preset.fallbacks } : {}),
34
+ ...(preset.fallbackSource ? { routeFallbackSource: preset.fallbackSource } : {}),
34
35
  };
35
36
  const created = await createSession({
36
37
  cwd: spec.cwd || process.cwd(),
@@ -5,8 +5,12 @@ import { randomUUID } from 'node:crypto';
5
5
  import { createAgentChildFactory } from './agent-child.mjs';
6
6
  import { partialHandoffTextFromSession } from '../../../runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs';
7
7
  import { attachmentsForIntake } from '../../../runtime/attachments/store.mjs';
8
- import { artifactLines } from '../../../runtime/shared/handoff-artifacts.mjs';
9
- import { collectTurnArtifacts, handoffContent, sessionRoots } from '../../../session-runtime/handoff-attachments.mjs';
8
+ import { producedFileLines } from '../../../runtime/shared/handoff-artifacts.mjs';
9
+ import {
10
+ collectUnreportedWrites,
11
+ handoffContent,
12
+ sessionRoots,
13
+ } from '../../../session-runtime/handoff-attachments.mjs';
10
14
 
11
15
  /** An agent turn's prompt: text, or text with forwarded attachment parts
12
16
  * (handoff-attachments.mjs), never any other shape. */
@@ -25,18 +29,19 @@ export function agentTurnTranscriptMeta(content) {
25
29
  return { sender: 'lead', ...(attachments.length ? { attachments } : {}) };
26
30
  }
27
31
 
28
- /** The artifact lines of the turn that began at `messageStart`; [] on any
29
- * failure to read it (the handoff still goes out). */
30
- async function turnArtifactLines(runtime, messageStart, descriptor) {
32
+ /** The lines for files the turn that began at `messageStart` created or
33
+ * modified and `report` does not already name; [] on any failure to read it
34
+ * (the handoff still goes out). */
35
+ async function turnArtifactLines(runtime, messageStart, descriptor, report) {
31
36
  try {
32
37
  const { messages } = await runtime.readModelMessages(messageStart);
33
38
  const session = runtime.session || descriptor;
34
- const { files, omitted } = collectTurnArtifacts(messages, {
39
+ const { files, omitted } = collectUnreportedWrites(messages, {
35
40
  cwd: descriptor.cwd,
36
41
  roots: sessionRoots(session, descriptor.cwd),
42
+ report,
37
43
  });
38
- // Text only: the caller forwards these by path (an id in text is never trusted).
39
- return artifactLines(files, omitted, { ids: false });
44
+ return producedFileLines(files, omitted);
40
45
  } catch {
41
46
  return [];
42
47
  }
@@ -131,10 +136,9 @@ export function createAgentTurns({
131
136
  }
132
137
  let result = detail?.result || { content: '' };
133
138
  // The files the turn produced reach the owner with its handoff.
134
- const files = await turnArtifactLines(entry.runtime, messageStart, descriptor);
135
- if (files.length) {
136
- result = { ...result, content: [String(result.content || ''), files.join('\n')].join('\n\n') };
137
- }
139
+ const report = String(result.content || '');
140
+ const files = await turnArtifactLines(entry.runtime, messageStart, descriptor, report);
141
+ if (files.length) result = { ...result, content: [report, files.join('\n')].join('\n\n') };
138
142
  descriptor.status = 'idle';
139
143
  descriptor.stage = 'idle';
140
144
  descriptor.lastHandoff = typeof result?.content === 'string' ? result.content : '';
@@ -44,6 +44,9 @@ async function resumeDueEntry(entry, { store, materializeSession, readQuotaUsabl
44
44
  try {
45
45
  usable = await readQuotaUsable(provider, model);
46
46
  } catch (error) {
47
+ // A disconnected PC supplies no quota reading. The scheduler's outer
48
+ // deferral keeps this reservation without spending an exhaustion attempt.
49
+ if (error?.code === 'MODEL_PROXY_UNAVAILABLE') throw error;
47
50
  log(`quota resume usage reading failed provider=${provider}: ${error?.message || error}`);
48
51
  }
49
52
  if (!isCurrent(store, entry)) return 'cancelled';
@@ -7,6 +7,17 @@
7
7
  * turn. The eviction sweep that consumes this lives in ../retention.mjs.
8
8
  */
9
9
  import { activeBackgroundTaskSessionIds, hasActiveBackgroundTasks } from '../../../runtime/shared/background-tasks.mjs';
10
+ import { emitSessionApprovalCardChange } from '../../../runtime/shared/session-activity-signal.mjs';
11
+ import { roomMemberOfSession } from '../../../runtime/agent/orchestrator/session/agent-room.mjs';
12
+
13
+ /** A room member session's copies of the questions of sessions it handed work
14
+ * to (tui/session/tool-approval.mjs `handoffQuestions`); empty for any other
15
+ * session. The room shows them from the member's catalog row (agent-rooms.ts),
16
+ * as no view watches a member session. */
17
+ function roomHandoffQuestionsOf(sessionId, state) {
18
+ if (!roomMemberOfSession(sessionId)) return [];
19
+ return Array.isArray(state?.handoffQuestions) ? state.handoffQuestions : [];
20
+ }
10
21
 
11
22
  export function createBusyTracker({ sessions, currentSessionId }) {
12
23
  function stateBusy(state) {
@@ -18,9 +29,54 @@ export function createBusyTracker({ sessions, currentSessionId }) {
18
29
  function updateEntryBusy(entry, state) {
19
30
  const next = stateBusy(state);
20
31
  entry.busy = next;
32
+ // Every runtime state change passes here, watched or headless: a session
33
+ // that starts or stops showing an approval card (any kind, a sub-agent's
34
+ // delegated copy included) announces it, so the session catalog — the one
35
+ // status source every list row has, open pane or not — re-reads it.
36
+ const awaitingApproval = Boolean(state?.toolApproval);
37
+ const awaitingQuestion = state?.toolApproval?.kind === 'question';
38
+ // A room member's handed-off questions coming and going re-read it too.
39
+ const sessionId = currentSessionId(entry) || '';
40
+ const handoffQuestions = roomHandoffQuestionsOf(sessionId, state)
41
+ .map((question) => String(question?.id ?? ''))
42
+ .join('\n');
43
+ if (
44
+ awaitingApproval !== (entry.awaitingApproval === true) ||
45
+ awaitingQuestion !== (entry.awaitingQuestion === true) ||
46
+ handoffQuestions !== (entry.handoffQuestions ?? '')
47
+ ) {
48
+ entry.awaitingApproval = awaitingApproval;
49
+ entry.awaitingQuestion = awaitingQuestion;
50
+ entry.handoffQuestions = handoffQuestions;
51
+ emitSessionApprovalCardChange(sessionId);
52
+ }
21
53
  return next;
22
54
  }
23
55
 
56
+ /** Room member session id -> its pending handed-off question copies, for
57
+ * every live member runtime holding one. */
58
+ function roomHandoffQuestions() {
59
+ const byMember = new Map();
60
+ for (const entry of sessions) {
61
+ const sessionId = currentSessionId(entry);
62
+ const questions = sessionId ? roomHandoffQuestionsOf(sessionId, entry.runtime?.getState?.()) : [];
63
+ if (questions.length) byMember.set(sessionId, questions);
64
+ }
65
+ return byMember;
66
+ }
67
+
68
+ /** Session id -> the kind of its pending card ('approval' | 'question') for
69
+ * every session whose live runtime shows one waiting on the user. */
70
+ function awaitingApprovalSessionKinds() {
71
+ const kinds = new Map();
72
+ for (const entry of sessions) {
73
+ const sessionId = currentSessionId(entry);
74
+ const pending = sessionId ? entry.runtime?.getState?.()?.toolApproval : null;
75
+ if (pending) kinds.set(sessionId, pending.kind === 'question' ? 'question' : 'approval');
76
+ }
77
+ return kinds;
78
+ }
79
+
24
80
  function sessionBusy(entry) {
25
81
  const sessionId = currentSessionId(entry);
26
82
  // Detached views do not make their background commands disposable. Keep
@@ -65,5 +121,13 @@ export function createBusyTracker({ sessions, currentSessionId }) {
65
121
  return count;
66
122
  }
67
123
 
68
- return { stateBusy, updateEntryBusy, sessionBusy, liveBusyCount, liveTurnBusyCount };
124
+ return {
125
+ stateBusy,
126
+ updateEntryBusy,
127
+ awaitingApprovalSessionKinds,
128
+ roomHandoffQuestions,
129
+ sessionBusy,
130
+ liveBusyCount,
131
+ liveTurnBusyCount,
132
+ };
69
133
  }
@@ -4,6 +4,7 @@
4
4
  import { SESSION_CONFIGURE_ACTION_SET, SESSION_READ_ACTION_SET } from '../../session-protocol.mjs';
5
5
  import { annotateSpan, markPhase } from '../../../runtime/shared/slow-span.mjs';
6
6
  import { sanitizeForWire } from '../../session-wire-values.mjs';
7
+ import { botWorkBySession } from '../../../runtime/shared/bot-owned-work.mjs';
7
8
 
8
9
  /** Reads a session without a live runtime answers from disk (readStoredReview). */
9
10
  const STORED_REVIEW_ACTIONS = new Set([
@@ -40,7 +41,7 @@ export function createSessionActionCalls(ctx) {
40
41
  responseSessionId,
41
42
  } = ctx;
42
43
  const { bodyForClient } = ctx.projection;
43
- const { retainUnwatched } = ctx.retention;
44
+ const { retainUnwatched, awaitingApprovalSessionKinds, roomHandoffQuestions } = ctx.retention;
44
45
  const { assertAvailable, hostedEntryForSession, entryForSession } = ctx.entries;
45
46
 
46
47
  /** A cold session's review, read from its durable turn record (the same
@@ -111,6 +112,33 @@ export function createSessionActionCalls(ctx) {
111
112
  return result;
112
113
  }
113
114
 
115
+ /** Rows with `awaitingApproval` on every session whose live runtime shows an
116
+ * approval card: a list row reads "needs you" from it whether or not any
117
+ * pane receives that session's lane. A room member's row also carries the
118
+ * handed-off questions it holds (`handoffQuestions`), which its room shows.
119
+ * A session holding work a bot sent (bot-owned-work.mjs) carries those bots
120
+ * (`handedBy`): the work there is theirs, and a turn nobody sent (the
121
+ * user's own) is nobody's but the user's. */
122
+ function withApprovalWaits(rows) {
123
+ if (!Array.isArray(rows)) return rows;
124
+ const waiting = awaitingApprovalSessionKinds();
125
+ const questions = roomHandoffQuestions();
126
+ const sent = botWorkBySession();
127
+ if (!waiting.size && !questions.size && !sent.size) return rows;
128
+ return rows.map((row) => {
129
+ const kind = waiting.get(row?.id);
130
+ const asked = questions.get(row?.id);
131
+ const bots = sent.get(row?.id);
132
+ if (!kind && !asked && !bots) return row;
133
+ return {
134
+ ...row,
135
+ ...(kind ? { awaitingApproval: true, ...(kind === 'question' ? { awaitingQuestion: true } : {}) } : {}),
136
+ ...(asked ? { handoffQuestions: asked } : {}),
137
+ ...(bots ? { handedBy: bots } : {}),
138
+ };
139
+ });
140
+ }
141
+
114
142
  async function listSessionCatalog(options = {}) {
115
143
  if (isClosed()) throw new Error('session service is closed');
116
144
  if (typeof listSessions !== 'function') {
@@ -124,7 +152,7 @@ export function createSessionActionCalls(ctx) {
124
152
  });
125
153
  // A `page: { limit, cursor }` request answers one page: { sessions, nextCursor }.
126
154
  const page = listed && !Array.isArray(listed) && Array.isArray(listed.sessions) ? listed : null;
127
- const sessions = page ? page.sessions : listed;
155
+ const sessions = withApprovalWaits(page ? page.sessions : listed);
128
156
  const remoteSession = typeof getRemoteSessionState === 'function' ? await getRemoteSessionState() : null;
129
157
  const nextCursor = typeof page?.nextCursor === 'string' ? page.nextCursor : null;
130
158
  return {
@@ -131,6 +131,14 @@ export function createSessionViewCalls(ctx) {
131
131
  notePrependViewer(viewer, params);
132
132
  const id = String(sessionId || '');
133
133
  if (!id) throw new TypeError('sessionId is required');
134
+ if (params.attachmentHistory === true) {
135
+ // Apart from every window: nothing here reads, fills or replaces a
136
+ // transcript projection.
137
+ const stored =
138
+ typeof readStoredSession === 'function' ? await readStoredSession(id, { attachmentHistory: true }) : null;
139
+ assertAvailable();
140
+ return { history: stored ? { items: stored.items } : null };
141
+ }
134
142
  const live = await liveEntryFor(id);
135
143
  assertAvailable(live);
136
144
  if (params.transcriptRange) {
@@ -7,6 +7,8 @@ import { summarizeToolResult } from '../runtime/shared/tool-result-summary.mjs';
7
7
  import { TOOL_OUTPUT_PAGE_BYTES, TOOL_OUTPUT_TAIL_BYTES } from '../runtime/shared/tool-output-budget.mjs';
8
8
 
9
9
  export const SESSION_TOOL_OUTPUT_BYTES = TOOL_OUTPUT_TAIL_BYTES;
10
+ // A session title as the session tool quotes it, listed or read.
11
+ export const SESSION_TITLE_LIMIT = 160;
10
12
  const MESSAGE_TEXT_LIMIT = 2000;
11
13
  const LIST_PREVIEW_LIMIT = 100;
12
14
  const outputBytes = (value) => Buffer.byteLength(JSON.stringify(value), 'utf8');
@@ -15,24 +17,30 @@ const outputBytes = (value) => Buffer.byteLength(JSON.stringify(value), 'utf8');
15
17
  * `rich` adds the owning bot, last activity, latest line and working state
16
18
  * (never for a background caller: bot-status.mjs scopedBot). `rich` may be a
17
19
  * per-row predicate: a bot gets them only for its own sessions. */
18
- export function sessionListOutput(page, limit, { rich = true } = {}) {
20
+ export function sessionListOutput(page, limit, { rich = true, cursorOf = encodeCatalogCursor } = {}) {
19
21
  const raw = page.sessions;
20
22
  const sessions = raw.slice(0, limit).map((row) => {
21
23
  // Decided first: a session that is not the caller's carries its real
22
24
  // title only, never a preview standing in for it.
23
25
  const own = typeof rich === 'function' ? rich(row) : rich;
24
26
  const title = own ? row.title || row.preview : row.title;
27
+ // Live work, for every caller: its own turn or pool row (`working`)
28
+ // reads `running` whatever the settled catalog status; an Agent session
29
+ // working for it (`agentWorking`) marks it working too.
30
+ const status = row.working === true ? 'running' : row.status;
31
+ const working = row.working === true || row.agentWorking === true ? { working: true } : {};
25
32
  const base = {
26
33
  id: row.id,
27
- ...(title ? { title: escapeHarnessTags(truncateToolText(title, 160)) } : {}),
28
- ...(row.status ? { status: row.status } : {}),
34
+ ...(title ? { title: escapeHarnessTags(truncateToolText(title, SESSION_TITLE_LIMIT)) } : {}),
35
+ ...(status ? { status } : {}),
29
36
  ...(row.cwd ? { cwd: row.cwd } : {}),
30
37
  ...(row.archived === true ? { archived: true } : {}),
31
38
  };
32
- if (!own) return base;
39
+ if (!own) return { ...base, ...working };
33
40
  // The bot it belongs to: its chat, room seat or the task's creator.
34
41
  const bot = sessionBotOf(row);
35
- const lastUsedAt = Number(row.lastUsedAt) || 0;
42
+ // A live row's latest sign of work (`liveAt`) is newer than its last settled turn.
43
+ const lastUsedAt = Math.max(Number(row.lastUsedAt) || 0, Number(row.liveAt) || 0);
36
44
  const preview = String(row.lastMessagePreview || '').replace(/\s+/g, ' ');
37
45
  return {
38
46
  ...base,
@@ -40,7 +48,7 @@ export function sessionListOutput(page, limit, { rich = true } = {}) {
40
48
  ...(lastUsedAt ? { lastUsedAt: new Date(lastUsedAt).toISOString() } : {}),
41
49
  // The latest user or assistant line, quoted data.
42
50
  ...(preview.trim() ? { preview: escapeHarnessTags(truncateToolText(preview, LIST_PREVIEW_LIMIT)) } : {}),
43
- ...(row.working === true || row.agentWorking === true ? { working: true } : {}),
51
+ ...working,
44
52
  };
45
53
  });
46
54
  const result = {
@@ -50,7 +58,7 @@ export function sessionListOutput(page, limit, { rich = true } = {}) {
50
58
  };
51
59
  for (;;) {
52
60
  if (sessions.length < raw.length && sessions.length) {
53
- result.nextCursor = encodeCatalogCursor(raw[sessions.length - 1]);
61
+ result.nextCursor = cursorOf(raw[sessions.length - 1]);
54
62
  }
55
63
  if (outputBytes(result) <= TOOL_OUTPUT_PAGE_BYTES) return result;
56
64
  if (sessions.length <= 1) throw new Error('session: one catalog row exceeds the output budget');
@@ -70,15 +70,18 @@ export function createClientGrace({
70
70
  // tick for as long as the daemon took to go down. A lifecycle client that
71
71
  // attaches again clears the latch, because that daemon is staying up.
72
72
  if (graceTimer || signalled) return;
73
- graceTimer = setTimeout(() => {
74
- graceTimer = null;
75
- if (isClosed() || lifecycleClientCount() > 0) return;
76
- signalled = true;
77
- log(`no clients remain (${reason}) — signalling shutdown`);
78
- try {
79
- onClientsEmpty();
80
- } catch {}
81
- }, lastLifecycleWasRemote ? remoteClientGraceMs() : clientGraceMs);
73
+ graceTimer = setTimeout(
74
+ () => {
75
+ graceTimer = null;
76
+ if (isClosed() || lifecycleClientCount() > 0) return;
77
+ signalled = true;
78
+ log(`no clients remain (${reason}) — signalling shutdown`);
79
+ try {
80
+ onClientsEmpty();
81
+ } catch {}
82
+ },
83
+ lastLifecycleWasRemote ? remoteClientGraceMs() : clientGraceMs
84
+ );
82
85
  graceTimer.unref?.();
83
86
  }
84
87
 
@@ -38,9 +38,7 @@ function renderToolApproval({ toolApproval, store, frameColumns, expandedOptionP
38
38
  onSubmit={(answers) =>
39
39
  store.resolveToolApproval?.(toolApproval.id, { approved: true, reason: 'answered by user', answers })
40
40
  }
41
- onDismiss={() =>
42
- store.resolveToolApproval?.(toolApproval.id, { approved: false, reason: 'dismissed by user' })
43
- }
41
+ onDismiss={() => store.resolveToolApproval?.(toolApproval.id, { approved: false, reason: 'dismissed by user' })}
44
42
  />
45
43
  );
46
44
  }
@@ -249,7 +247,12 @@ export function renderFloatingPanel(ctx) {
249
247
  }
250
248
  if (btwPanel) {
251
249
  return (
252
- <BtwPanel panel={btwPanel} columns={frameColumns} panelRows={floatingPanelRows} themeEpoch={ctx.state?.themeEpoch || 0} />
250
+ <BtwPanel
251
+ panel={btwPanel}
252
+ columns={frameColumns}
253
+ panelRows={floatingPanelRows}
254
+ themeEpoch={ctx.state?.themeEpoch || 0}
255
+ />
253
256
  );
254
257
  }
255
258
  return null;
@@ -9,6 +9,7 @@ import { theme } from '../theme.mjs';
9
9
  import { displayModelName, effortDisplayLabel } from '../../runtime/shared/model-display.mjs';
10
10
  import { isRollingModelAlias } from '../../runtime/shared/model-alias.mjs';
11
11
  import { describeError } from '../../runtime/shared/error-presentation.mjs';
12
+ import { providerDisplayName } from '../../runtime/shared/provider-display-name.mjs';
12
13
  import { DAYBREAK_PROVIDER, daybreakBlueOn } from '../../runtime/shared/llm/openai-daybreak.mjs';
13
14
 
14
15
  export const parsedModelVersion = (id) => {
@@ -165,34 +166,8 @@ export const normalizeModelOptions = (models) => {
165
166
  return normalized;
166
167
  };
167
168
 
168
- const PROVIDER_DISPLAY_NAMES = new Map([
169
- ['openai-oauth', 'OpenAI OAuth'],
170
- ['anthropic-oauth', 'Anthropic OAuth'],
171
- ['grok-oauth', 'Grok OAuth'],
172
- ['muse-code-oauth', 'Muse Code'],
173
- ['command-code-oauth', 'Command Code'],
174
- ['mimo-oauth', 'MiMo'],
175
- ['cursor-oauth', 'Cursor OAuth'],
176
- ['devin-oauth', 'Devin'],
177
- ['antigravity-oauth', 'Antigravity OAuth'],
178
- ['openai', 'OpenAI API'],
179
- ['openai-api', 'OpenAI API'],
180
- ['anthropic', 'Anthropic API'],
181
- ['anthropic-api', 'Anthropic API'],
182
- ['gemini', 'Gemini API'],
183
- ['gemini-api', 'Gemini API'],
184
- ['xai', 'xAI API'],
185
- ['xai-api', 'xAI API'],
186
- ['deepseek', 'DeepSeek API'],
187
- ['deepseek-api', 'DeepSeek API'],
188
- ['opencode-go-oauth', 'OpenCode Go OAuth'],
189
- ['openrouter', 'OpenRouter'],
190
- ['mixdog-local', 'Local Provider'],
191
- ['default', 'Default'],
192
- ]);
193
-
194
- export const providerDisplayName = (provider) =>
195
- PROVIDER_DISPLAY_NAMES.get(String(provider || '').toLowerCase()) ?? (provider || 'Provider');
169
+ // Provider display names live in runtime/shared so error text can name the provider too.
170
+ export { providerDisplayName };
196
171
 
197
172
  export const resolveProviderDisplayName = (provider, providerNames = null) =>
198
173
  (String(provider || '')
@@ -89,9 +89,7 @@ export function createFastParameterSelection({ state, currentRoute, isCurrentRou
89
89
  * on/off) to its next option; false when the model has none. Fast is
90
90
  * dropped when the new parameters rule it out. */
91
91
  const cycleThinking = (model) => {
92
- const definition = (model.modelParameterOptions || []).find((parameter) =>
93
- TOGGLE_PARAMETER_IDS.has(parameter.id)
94
- );
92
+ const definition = (model.modelParameterOptions || []).find((parameter) => TOGGLE_PARAMETER_IDS.has(parameter.id));
95
93
  if (!definition?.options?.length) return false;
96
94
  const wanted = definition.id;
97
95
  const parameters = modelParametersFor(model);
@@ -27,9 +27,10 @@ export function createRouteSelection({ providerModels, state, currentRoute }) {
27
27
  const fastCapable = fast.fastAvailableFor(selected, coercedEffort);
28
28
  const contextSelection = context.contextSelectionFor(selected);
29
29
  const { serviceTier, ...otherParameters } = fast.modelParametersFor(selected);
30
- const modelParameters = serviceTier && fastCapable && fast.getSelectedFast(selected)
31
- ? { ...otherParameters, serviceTier }
32
- : otherParameters;
30
+ const modelParameters =
31
+ serviceTier && fastCapable && fast.getSelectedFast(selected)
32
+ ? { ...otherParameters, serviceTier }
33
+ : otherParameters;
33
34
  return {
34
35
  effort: coercedEffort,
35
36
  routeInput: {
@@ -38,9 +39,7 @@ export function createRouteSelection({ providerModels, state, currentRoute }) {
38
39
  ...(coercedEffort ? { effort: coercedEffort } : {}),
39
40
  ...(contextSelection ? { contextPercent: contextSelection.percent } : {}),
40
41
  ...(selected.fastCapable ? { fast: fastCapable && fast.getSelectedFast(selected) } : {}),
41
- ...((selected.modelParameterOptions || []).length
42
- ? { modelParameters }
43
- : {}),
42
+ ...((selected.modelParameterOptions || []).length ? { modelParameters } : {}),
44
43
  },
45
44
  };
46
45
  };
@@ -3,6 +3,7 @@
3
3
  // progress and result panels, the interactive (code prompt) login through
4
4
  // store.beginOAuthProviderLogin, and the legacy store.loginOAuthProvider
5
5
  // path. `flow` is the per-open picker state built by provider-setup-picker.mjs.
6
+ import { canOpenBrowser } from '../../../runtime/shared/open-url.mjs';
6
7
  import { providerDetailText } from '../app-format.mjs';
7
8
  import { forgetProviderAuth, providerStatusFooter } from './provider-items.mjs';
8
9
 
@@ -27,7 +28,7 @@ function showOAuthProgress(flow, providerItem, message, onBack) {
27
28
  value: 'waiting',
28
29
  label: 'Waiting for login',
29
30
  meta: 'Running',
30
- description: 'finish the browser/OAuth prompt',
31
+ description: 'finish the sign-in shown above',
31
32
  _action: 'waiting',
32
33
  },
33
34
  {
@@ -71,6 +72,20 @@ function showOAuthResult(flow, providerItem, ok, message = '') {
71
72
  });
72
73
  }
73
74
 
75
+ function oauthCodeHint(manualUrl, loginUrl, providerName) {
76
+ if (manualUrl) return 'If the browser callback does not finish, open the URL below manually and paste code#state.';
77
+ if (loginUrl) {
78
+ return `Open the URL below to sign in, then paste the authorization code or full redirect URL for ${providerName}.`;
79
+ }
80
+ return `Paste the authorization code or full redirect URL for ${providerName}.`;
81
+ }
82
+
83
+ function pollingLoginMessage(userCode, loginUrl, opened) {
84
+ if (userCode) return `Enter code ${userCode} at:\n${loginUrl}${opened}`;
85
+ if (loginUrl) return `Open this URL to sign in:\n${loginUrl}${opened}`;
86
+ return 'Finish signing in for this provider.';
87
+ }
88
+
74
89
  /** Login through store.beginOAuthProviderLogin: a code-completing login hands
75
90
  * the surface to the OAuth code prompt; the callback (or the prompt) finishes. */
76
91
  function beginInteractiveOAuthLogin(flow, providerItem, login) {
@@ -91,26 +106,26 @@ function beginInteractiveOAuthLogin(flow, providerItem, login) {
91
106
  message || (ok ? `${providerName} login complete.` : `${providerName} login failed.`)
92
107
  );
93
108
  };
109
+ // Headless machines never try a browser; the URL is shown in the panel either way.
110
+ const openBrowser = canOpenBrowser();
94
111
  void flow.store
95
- .beginOAuthProviderLogin(providerItem._providerId)
112
+ .beginOAuthProviderLogin(providerItem._providerId, { openBrowser })
96
113
  .then((started) => {
114
+ const loginUrl = started?.manualUrl || started?.url || '';
97
115
  if (typeof started?.completeCode === 'function') {
98
116
  // Post-await handover to the OAuth code prompt: only if this flow
99
117
  // still owns the surface (Esc during beginOAuthProviderLogin).
100
118
  if (!flow.ownsSurface()) return;
101
119
  flow.releaseSurface();
102
- const manualUrl = started?.manualUrl || '';
103
120
  flow.setProviderPrompt({
104
121
  kind: 'oauth-code',
105
122
  providerId: providerItem._providerId,
106
123
  providerName,
107
124
  label: `${providerName} OAuth code`,
108
- hint: manualUrl
109
- ? 'If the browser callback does not finish, open the URL below manually and paste code#state.'
110
- : `Paste the authorization code or full redirect URL for ${providerName}.`,
125
+ hint: oauthCodeHint(started?.manualUrl, loginUrl, providerName),
111
126
  // Shown inside the live panel only — never written to the
112
127
  // transcript, so it cannot linger in scrollback after the flow.
113
- detail: manualUrl,
128
+ detail: loginUrl,
114
129
  login: started,
115
130
  afterSave: flow.returnTo,
116
131
  successReturn: () => {
@@ -124,16 +139,16 @@ function beginInteractiveOAuthLogin(flow, providerItem, login) {
124
139
  },
125
140
  });
126
141
  flow.store.pushNotice(
127
- `browser opened for ${providerName}; paste code/redirect here if callback does not finish`,
128
- 'info'
129
- );
130
- } else if (started?.userCode) {
131
- flow.store.pushNotice(
132
- `${providerName}: enter code ${started.userCode} in the browser to finish signing in`,
142
+ openBrowser
143
+ ? `browser opened for ${providerName}; paste code/redirect here if callback does not finish`
144
+ : `open the URL shown to sign in to ${providerName}, then paste the code/redirect here`,
133
145
  'info'
134
146
  );
135
- } else {
136
- flow.store.pushNotice(`browser opened for ${providerName}; finish signing in there`, 'info');
147
+ } else if (!login.backedOut && flow.ownsSurface()) {
148
+ // Device-code and URL-only polling logins stay in the progress panel,
149
+ // with the code and URL, until the result panel replaces it or Back.
150
+ const opened = openBrowser ? ' (browser opened)' : '';
151
+ showOAuthProgress(flow, providerItem, pollingLoginMessage(started?.userCode, loginUrl, opened), login.onBack);
137
152
  }
138
153
  started.waitForCallback
139
154
  ?.then((result) => {
@@ -171,11 +186,14 @@ function runLegacyOAuthLogin(flow, providerItem, login) {
171
186
  function startOAuthLogin(flow, providerItem) {
172
187
  // Back on the progress panel returns to the actions; a login that settles
173
188
  // afterwards becomes a notice instead of a result panel.
174
- const login = { backedOut: false };
175
- showOAuthProgress(flow, providerItem, 'Opening login flow. Complete it in the browser if prompted.', () => {
176
- login.backedOut = true;
177
- openOAuthProviderActions(flow, providerItem);
178
- });
189
+ const login = {
190
+ backedOut: false,
191
+ onBack: () => {
192
+ login.backedOut = true;
193
+ openOAuthProviderActions(flow, providerItem);
194
+ },
195
+ };
196
+ showOAuthProgress(flow, providerItem, 'Starting login flow…', login.onBack);
179
197
  if (typeof flow.store.beginOAuthProviderLogin === 'function') {
180
198
  beginInteractiveOAuthLogin(flow, providerItem, login);
181
199
  return;
@@ -80,8 +80,14 @@ export function buildProviderItems(setup) {
80
80
  if (setup.managedByClient === true) {
81
81
  for (const p of setup.local || []) {
82
82
  providerItems.push({
83
- value: `local:${p.id}`, label: p.name, meta: providerStatusLabel(p), description: '',
84
- _type: 'local', _providerId: p.id, _providerName: p.name, _provider: p,
83
+ value: `local:${p.id}`,
84
+ label: p.name,
85
+ meta: providerStatusLabel(p),
86
+ description: '',
87
+ _type: 'local',
88
+ _providerId: p.id,
89
+ _providerName: p.name,
90
+ _provider: p,
85
91
  });
86
92
  }
87
93
  }
@@ -129,13 +129,17 @@ export function createProviderSetupPicker({
129
129
 
130
130
  flow.paint({
131
131
  title: options.title || 'Providers',
132
- description: setup.managedByClient === true
133
- ? 'Manage provider sign-ins and accounts in the local desktop window. Refresh to update availability.'
134
- : options.description || 'Choose a provider. Enter opens provider actions.',
132
+ description:
133
+ setup.managedByClient === true
134
+ ? 'Manage provider sign-ins and accounts in the local desktop window. Refresh to update availability.'
135
+ : options.description || 'Choose a provider. Enter opens provider actions.',
135
136
  footer: providerFooter,
136
137
  footerGapRows: 1,
137
- help: options.confirmBar ? undefined : setup.managedByClient === true
138
- ? '↑/↓ Select · Enter Refresh · Esc Back' : '↑/↓ Select · Enter Open · Esc Back',
138
+ help: options.confirmBar
139
+ ? undefined
140
+ : setup.managedByClient === true
141
+ ? '↑/↓ Select · Enter Refresh · Esc Back'
142
+ : '↑/↓ Select · Enter Open · Esc Back',
139
143
  indexMode: 'always',
140
144
  labelWidth: 18,
141
145
  metaWidth: 12,