mixdog 1.4.0 → 1.4.2

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 (493) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-shipped-history.mjs +115 -33
  3. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  4. package/scripts/gate-local.mjs +183 -63
  5. package/scripts/latest-guard.mjs +21 -9
  6. package/scripts/lib/gate-scheduler.mjs +138 -32
  7. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +91 -66
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +124 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/lib/test-failure-records.mjs +14 -1
  14. package/scripts/lib/test-failure-summary.mjs +16 -4
  15. package/scripts/lib/test-spawn-ledger.mjs +12 -3
  16. package/scripts/post-release-check.mjs +1 -6
  17. package/scripts/pptx-kit-index.mjs +17 -5
  18. package/scripts/suite-health.mjs +115 -24
  19. package/scripts/test-data-dir.mjs +10 -7
  20. package/scripts/test.mjs +9 -14
  21. package/src/agents/advisor/AGENT.md +4 -4
  22. package/src/agents/advisor/agent.json +1 -1
  23. package/src/agents/explore/AGENT.md +22 -0
  24. package/src/agents/explore/agent.json +6 -0
  25. package/src/app.mjs +4 -0
  26. package/src/cli.mjs +7 -0
  27. package/src/defaults/agents.json +7 -0
  28. package/src/defaults/shipped-history.json +23 -2
  29. package/src/defaults/skills/browser-use/SKILL.md +10 -5
  30. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  31. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  32. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  33. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  34. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  35. package/src/defaults/skills/computer-use/SKILL.md +16 -4
  36. package/src/defaults/skills/goal-management/SKILL.md +1 -1
  37. package/src/defaults/skills/setup/references/actions.md +12 -6
  38. package/src/defaults/skills/setup/references/surfaces.md +2 -2
  39. package/src/defaults/skills/setup-guide/SKILL.md +5 -2
  40. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  41. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  42. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  43. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  44. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  45. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  46. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  47. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  48. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  49. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  50. package/src/defaults/skills/visualize/SKILL.md +6 -2
  51. package/src/lib/rules-builder.cjs +35 -42
  52. package/src/output-styles/common.md +2 -2
  53. package/src/output-styles/simple.md +1 -1
  54. package/src/rules/agent/AGENT.md +5 -4
  55. package/src/rules/lead/LEAD.md +12 -7
  56. package/src/rules/shared/10-tool-workflow.md +3 -1
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/45-destructive.md +0 -2
  60. package/src/rules/shared/50-execution.md +2 -0
  61. package/src/rules/shared/60-verification.md +10 -9
  62. package/src/rules/shared/70-delivery.md +8 -9
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
  65. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
  66. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  69. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  70. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
  71. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
  72. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
  79. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
  80. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
  81. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
  82. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
  84. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  85. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  86. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  90. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
  91. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
  92. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  93. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  94. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  95. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  97. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
  99. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  100. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  101. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  102. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  103. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  104. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  105. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  106. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  107. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
  108. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  109. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  110. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  113. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  114. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  115. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  116. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  117. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  129. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  130. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  131. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  132. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  133. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
  135. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  136. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
  137. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  138. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  139. package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
  140. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  141. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  142. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  143. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
  145. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
  147. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
  148. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
  150. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
  151. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  152. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  153. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  154. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  155. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  156. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
  157. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  158. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  159. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  160. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  161. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
  162. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  163. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
  164. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
  165. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  166. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  167. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
  168. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  169. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
  170. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
  171. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
  172. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  174. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
  175. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  179. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
  180. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  181. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  184. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
  185. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
  186. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
  187. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
  188. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
  189. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
  190. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
  192. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
  193. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  194. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  195. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
  196. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  197. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
  198. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
  199. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  200. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
  201. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
  202. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
  203. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  204. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
  209. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  210. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
  211. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  212. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
  213. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  214. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  215. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  217. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
  218. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
  219. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
  221. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  223. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  224. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  225. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  226. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  227. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  228. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  229. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  231. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
  232. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  233. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  234. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  235. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  236. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  237. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  238. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  239. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
  240. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  241. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  243. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
  244. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
  245. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  246. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  248. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  249. package/src/runtime/channels/lib/whisper-port.mjs +29 -11
  250. package/src/runtime/channels/lib/whisper-server.mjs +10 -1
  251. package/src/runtime/computer-bridge/action-schema.mjs +2 -2
  252. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  253. package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
  254. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  255. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  256. package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
  257. package/src/runtime/connectors/gmail-app-password.mjs +3 -3
  258. package/src/runtime/explore/explorer.mjs +93 -0
  259. package/src/runtime/explore/tool-defs.mjs +35 -0
  260. package/src/runtime/explore/tool.mjs +123 -0
  261. package/src/runtime/local-provider/server-process.mjs +2 -1
  262. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  263. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  264. package/src/runtime/memory/index.mjs +4 -0
  265. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  266. package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
  267. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  268. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  269. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  270. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  271. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  272. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  273. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  274. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  275. package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
  276. package/src/runtime/office/quality/design-review.mjs +1 -5
  277. package/src/runtime/office/quality/document-brief.mjs +1 -5
  278. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  279. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  280. package/src/runtime/shared/agent-route-config.mjs +17 -2
  281. package/src/runtime/shared/atomic-file.mjs +103 -2
  282. package/src/runtime/shared/background-tasks.mjs +15 -6
  283. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  284. package/src/runtime/shared/connector-accounts.mjs +5 -5
  285. package/src/runtime/shared/connector-catalog.d.mts +11 -4
  286. package/src/runtime/shared/connector-catalog.mjs +60 -52
  287. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  288. package/src/runtime/shared/defaults-separation.mjs +1 -4
  289. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  290. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  291. package/src/runtime/shared/file-has-data.mjs +26 -2
  292. package/src/runtime/shared/file-lock.mjs +13 -15
  293. package/src/runtime/shared/git-launch.d.mts +9 -0
  294. package/src/runtime/shared/git-launch.mjs +213 -0
  295. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  296. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  297. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  298. package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
  299. package/src/runtime/shared/llm/cost.mjs +11 -2
  300. package/src/runtime/shared/llm/http-agent.mjs +313 -29
  301. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  302. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  303. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  304. package/src/runtime/shared/llm/system-proxy.mjs +452 -0
  305. package/src/runtime/shared/loopback-listener.mjs +25 -2
  306. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  307. package/src/runtime/shared/model-route-chain.mjs +22 -4
  308. package/src/runtime/shared/open-url.mjs +10 -0
  309. package/src/runtime/shared/provider-accounts.mjs +52 -2
  310. package/src/runtime/shared/session-activity-signal.mjs +14 -0
  311. package/src/runtime/shared/session-scratch.mjs +37 -0
  312. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  313. package/src/runtime/shared/staged-update.mjs +47 -2
  314. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  315. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  316. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  317. package/src/runtime/shared/tool-surface.mjs +113 -36
  318. package/src/runtime/shared/tool-work-units.mjs +6 -0
  319. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  320. package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
  321. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  322. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  323. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  324. package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
  325. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  326. package/src/runtime/shared/worktrees/git.mjs +72 -0
  327. package/src/runtime/shared/worktrees/manager.mjs +285 -168
  328. package/src/runtime/shared/worktrees/test-support.mjs +6 -10
  329. package/src/runtime/tidy/install.mjs +95 -15
  330. package/src/runtime/tidy/languages.mjs +17 -15
  331. package/src/runtime/tidy/process.mjs +7 -4
  332. package/src/runtime/tidy/resolve.mjs +19 -16
  333. package/src/runtime/tidy/runners/biome.mjs +3 -3
  334. package/src/runtime/tidy/tool.mjs +1 -1
  335. package/src/runtime/tidy/worktree.mjs +10 -6
  336. package/src/runtime/visualize-bridge/client.mjs +6 -1
  337. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  338. package/src/runtime/web-search/index.mjs +1 -1
  339. package/src/session-runtime/agent-home-delivery.mjs +41 -0
  340. package/src/session-runtime/agent-task-sessions.mjs +458 -312
  341. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  342. package/src/session-runtime/boot/tools.mjs +7 -1
  343. package/src/session-runtime/bot-status.mjs +107 -101
  344. package/src/session-runtime/bot-target.mjs +38 -0
  345. package/src/session-runtime/channel-config-api.mjs +6 -1
  346. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  347. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  348. package/src/session-runtime/conversation-import/discovery.mjs +401 -36
  349. package/src/session-runtime/conversation-import/service.mjs +35 -8
  350. package/src/session-runtime/handoff-attachments.mjs +82 -31
  351. package/src/session-runtime/held-requests.mjs +3 -1
  352. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
  353. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
  354. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
  355. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  356. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  357. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
  358. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  359. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
  360. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
  361. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  362. package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
  363. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  364. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  365. package/src/session-runtime/model-route/set-route.mjs +11 -2
  366. package/src/session-runtime/provider-auth/login.mjs +2 -2
  367. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  368. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  369. package/src/session-runtime/provider-models.mjs +4 -2
  370. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  371. package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
  372. package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
  373. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  374. package/src/session-runtime/resource-recall-api.mjs +6 -1
  375. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  376. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  377. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  378. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  379. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  380. package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
  381. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  382. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
  383. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
  384. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  385. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  386. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  387. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  388. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  389. package/src/session-runtime/services/plugin-admin.mjs +10 -6
  390. package/src/session-runtime/services/provider-admin.mjs +283 -11
  391. package/src/session-runtime/session-turn-api.mjs +2 -0
  392. package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
  393. package/src/session-runtime/settings-system-api.mjs +1 -1
  394. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  395. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  396. package/src/session-runtime/setup-tool/executor.mjs +6 -2
  397. package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
  398. package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
  399. package/src/session-runtime/turn/agent-ops.mjs +23 -0
  400. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
  401. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  402. package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
  403. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  404. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  405. package/src/session-runtime/workspace/session-view.mjs +149 -0
  406. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  407. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  408. package/src/session-runtime/workspace/transitions.mjs +108 -1041
  409. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  410. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  411. package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
  412. package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
  413. package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
  414. package/src/standalone/daemon-desktop-runtime.mjs +2 -0
  415. package/src/standalone/daemon-session-control.mjs +169 -138
  416. package/src/standalone/daemon.mjs +7 -0
  417. package/src/standalone/desktop-service-registry.mjs +9 -0
  418. package/src/standalone/local-session-runtime.mjs +5 -1
  419. package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
  420. package/src/standalone/session-client.mjs +5 -1
  421. package/src/standalone/session-frame-stream.mjs +83 -11
  422. package/src/standalone/session-protocol.mjs +4 -0
  423. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  424. package/src/standalone/session-service/agent-tree.mjs +45 -9
  425. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  426. package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
  427. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  428. package/src/standalone/session-service/stored-reader.mjs +127 -40
  429. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  430. package/src/tui/App.jsx +154 -164
  431. package/src/tui/app/app-view/floating-panel.jsx +10 -4
  432. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  433. package/src/tui/app/clipboard.mjs +21 -10
  434. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  435. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  436. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  437. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  438. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  439. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  440. package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
  441. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  442. package/src/tui/app/provider-setup-picker.mjs +29 -18
  443. package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
  444. package/src/tui/app/slash-commands.mjs +1 -0
  445. package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
  446. package/src/tui/app/slash-dispatch.mjs +1 -1
  447. package/src/tui/app/use-btw-panel.mjs +29 -0
  448. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  449. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  450. package/src/tui/app/use-mouse-input.mjs +11 -0
  451. package/src/tui/app/use-onboarding-start.mjs +8 -3
  452. package/src/tui/app/use-panel-transition.mjs +10 -1
  453. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  454. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  455. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  456. package/src/tui/app/use-prompt-queue-history.mjs +3 -2
  457. package/src/tui/app/use-selection-focus.mjs +11 -2
  458. package/src/tui/app/use-selection-geometry.mjs +18 -9
  459. package/src/tui/app/use-selection-paint.mjs +4 -4
  460. package/src/tui/app/use-selection-stitch.mjs +3 -3
  461. package/src/tui/app/use-slash-palette.mjs +62 -0
  462. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  463. package/src/tui/app/use-transcript-activity.mjs +47 -32
  464. package/src/tui/app/use-transcript-follow.mjs +12 -4
  465. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  466. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  467. package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
  468. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  469. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  470. package/src/tui/app/use-transcript-window.mjs +21 -11
  471. package/src/tui/app/use-tui-ready.mjs +18 -0
  472. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  473. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  474. package/src/tui/components/Picker.jsx +27 -3
  475. package/src/tui/components/QuestionPanel.jsx +13 -4
  476. package/src/tui/components/SignInUrl.jsx +68 -0
  477. package/src/tui/components/TextEntryPanel.jsx +76 -46
  478. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  479. package/src/tui/dist/index.mjs +1963 -1361
  480. package/src/tui/session/goal-turn-state.mjs +6 -2
  481. package/src/tui/session/session-api/controls.mjs +4 -0
  482. package/src/tui/session/session-api/extensions.mjs +8 -0
  483. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  484. package/src/tui/session/session-api/intake.mjs +2 -0
  485. package/src/tui/session/session-api/integrations.mjs +2 -2
  486. package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
  487. package/src/tui/session/session-api/settings.mjs +2 -2
  488. package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
  489. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  490. package/src/tui/session/transcript-spill.mjs +92 -4
  491. package/src/tui/session/transcript-store.mjs +2 -0
  492. package/src/ui/statusline-agents.mjs +1 -3
  493. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
@@ -6,9 +6,13 @@ import { openInBrowser } from '../../../runtime/shared/open-url.mjs';
6
6
  import { providerDetailText } from '../app-format.mjs';
7
7
  import { forgetProviderAuth, keyConsoleUrl, providerStatusFooter } from './provider-items.mjs';
8
8
 
9
- const setApiKeyPrompt = (flow, providerItem) => {
9
+ const VERTEX_EXPRESS_HINT =
10
+ 'Express mode API keys serve Gemini models on the global location only. Claude and MaaS models need a service-account key or the gcloud login.';
11
+
12
+ const setApiKeyPrompt = (flow, providerItem, extra = {}) => {
10
13
  if (!flow.ownsSurface()) return;
11
14
  flow.setProviderPrompt({
15
+ ...extra,
12
16
  kind: 'api-key',
13
17
  providerId: providerItem._providerId,
14
18
  label: providerItem._providerName,
@@ -51,6 +55,28 @@ function apiKeyActions(providerItem, provider) {
51
55
  return { apiActions, keyUrl };
52
56
  }
53
57
 
58
+ // Vertex AI takes either a service-account key or an express-mode API key.
59
+ function openVertexModePicker(flow, providerItem) {
60
+ flow.paint({
61
+ title: `Provider · ${providerItem._providerName}`,
62
+ description: 'Choose the Vertex AI key type.',
63
+ help: '↑/↓ Select · Enter Choose · Esc Back',
64
+ indexMode: 'always',
65
+ labelWidth: 22,
66
+ pickerKey: `providers-vertex-mode:${providerItem.value}`,
67
+ initialIndex: 0,
68
+ items: [
69
+ { value: 'service-account', label: 'Service account key', description: 'service-account JSON' },
70
+ { value: 'api-key', label: 'API key (express mode)', description: 'Gemini only · global location' },
71
+ ],
72
+ onSelect: (mode) => {
73
+ flow.releaseSurface();
74
+ setApiKeyPrompt(flow, providerItem, mode === 'api-key' ? { authMode: 'api-key', hint: VERTEX_EXPRESS_HINT } : {});
75
+ },
76
+ onCancel: () => openApiProviderActions(flow, providerItem),
77
+ });
78
+ }
79
+
54
80
  export function openApiProviderActions(flow, providerItem) {
55
81
  // Reached from acks (a failed forget-key) as well as key presses: prove
56
82
  // ownership at the sink so every caller is covered.
@@ -69,6 +95,10 @@ export function openApiProviderActions(flow, providerItem) {
69
95
  initialIndex: 0,
70
96
  items: apiActions,
71
97
  onSelect: (_detailValue, detail) => {
98
+ if (detail._action === 'set-key' && providerItem._providerId === 'vertex-ai') {
99
+ openVertexModePicker(flow, providerItem);
100
+ return;
101
+ }
72
102
  flow.releaseSurface();
73
103
  if (detail._action === 'set-key') {
74
104
  setApiKeyPrompt(flow, providerItem);
@@ -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
 
@@ -15,11 +16,21 @@ const panelFrame = (providerItem, provider, pickerKey) => ({
15
16
  initialIndex: 0,
16
17
  });
17
18
 
18
- function showOAuthProgress(flow, providerItem, message, onBack) {
19
+ // Shown with every device code: a code someone else hands you signs THEM in to your account.
20
+ // One row that fits 80 columns: it takes the row the status footer did, so the URL
21
+ // keeps its copy-hint row and the "Enter code" line is never replaced by the copy note.
22
+ const DEVICE_CODE_WARNING = [
23
+ { glyph: '!', text: 'Continue only if you started this. Never enter a code someone sent you.' },
24
+ ];
25
+
26
+ function showOAuthProgress(flow, providerItem, message, onBack, detail = '', footer = null) {
19
27
  const provider = providerItem._provider || {};
28
+ const frame = panelFrame(providerItem, provider, `providers-oauth-progress:${providerItem.value}`);
20
29
  flow.paint({
21
- ...panelFrame(providerItem, provider, `providers-oauth-progress:${providerItem.value}`),
30
+ ...frame,
31
+ ...(footer ? { footer } : {}),
22
32
  description: message,
33
+ detail,
23
34
  help: '↑/↓ Select · Enter Choose · Esc Providers',
24
35
  indexMode: 'never',
25
36
  items: [
@@ -27,7 +38,7 @@ function showOAuthProgress(flow, providerItem, message, onBack) {
27
38
  value: 'waiting',
28
39
  label: 'Waiting for login',
29
40
  meta: 'Running',
30
- description: 'finish the browser/OAuth prompt',
41
+ description: 'finish the sign-in shown above',
31
42
  _action: 'waiting',
32
43
  },
33
44
  {
@@ -71,6 +82,21 @@ function showOAuthResult(flow, providerItem, ok, message = '') {
71
82
  });
72
83
  }
73
84
 
85
+ function oauthCodeHint(manualUrl, loginUrl, providerName) {
86
+ if (manualUrl) return 'If the browser callback does not finish, open the URL below manually and paste code#state.';
87
+ if (loginUrl) {
88
+ return `Open the URL below to sign in, then paste the authorization code or full redirect URL for ${providerName}.`;
89
+ }
90
+ return `Paste the authorization code or full redirect URL for ${providerName}.`;
91
+ }
92
+
93
+ // The URL goes in the picker's wrapped `detail` block, never the one-line description.
94
+ function pollingLoginMessage(userCode, loginUrl, opened) {
95
+ if (userCode) return { message: `Enter code ${userCode} at${opened}:`, detail: loginUrl };
96
+ if (loginUrl) return { message: `Open this URL to sign in${opened}:`, detail: loginUrl };
97
+ return { message: 'Finish signing in for this provider.', detail: '' };
98
+ }
99
+
74
100
  /** Login through store.beginOAuthProviderLogin: a code-completing login hands
75
101
  * the surface to the OAuth code prompt; the callback (or the prompt) finishes. */
76
102
  function beginInteractiveOAuthLogin(flow, providerItem, login) {
@@ -91,26 +117,26 @@ function beginInteractiveOAuthLogin(flow, providerItem, login) {
91
117
  message || (ok ? `${providerName} login complete.` : `${providerName} login failed.`)
92
118
  );
93
119
  };
120
+ // Headless machines never try a browser; the URL is shown in the panel either way.
121
+ const openBrowser = canOpenBrowser();
94
122
  void flow.store
95
- .beginOAuthProviderLogin(providerItem._providerId)
123
+ .beginOAuthProviderLogin(providerItem._providerId, { openBrowser })
96
124
  .then((started) => {
125
+ const loginUrl = started?.manualUrl || started?.url || '';
97
126
  if (typeof started?.completeCode === 'function') {
98
127
  // Post-await handover to the OAuth code prompt: only if this flow
99
128
  // still owns the surface (Esc during beginOAuthProviderLogin).
100
129
  if (!flow.ownsSurface()) return;
101
130
  flow.releaseSurface();
102
- const manualUrl = started?.manualUrl || '';
103
131
  flow.setProviderPrompt({
104
132
  kind: 'oauth-code',
105
133
  providerId: providerItem._providerId,
106
134
  providerName,
107
135
  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}.`,
136
+ hint: oauthCodeHint(started?.manualUrl, loginUrl, providerName),
111
137
  // Shown inside the live panel only — never written to the
112
138
  // transcript, so it cannot linger in scrollback after the flow.
113
- detail: manualUrl,
139
+ detail: loginUrl,
114
140
  login: started,
115
141
  afterSave: flow.returnTo,
116
142
  successReturn: () => {
@@ -124,16 +150,24 @@ function beginInteractiveOAuthLogin(flow, providerItem, login) {
124
150
  },
125
151
  });
126
152
  flow.store.pushNotice(
127
- `browser opened for ${providerName}; paste code/redirect here if callback does not finish`,
153
+ openBrowser
154
+ ? `browser opened for ${providerName}; paste code/redirect here if callback does not finish`
155
+ : `open the URL shown to sign in to ${providerName}, then paste the code/redirect here`,
128
156
  'info'
129
157
  );
130
- } else if (started?.userCode) {
131
- flow.store.pushNotice(
132
- `${providerName}: enter code ${started.userCode} in the browser to finish signing in`,
133
- 'info'
158
+ } else if (!login.backedOut && flow.ownsSurface()) {
159
+ // Device-code and URL-only polling logins stay in the progress panel,
160
+ // with the code and URL, until the result panel replaces it or Back.
161
+ const opened = openBrowser ? ' (browser opened)' : '';
162
+ const { message, detail } = pollingLoginMessage(started?.userCode, loginUrl, opened);
163
+ showOAuthProgress(
164
+ flow,
165
+ providerItem,
166
+ message,
167
+ login.onBack,
168
+ detail,
169
+ started?.userCode ? () => DEVICE_CODE_WARNING : null
134
170
  );
135
- } else {
136
- flow.store.pushNotice(`browser opened for ${providerName}; finish signing in there`, 'info');
137
171
  }
138
172
  started.waitForCallback
139
173
  ?.then((result) => {
@@ -171,11 +205,14 @@ function runLegacyOAuthLogin(flow, providerItem, login) {
171
205
  function startOAuthLogin(flow, providerItem) {
172
206
  // Back on the progress panel returns to the actions; a login that settles
173
207
  // 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
- });
208
+ const login = {
209
+ backedOut: false,
210
+ onBack: () => {
211
+ login.backedOut = true;
212
+ openOAuthProviderActions(flow, providerItem);
213
+ },
214
+ };
215
+ showOAuthProgress(flow, providerItem, 'Starting login flow…', login.onBack);
179
216
  if (typeof flow.store.beginOAuthProviderLogin === 'function') {
180
217
  beginInteractiveOAuthLogin(flow, providerItem, login);
181
218
  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
  }
@@ -18,6 +18,25 @@ import {
18
18
 
19
19
  const providerFooter = (item) => providerStatusFooter(item?._provider);
20
20
 
21
+ /** The rows of the main provider list: the continue row, one row per provider,
22
+ * and the client refresh row. */
23
+ function mainListItems(setup, options, canContinue) {
24
+ const items = [];
25
+ if (canContinue && !options.confirmBar) {
26
+ items.push({
27
+ value: 'continue-setup',
28
+ label: options.continueLabel || 'Continue setup',
29
+ description: options.continueDescription || 'return to setup',
30
+ _type: 'continue',
31
+ });
32
+ }
33
+ items.push(...buildProviderItems(setup));
34
+ if (setup.managedByClient === true) {
35
+ items.push({ value: 'refresh-client-providers', label: 'Refresh', _type: 'refresh-client-providers' });
36
+ }
37
+ return items;
38
+ }
39
+
21
40
  export function createProviderSetupPicker({
22
41
  store,
23
42
  surface,
@@ -87,19 +106,7 @@ export function createProviderSetupPicker({
87
106
  if (!setup) return;
88
107
  }
89
108
 
90
- const items = [];
91
- if ((returnTo || onContinue) && !options.confirmBar) {
92
- items.push({
93
- value: 'continue-setup',
94
- label: options.continueLabel || 'Continue setup',
95
- description: options.continueDescription || 'return to setup',
96
- _type: 'continue',
97
- });
98
- }
99
- items.push(...buildProviderItems(setup));
100
- if (setup.managedByClient === true) {
101
- items.push({ value: 'refresh-client-providers', label: 'Refresh', _type: 'refresh-client-providers' });
102
- }
109
+ const items = mainListItems(setup, options, Boolean(returnTo || onContinue));
103
110
 
104
111
  const flow = {
105
112
  store,
@@ -129,13 +136,17 @@ export function createProviderSetupPicker({
129
136
 
130
137
  flow.paint({
131
138
  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.',
139
+ description:
140
+ setup.managedByClient === true
141
+ ? 'Manage provider sign-ins and accounts in the local desktop window. Refresh to update availability.'
142
+ : options.description || 'Choose a provider. Enter opens provider actions.',
135
143
  footer: providerFooter,
136
144
  footerGapRows: 1,
137
- help: options.confirmBar ? undefined : setup.managedByClient === true
138
- ? '↑/↓ Select · Enter Refresh · Esc Back' : '↑/↓ Select · Enter Open · Esc Back',
145
+ help: options.confirmBar
146
+ ? undefined
147
+ : setup.managedByClient === true
148
+ ? '↑/↓ Select · Enter Refresh · Esc Back'
149
+ : '↑/↓ Select · Enter Open · Esc Back',
139
150
  indexMode: 'always',
140
151
  labelWidth: 18,
141
152
  metaWidth: 12,
@@ -4,8 +4,9 @@
4
4
  * welcome banner, floating panel, and the layout signature that names them.
5
5
  */
6
6
  import { isLiveSpinnerMetaVisible } from '../live-spinner-visibility.mjs';
7
- import { promptContentRows, wrappedDetailRows, queuedBandRows } from '../text-layout.mjs';
7
+ import { promptContentRows, queuedBandRows } from '../text-layout.mjs';
8
8
  import { questionPanelRows, questionsOf } from '../../components/question-panel-model.mjs';
9
+ import { signInUrlLayout } from '../../components/sign-in-url-layout.mjs';
9
10
  import { CORE_MULTILINE_TEXT_ENTRY_KINDS } from '../panel-signature.mjs';
10
11
  import { btwPanelRows } from '../btw-controller.mjs';
11
12
 
@@ -49,24 +50,25 @@ function promptBoxBudget(inputBoxHidden, promptLayoutValueRef, promptContentColu
49
50
 
50
51
  // TextEntryPanel content is one prompt line (chrome + 1) for single-line
51
52
  // prompts, or up to PANEL_MAX_VISIBLE wrapped rows for core memory add/edit.
52
- // PLUS an optional wrapped detail block (blank spacer + N wrapped rows — e.g.
53
- // the manual OAuth URL). The floating container clips from the TOP (flex-end +
53
+ // PLUS an optional borderless sign-in URL block under the panel (the manual
54
+ // OAuth URL). The floating container clips from the TOP (flex-end +
54
55
  // overflow hidden), so under-reserving here pushed the bordered title off
55
- // the top of the panel. Width matches the panel interior: frame − 2 border
56
- // − 2 paddingX, same wrap-ansi math ink uses for wrap="wrap".
57
- function textEntryBudget(textEntryPrompt, textEntryLayoutRows, frameColumns) {
56
+ // the top of the panel. The block gets only the rows the terminal leaves
57
+ // (maxFloatingPanelRows minus chrome and content) and TextEntryPanel degrades
58
+ // it to fit, using the same sign-in-url-layout math.
59
+ function textEntryBudget(textEntryPrompt, textEntryLayoutRows, frameColumns, maxFloatingPanelRows) {
58
60
  const textEntryKind = String(textEntryPrompt?.kind || '');
59
61
  const textEntryMultiline = CORE_MULTILINE_TEXT_ENTRY_KINDS.has(textEntryKind);
60
62
  const textEntryDetailText = String(textEntryPrompt?.detail || '').trim();
61
- const textEntryDetailRows = textEntryDetailText
62
- ? 1 + wrappedDetailRows(textEntryDetailText, Math.max(1, frameColumns - 4))
63
- : 0;
64
63
  const textEntryContentRows = textEntryMultiline ? textEntryLayoutRows : 1;
64
+ const textEntryUrlMaxRows = Math.max(0, maxFloatingPanelRows - PANEL_CHROME_ROWS - textEntryContentRows);
65
+ const textEntryDetailRows = signInUrlLayout(textEntryDetailText, frameColumns, textEntryUrlMaxRows).rows;
65
66
  return {
66
67
  textEntryKind,
67
68
  textEntryMultiline,
68
69
  textEntryDetailText,
69
70
  textEntryDetailRows,
71
+ textEntryUrlMaxRows,
70
72
  textEntryContentRows,
71
73
  TEXT_ENTRY_ROWS: PANEL_CHROME_ROWS + textEntryContentRows + textEntryDetailRows,
72
74
  };
@@ -187,7 +189,6 @@ export function computeRowBudgets({
187
189
  const { textEntryPrompt, hasTextEntryPrompt, hasFloatingPanel, expandedOptionPanel, inputBoxHidden } = surfaces;
188
190
  const { liveSpinner, liveSpinnerIsCommand, latestTranscriptItem, inputHint } = hints;
189
191
  const prompt = promptBoxBudget(inputBoxHidden, promptLayoutValueRef, promptContentColumns);
190
- const textEntry = textEntryBudget(textEntryPrompt, textEntryLayoutRows, frameColumns);
191
192
  const OPTION_PANEL_EXTRA_ROWS = expandedOptionPanel ? 3 : 0;
192
193
  const queuedVisible = !hasFloatingPanel && !inputBoxHidden && state.queued?.length > 0;
193
194
  // While the slash palette is open it owns the area above the prompt, so the
@@ -214,6 +215,7 @@ export function computeRowBudgets({
214
215
  const baseReserve =
215
216
  welcome.WELCOME_ROWS + SCROLL_HINT_ROWS + LIVE_STATUS_ROWS + INPUT_BOX_ROWS + STATUSLINE_ROWS + queued.queuedRows;
216
217
  const maxFloatingPanelRows = Math.max(0, resizeState.rows - baseReserve - 1);
218
+ const textEntry = textEntryBudget(textEntryPrompt, textEntryLayoutRows, frameColumns, maxFloatingPanelRows);
217
219
  const panel = floatingPanelBudget({
218
220
  toolApproval,
219
221
  picker,
@@ -41,6 +41,7 @@ export const SLASH_COMMANDS = [
41
41
  params: '[release <task_id> [--confirm]]',
42
42
  description: 'List shells; release one whose termination is unconfirmed',
43
43
  },
44
+ { name: 'stop', usage: '/stop', description: 'Stop every background shell of this session' },
44
45
  {
45
46
  name: 'fork',
46
47
  usage: '/fork',
@@ -4,6 +4,7 @@
4
4
  // while a turn or session command is running.
5
5
  import { presentErrorText } from '../../../runtime/shared/err-text.mjs';
6
6
  import { BTW_USAGE_HINT } from '../btw-controller.mjs';
7
+ import { theme } from '../../theme.mjs';
7
8
 
8
9
  function compactFailureNotice(error) {
9
10
  if (error == null || String(error).trim() === '') return 'Compact failed.';
@@ -168,6 +169,51 @@ export const sessionCommands = {
168
169
  return true;
169
170
  },
170
171
 
172
+ // /stop — stop every background shell of this session (never the running
173
+ // foreground command, agents or other sessions) after one confirmation.
174
+ stop(ctx) {
175
+ const { store, surface } = ctx;
176
+ const stopAll = () =>
177
+ Promise.resolve(store.stopShellJobs?.())
178
+ .then((result) => {
179
+ const stopped = result?.stopped || 0;
180
+ const stopping = result?.stopping || 0;
181
+ store.pushNotice(
182
+ stopping
183
+ ? `Stopped background shells: ${stopped} · still stopping: ${stopping}`
184
+ : `Stopped background shells: ${stopped}`,
185
+ stopping ? 'warn' : 'info'
186
+ );
187
+ })
188
+ .catch((error) => store.pushNotice(String(error?.message || error), 'error'));
189
+ void Promise.resolve(store.listStoppableShellJobs?.())
190
+ .then((result) => {
191
+ const jobs = Array.isArray(result?.jobs) ? result.jobs : [];
192
+ if (!jobs.length) {
193
+ store.pushNotice('No background shells are running.', 'info');
194
+ return;
195
+ }
196
+ const own = surface.claim();
197
+ own.paint({
198
+ title: `Stop background shells (${jobs.length})?`,
199
+ indexMode: 'always',
200
+ labelWidth: 12,
201
+ items: [
202
+ { value: 'cancel', label: 'Cancel' },
203
+ { value: 'stop', label: 'Stop' },
204
+ ],
205
+ footer: jobs.map((job) => ({ glyph: '·', color: theme.warning, text: job.command })),
206
+ onSelect: (value) => {
207
+ own.close();
208
+ if (value === 'stop') void stopAll();
209
+ },
210
+ onCancel: () => own.close(),
211
+ });
212
+ })
213
+ .catch((error) => store.pushNotice(String(error?.message || error), 'error'));
214
+ return true;
215
+ },
216
+
171
217
  doctor(ctx) {
172
218
  const { state, store, deps } = ctx;
173
219
  if (state.commandBusy) {
@@ -17,7 +17,7 @@ import { createSlashPanelOpener } from './slash-dispatch/slash-panel.mjs';
17
17
  const commands = { ...routeCommands, ...sessionCommands, ...panelCommands };
18
18
 
19
19
  export function createSlashDispatch({ state, store, normalizeSlashCommandName, surface, closeUsagePanel, ...deps }) {
20
- const ctx = { state, store, deps, openSlashPanel: createSlashPanelOpener({ surface, store }) };
20
+ const ctx = { state, store, deps, surface, openSlashPanel: createSlashPanelOpener({ surface, store }) };
21
21
  const runSlashCommand = (cmd, arg = '') => {
22
22
  const rawName = String(cmd || '').toLowerCase();
23
23
  cmd = normalizeSlashCommandName(cmd);
@@ -0,0 +1,29 @@
1
+ /*
2
+ * app/use-btw-panel.mjs — the /btw side-question panel: its state, the
3
+ * controller that fills it, and the controller's session/unmount lifecycle.
4
+ */
5
+ import { useEffect, useRef, useState } from 'react';
6
+ import { createBtwController } from './btw-controller.mjs';
7
+
8
+ export function useBtwPanel({ store, sessionId }) {
9
+ const [btwPanel, setBtwPanel] = useState(null);
10
+ const btwRef = useRef(null);
11
+ const sessionIdRef = useRef('');
12
+ sessionIdRef.current = sessionId || '';
13
+ if (!btwRef.current) {
14
+ btwRef.current = createBtwController({
15
+ getStore: () => store,
16
+ setPanel: setBtwPanel,
17
+ getSessionId: () => sessionIdRef.current,
18
+ });
19
+ }
20
+ const btw = btwRef.current;
21
+ // A side answer belongs to the conversation it was asked in: drop it on a
22
+ // session change (new/resume/clear/switch) and cancel it on unmount.
23
+ // biome-ignore lint/correctness/useExhaustiveDependencies(sessionId): session-change trigger; the controller reads the id through its getter
24
+ useEffect(() => {
25
+ btw.sync();
26
+ }, [btw, sessionId]);
27
+ useEffect(() => () => btw.dispose(), [btw]);
28
+ return { btwPanel, btw };
29
+ }
@@ -0,0 +1,31 @@
1
+ /*
2
+ * app/use-context-panel-refresh.mjs — keeps an open /context breakdown panel
3
+ * current: it is rebuilt whenever one of the session fields it summarizes
4
+ * changes.
5
+ */
6
+ import { useEffect } from 'react';
7
+
8
+ export function useContextPanelRefresh({ contextPanelKind, state, openContextPicker }) {
9
+ // The deps are the refresh triggers (the fields the breakdown summarizes),
10
+ // not the reads; openContextPicker is rebuilt by its factory every render
11
+ // and must not re-trigger the rebuild.
12
+ // biome-ignore lint/correctness/useExhaustiveDependencies: trigger-keyed refresh over the summarized session fields
13
+ useEffect(() => {
14
+ if (contextPanelKind === 'context') openContextPicker();
15
+ }, [
16
+ contextPanelKind,
17
+ state.stats,
18
+ state.contextWindow,
19
+ state.rawContextWindow,
20
+ state.sessionId,
21
+ state.toolMode,
22
+ state.agentWorkers,
23
+ state.agentJobs,
24
+ state.provider,
25
+ state.model,
26
+ state.effort,
27
+ state.fast,
28
+ state.cwd,
29
+ state.clientHostPid,
30
+ ]);
31
+ }
@@ -20,16 +20,19 @@ export function useModelCatalogCache({ store, onboardingRef }) {
20
20
  // provider-scope cache clear (e.g. after auth) so a stale in-flight
21
21
  // listProviderModels() cannot repopulate the ref after invalidation.
22
22
  const onboardingPrefetchSeqRef = useRef(0);
23
- const clearModelCaches = useCallback((scope = 'all') => {
24
- if (scope === 'all' || scope === 'provider') {
25
- providerModelsCacheRef.current = { models: null, at: 0 };
26
- onboardingRef.current.providerModels = [];
27
- onboardingPrefetchSeqRef.current += 1;
28
- }
29
- if (scope === 'all' || scope === 'webSearch') {
30
- webSearchModelsCacheRef.current = { models: null, at: 0 };
31
- }
32
- }, []);
23
+ const clearModelCaches = useCallback(
24
+ (scope = 'all') => {
25
+ if (scope === 'all' || scope === 'provider') {
26
+ providerModelsCacheRef.current = { models: null, at: 0 };
27
+ onboardingRef.current.providerModels = [];
28
+ onboardingPrefetchSeqRef.current += 1;
29
+ }
30
+ if (scope === 'all' || scope === 'webSearch') {
31
+ webSearchModelsCacheRef.current = { models: null, at: 0 };
32
+ }
33
+ },
34
+ [onboardingRef]
35
+ );
33
36
  // Boot-time catalog prefetch: warm the /model & /agents provider catalog and
34
37
  // the /websearch catalog once at startup so those pickers open instantly from
35
38
  // cache (openModelPicker still TTL-refreshes stale rows in the background).
@@ -316,6 +316,17 @@ export function useMouseInput({
316
316
  isRawModeSupported,
317
317
  store,
318
318
  stdout,
319
+ dragRef,
320
+ lastClickRef,
321
+ slashPaletteRef,
322
+ scrollFocusRef,
323
+ promptMouseSelectionRef,
324
+ frameRowsRef,
325
+ promptBoxRectRef,
326
+ transcriptViewportRef,
327
+ scrollTargetRef,
328
+ setSlashIndex,
329
+ setMeasuredRowsVersion,
319
330
  passthroughCtrlWheelZoom,
320
331
  frameColumns,
321
332
  statuslineBandRows,
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * app/use-onboarding-start.mjs — first-run onboarding gate + wizard launch.
3
3
  */
4
- import { useEffect } from 'react';
4
+ import { useEffect, useRef } from 'react';
5
5
 
6
6
  // First-run gate. The daemon-backed engine store answers any method it does
7
7
  // not implement locally with an async remote call, so a synchronous
@@ -25,10 +25,15 @@ export function useOnboardingStart({
25
25
  store,
26
26
  forceOnboarding,
27
27
  onboardingCompleted,
28
- onboardingStartedRef,
29
28
  setOnboardingActive,
30
29
  openOnboardingAuthStep,
31
30
  }) {
31
+ // Latches the launch so the wizard opens at most once per mount.
32
+ const onboardingStartedRef = useRef(false);
33
+ // openOnboardingAuthStep is rebuilt by the picker factory every render;
34
+ // depending on it would re-run this launch (and cancel its deferred open)
35
+ // on every commit. The launch keys on the gate inputs only.
36
+ // biome-ignore lint/correctness/useExhaustiveDependencies(openOnboardingAuthStep): per-render factory callback; launch keys on gate inputs
32
37
  useEffect(() => {
33
38
  if (onboardingStartedRef.current) return undefined;
34
39
  if (resolveOnboardingCompleted(store, onboardingCompleted) && !forceOnboarding) return undefined;
@@ -41,5 +46,5 @@ export function useOnboardingStart({
41
46
  return () => {
42
47
  canceled = true;
43
48
  };
44
- }, [store, forceOnboarding, onboardingCompleted]);
49
+ }, [store, forceOnboarding, onboardingCompleted, setOnboardingActive]);
45
50
  }
@@ -30,7 +30,16 @@ export function usePanelTransition({
30
30
  if (!hadTransitionClearance) return undefined;
31
31
  const timer = setTimeout(() => setPanelTransitionEpoch((epoch) => epoch + 1), 0);
32
32
  return () => clearTimeout(timer);
33
- }, [panelLayoutSignature, bottomClusterRows, panelTransitionClearRows, panelTransitionGuardRows]);
33
+ }, [
34
+ panelTransitionRef,
35
+ panelCloseInkMaskRowsRef,
36
+ panelLayoutSignature,
37
+ bottomClusterRows,
38
+ panelTransitionClearRows,
39
+ panelTransitionGuardRows,
40
+ setPanelInkMaskEpoch,
41
+ setPanelTransitionEpoch,
42
+ ]);
34
43
  // Record the transcript tail id AFTER every commit so the next render's
35
44
  // spinner-meta-collapse gate (doneTailAppendedThisCommit) can tell a freshly
36
45
  // appended done row from a stale one that was already at the tail.
@@ -48,31 +48,39 @@ function usePastedBufferSlice({ toEntry, formatRef }) {
48
48
  setBuffers(next);
49
49
  }, []);
50
50
 
51
- const register = useCallback((input) => {
52
- const id = nextIdRef.current;
53
- const entry = toEntry(input, id);
54
- if (!entry) return '';
55
- nextIdRef.current = id + 1;
56
- buffersRef.current = { ...buffersRef.current, [id]: entry };
57
- setBuffers(buffersRef.current);
58
- return formatRef(entry);
59
- }, []);
51
+ const register = useCallback(
52
+ (input) => {
53
+ const id = nextIdRef.current;
54
+ const entry = toEntry(input, id);
55
+ if (!entry) return '';
56
+ nextIdRef.current = id + 1;
57
+ buffersRef.current = { ...buffersRef.current, [id]: entry };
58
+ setBuffers(buffersRef.current);
59
+ return formatRef(entry);
60
+ },
61
+ [toEntry, formatRef]
62
+ );
60
63
 
61
64
  return { buffersRef, nextIdRef, install, clearSnapshot, register };
62
65
  }
63
66
 
67
+ // Module-level slice specs keep toEntry/formatRef identities stable, so
68
+ // `register` is created once per mount.
69
+ const IMAGE_SLICE = {
70
+ toEntry: (image, id) => (image?.type === 'image' && image.content ? { ...image, id } : null),
71
+ formatRef: (entry) => formatImageRef(entry.id),
72
+ };
73
+ const TEXT_SLICE = {
74
+ toEntry: (text, id) => {
75
+ const value = String(text ?? '');
76
+ return value ? { id, text: value } : null;
77
+ },
78
+ formatRef: (entry) => formatPastedTextRef(entry.id, entry.text),
79
+ };
80
+
64
81
  export function usePastedBuffers() {
65
- const images = usePastedBufferSlice({
66
- toEntry: (image, id) => (image?.type === 'image' && image.content ? { ...image, id } : null),
67
- formatRef: (entry) => formatImageRef(entry.id),
68
- });
69
- const texts = usePastedBufferSlice({
70
- toEntry: (text, id) => {
71
- const value = String(text ?? '');
72
- return value ? { id, text: value } : null;
73
- },
74
- formatRef: (entry) => formatPastedTextRef(entry.id, entry.text),
75
- });
82
+ const images = usePastedBufferSlice(IMAGE_SLICE);
83
+ const texts = usePastedBufferSlice(TEXT_SLICE);
76
84
 
77
85
  return {
78
86
  pastedImagesRef: images.buffersRef,