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
@@ -65,6 +65,13 @@ export function usePromptDraftFlow({
65
65
  showPromptHint,
66
66
  slashDismissedFor,
67
67
  syncPromptLayoutRows,
68
+ promptHistoryDraftChangeRef,
69
+ promptHistoryNavRef,
70
+ setPromptDraft,
71
+ setPromptDraftOverride,
72
+ promptHintActiveRef,
73
+ promptHintTimerRef,
74
+ setSlashDismissedFor,
68
75
  ]
69
76
  );
70
77
 
@@ -21,11 +21,11 @@ export function usePromptLayoutRows({
21
21
  const nextRows = promptContentRows(text, promptContentColumns);
22
22
  setPromptLayoutRows((prev) => (prev === nextRows ? prev : nextRows));
23
23
  },
24
- [promptContentColumns]
24
+ [promptContentColumns, promptLayoutValueRef, setPromptLayoutRows]
25
25
  );
26
26
  useEffect(() => {
27
27
  syncPromptLayoutRows(promptLayoutValueRef.current);
28
- }, [syncPromptLayoutRows]);
28
+ }, [syncPromptLayoutRows, promptLayoutValueRef]);
29
29
  useEffect(() => {
30
30
  const kind = String(settingsPrompt?.kind || '');
31
31
  if (!CORE_MULTILINE_TEXT_ENTRY_KINDS.has(kind)) {
@@ -34,6 +34,6 @@ export function usePromptLayoutRows({
34
34
  }
35
35
  const cols = Math.max(1, frameColumns - 4 - stringWidth('Sentence > '));
36
36
  setTextEntryLayoutRows(textEntryReservedRows(settingsPrompt?.initialValue, cols, 8));
37
- }, [settingsPrompt?.kind, settingsPrompt?.initialValue, frameColumns]);
37
+ }, [settingsPrompt?.kind, settingsPrompt?.initialValue, frameColumns, setTextEntryLayoutRows]);
38
38
  return syncPromptLayoutRows;
39
39
  }
@@ -53,7 +53,7 @@ export function usePromptQueueHistory({
53
53
  exit();
54
54
  });
55
55
  }, 60);
56
- }, [store, exit]);
56
+ }, [store, exit, exitRequestedRef, setExiting]);
57
57
 
58
58
  const restoreQueuedToPrompt = useCallback(
59
59
  (options = {}) =>
@@ -74,6 +74,7 @@ export function usePromptQueueHistory({
74
74
  store,
75
75
  state?.queued,
76
76
  promptDraft,
77
+ promptValueRef,
77
78
  showPromptHint,
78
79
  clearPromptHint,
79
80
  installPastedImages,
@@ -94,7 +95,7 @@ export function usePromptQueueHistory({
94
95
 
95
96
  const resetPromptHistoryNav = useCallback(() => {
96
97
  promptHistoryNavRef.current = { active: false, index: -1, seed: '', lastValue: '' };
97
- }, []);
98
+ }, [promptHistoryNavRef]);
98
99
 
99
100
  return { requestExit, restoreQueuedToPrompt, recentPromptHistory, resetPromptHistoryNav };
100
101
  }
@@ -31,7 +31,7 @@ export function useSelectionFocusMove({
31
31
  const shiftedRect = dragRef.current.rect;
32
32
  return { anchor: shiftedRect ? { x: shiftedRect.x1, y: shiftedRect.y1 } : null };
33
33
  },
34
- [scrollTranscriptRows]
34
+ [dragRef, scrollTargetRef, scrollTranscriptRows]
35
35
  );
36
36
 
37
37
  const moveSelectionFocus = useCallback(
@@ -120,7 +120,16 @@ export function useSelectionFocusMove({
120
120
  dragNow.last = { x: col, y: row };
121
121
  return true;
122
122
  },
123
- [applySelectionRect, statusBandRows, transcriptViewportRows, selectionMaxColAtRow, scrollFocusPastEdge]
123
+ [
124
+ dragRef,
125
+ scrollTargetRef,
126
+ transcriptBottomSlackRowsRef,
127
+ applySelectionRect,
128
+ statusBandRows,
129
+ transcriptViewportRows,
130
+ selectionMaxColAtRow,
131
+ scrollFocusPastEdge,
132
+ ]
124
133
  );
125
134
 
126
135
  return moveSelectionFocus;
@@ -22,13 +22,16 @@ export function useSelectionGeometry({
22
22
  transcriptViewportRef,
23
23
  dragRef,
24
24
  }) {
25
- const selectionPointAtCurrentScroll = useCallback((point, pointScroll = 0) => {
26
- if (!point) return null;
27
- return {
28
- x: point.x,
29
- y: point.y + (Number(scrollTargetRef.current) || 0) - (Number(pointScroll) || 0),
30
- };
31
- }, []);
25
+ const selectionPointAtCurrentScroll = useCallback(
26
+ (point, pointScroll = 0) => {
27
+ if (!point) return null;
28
+ return {
29
+ x: point.x,
30
+ y: point.y + (Number(scrollTargetRef.current) || 0) - (Number(pointScroll) || 0),
31
+ };
32
+ },
33
+ [scrollTargetRef]
34
+ );
32
35
 
33
36
  // Grow a word/line multi-click selection from its anchor span out to the
34
37
  // word/line under the cursor. Shared by the mouse handler (motion/release)
@@ -68,9 +71,15 @@ export function useSelectionGeometry({
68
71
  [store, frameColumns, selectionPointAtCurrentScroll]
69
72
  );
70
73
 
71
- const transcriptViewportRows = useCallback(() => transcriptViewportRowRange(transcriptViewportRef.current), []);
74
+ const transcriptViewportRows = useCallback(
75
+ () => transcriptViewportRowRange(transcriptViewportRef.current),
76
+ [transcriptViewportRef]
77
+ );
72
78
 
73
- const statusBandRows = useCallback(() => statusBandRowRange(frameRowsRef.current, statuslineBandRows), []);
79
+ const statusBandRows = useCallback(
80
+ () => statusBandRowRange(frameRowsRef.current, statuslineBandRows),
81
+ [frameRowsRef, statuslineBandRows]
82
+ );
74
83
 
75
84
  const selectionMaxColAtRow = useCallback(
76
85
  (row) => {
@@ -54,12 +54,12 @@ export function useSelectionPaint({
54
54
  .catch(() => {
55
55
  /* best-effort capture: Ctrl+C falls back to the render-time text */
56
56
  });
57
- }, [store]);
57
+ }, [store, selectionTextRef]);
58
58
 
59
59
  // Clip band + theming: use-selection-paint/selection-clip.mjs.
60
60
  const selectionClip = useCallback(
61
61
  () => selectionClipBand({ dragRef, frameRowsRef, transcriptViewportRef, statuslineBandRows }),
62
- [statuslineBandRows]
62
+ [dragRef, frameRowsRef, transcriptViewportRef, statuslineBandRows]
63
63
  );
64
64
 
65
65
  const withSelectionClip = useCallback(
@@ -98,7 +98,7 @@ export function useSelectionPaint({
98
98
  cancelPendingSelectionPaint();
99
99
  paintSelectionRect(clippedRect, { rememberText: true });
100
100
  },
101
- [paintSelectionRect, withSelectionClip, clearStitchBuffer, cancelPendingSelectionPaint]
101
+ [dragRef, selectionTextRef, paintSelectionRect, withSelectionClip, clearStitchBuffer, cancelPendingSelectionPaint]
102
102
  );
103
103
 
104
104
  const applySelectionRectThrottled = useCallback(
@@ -111,7 +111,7 @@ export function useSelectionPaint({
111
111
  cancelPending: cancelPendingSelectionPaint,
112
112
  });
113
113
  },
114
- [paintSelectionRect, withSelectionClip, cancelPendingSelectionPaint]
114
+ [dragRef, paintSelectionRect, withSelectionClip, cancelPendingSelectionPaint]
115
115
  );
116
116
 
117
117
  return {
@@ -64,7 +64,7 @@ export function useSelectionStitchBuffer({ store, dragRef, scrollTargetRef }) {
64
64
  if (!Array.isArray(rows)) return;
65
65
  storeStitchRows(stitchBufferRef.current, rows, stitchHarvestScrollRef.current);
66
66
  }, 0);
67
- }, [store]);
67
+ }, [store, dragRef, scrollTargetRef]);
68
68
 
69
69
  // Synchronous sibling: snapshot the rows CURRENTLY under the selection
70
70
  // immediately, keyed by the given (pre-scroll) offset. Called right before
@@ -80,7 +80,7 @@ export function useSelectionStitchBuffer({ store, dragRef, scrollTargetRef }) {
80
80
  if (!Array.isArray(rows)) return;
81
81
  storeStitchRows(stitchBufferRef.current, rows, Number(scroll) || 0);
82
82
  },
83
- [store]
83
+ [store, dragRef]
84
84
  );
85
85
 
86
86
  // Map the CURRENT rect + current scrollTarget onto the content-key range and
@@ -122,7 +122,7 @@ export function useSelectionStitchBuffer({ store, dragRef, scrollTargetRef }) {
122
122
  }
123
123
  const text = logical.map((l) => l.replace(/\s+$/u, '')).join('\n');
124
124
  return text.trim() ? { text, complete } : empty;
125
- }, []);
125
+ }, [dragRef, scrollTargetRef]);
126
126
 
127
127
  return { clearStitchBuffer, harvestStitchRowsSoon, harvestStitchRowsNow, getStitchedSelectionText };
128
128
  }
@@ -0,0 +1,62 @@
1
+ /*
2
+ * app/use-slash-palette.mjs — the slash / `$skill` palette above the prompt.
3
+ *
4
+ * useSlashPaletteState owns the selection index, the dismissed-draft marker
5
+ * and the live open/count ref the mouse handler reads; it is declared early
6
+ * because the mouse and draft hooks need the setters. useSlashPalette derives
7
+ * the palette for this render from the prompt and the surfaces that suppress
8
+ * it, publishes it to that ref, and keeps the index inside the list.
9
+ */
10
+ import { useEffect, useRef, useState } from 'react';
11
+ import { deriveSlashPalette } from './slash-palette.mjs';
12
+ import { skillMentionQuery, useSkillMentionSkills } from './skill-mention-palette.mjs';
13
+
14
+ export function useSlashPaletteState() {
15
+ const [slashIndex, setSlashIndex] = useState(0);
16
+ const [slashDismissedFor, setSlashDismissedFor] = useState('');
17
+ const slashPaletteRef = useRef({ open: false, count: 0 });
18
+ return { slashIndex, setSlashIndex, slashDismissedFor, setSlashDismissedFor, slashPaletteRef };
19
+ }
20
+
21
+ export function useSlashPalette({
22
+ store,
23
+ slashPaletteRef,
24
+ setSlashIndex,
25
+ slashDismissedFor,
26
+ promptDraft,
27
+ promptCaret,
28
+ providerPrompt,
29
+ settingsPrompt,
30
+ toolApproval,
31
+ contextPanel,
32
+ usagePanel,
33
+ picker,
34
+ exiting,
35
+ commandBusy,
36
+ }) {
37
+ const mentionSkills = useSkillMentionSkills(store, skillMentionQuery(promptDraft, promptCaret) !== null);
38
+ const palette = deriveSlashPalette({
39
+ providerPrompt,
40
+ settingsPrompt,
41
+ toolApproval,
42
+ contextPanel,
43
+ usagePanel,
44
+ picker,
45
+ exiting,
46
+ commandBusy,
47
+ promptDraft,
48
+ slashDismissedFor,
49
+ skills: mentionSkills,
50
+ promptCaret,
51
+ });
52
+ const { activeSlashQuery, slashCommands, slashPaletteOpen } = palette;
53
+ slashPaletteRef.current = { open: slashPaletteOpen, count: slashCommands.length };
54
+
55
+ // A query change re-clamps even when the list length stays the same.
56
+ // biome-ignore lint/correctness/useExhaustiveDependencies(activeSlashQuery): query-change re-clamp trigger
57
+ useEffect(() => {
58
+ setSlashIndex((index) => Math.min(index, Math.max(0, slashCommands.length - 1)));
59
+ }, [slashCommands.length, activeSlashQuery, setSlashIndex]);
60
+
61
+ return palette;
62
+ }
@@ -47,7 +47,7 @@ export function useTerminalChrome({ stdout, isRawModeSupported, setResizeState }
47
47
  if (trailing) clearTimeout(trailing);
48
48
  stdout.off('resize', onResize);
49
49
  };
50
- }, [stdout]);
50
+ }, [stdout, setResizeState]);
51
51
 
52
52
  // Enable extended keyboard reporting (kitty + xterm modifyOtherKeys)
53
53
  // SYNCHRONOUSLY, ONCE, with NO query/round-trip. ink
@@ -61,7 +61,7 @@ export function useTerminalChrome({ stdout, isRawModeSupported, setResizeState }
61
61
  // \x1b[27;5;13~ (or kitty \x1b[13;5u) instead of a bare \r — fixing the old
62
62
  // "first Ctrl+Enter submits, second works" race. Teardown lives in index.jsx's
63
63
  // restoreTerminal(). The empty dep array makes this run exactly once on mount.
64
- // eslint-disable-next-line react-hooks/exhaustive-deps
64
+ // biome-ignore lint/correctness/useExhaustiveDependencies: one-shot mount enable; teardown is owned by restoreTerminal()
65
65
  useEffect(() => {
66
66
  if (!isRawModeSupported || !stdout?.write) return;
67
67
  if (!supportsExtendedKeys()) return;
@@ -105,38 +105,53 @@ export function useTranscriptActivity({ state }) {
105
105
  // StatusLine only reads a small stats subset; engine clones the full stats
106
106
  // object on many updates. Memoize by field value so identical usage keeps
107
107
  // the same object reference and React.memo / effect deps stay quiet.
108
- const statuslineStats = useMemo(() => {
109
- const s = state.stats || {};
110
- return {
111
- currentContextSource: s.currentContextSource ?? null,
112
- currentEstimatedContextTokens: s.currentEstimatedContextTokens ?? 0,
113
- currentContextTokens: s.currentContextTokens ?? null,
114
- contextTokens: s.contextTokens ?? 0,
115
- latestPromptTokens: s.latestPromptTokens ?? 0,
116
- latestInputTokens: s.latestInputTokens ?? 0,
117
- latestCachedTokens: s.latestCachedTokens ?? 0,
118
- latestCacheWriteTokens: s.latestCacheWriteTokens ?? 0,
119
- inputTokens: s.inputTokens ?? 0,
120
- cachedTokens: s.cachedTokens ?? 0,
121
- cacheWriteTokens: s.cacheWriteTokens ?? 0,
122
- promptTokens: s.promptTokens ?? 0,
123
- turns: s.turns ?? 0,
124
- };
125
- }, [
126
- state.stats?.currentContextSource,
127
- state.stats?.currentEstimatedContextTokens,
128
- state.stats?.currentContextTokens,
129
- state.stats?.contextTokens,
130
- state.stats?.latestPromptTokens,
131
- state.stats?.latestInputTokens,
132
- state.stats?.latestCachedTokens,
133
- state.stats?.latestCacheWriteTokens,
134
- state.stats?.inputTokens,
135
- state.stats?.cachedTokens,
136
- state.stats?.cacheWriteTokens,
137
- state.stats?.promptTokens,
138
- state.stats?.turns,
139
- ]);
108
+ const {
109
+ currentContextSource,
110
+ currentEstimatedContextTokens,
111
+ currentContextTokens,
112
+ contextTokens,
113
+ latestPromptTokens,
114
+ latestInputTokens,
115
+ latestCachedTokens,
116
+ latestCacheWriteTokens,
117
+ inputTokens,
118
+ cachedTokens,
119
+ cacheWriteTokens,
120
+ promptTokens,
121
+ turns,
122
+ } = state.stats || {};
123
+ const statuslineStats = useMemo(
124
+ () => ({
125
+ currentContextSource: currentContextSource ?? null,
126
+ currentEstimatedContextTokens: currentEstimatedContextTokens ?? 0,
127
+ currentContextTokens: currentContextTokens ?? null,
128
+ contextTokens: contextTokens ?? 0,
129
+ latestPromptTokens: latestPromptTokens ?? 0,
130
+ latestInputTokens: latestInputTokens ?? 0,
131
+ latestCachedTokens: latestCachedTokens ?? 0,
132
+ latestCacheWriteTokens: latestCacheWriteTokens ?? 0,
133
+ inputTokens: inputTokens ?? 0,
134
+ cachedTokens: cachedTokens ?? 0,
135
+ cacheWriteTokens: cacheWriteTokens ?? 0,
136
+ promptTokens: promptTokens ?? 0,
137
+ turns: turns ?? 0,
138
+ }),
139
+ [
140
+ currentContextSource,
141
+ currentEstimatedContextTokens,
142
+ currentContextTokens,
143
+ contextTokens,
144
+ latestPromptTokens,
145
+ latestInputTokens,
146
+ latestCachedTokens,
147
+ latestCacheWriteTokens,
148
+ inputTokens,
149
+ cachedTokens,
150
+ cacheWriteTokens,
151
+ promptTokens,
152
+ turns,
153
+ ]
154
+ );
140
155
 
141
156
  return { agentRevision, activeTools, statuslineStats };
142
157
  }
@@ -44,11 +44,11 @@ export function useTranscriptFollow({
44
44
  setScrollOffset(Math.max(0, Math.round(scrollPositionRef.current)));
45
45
  }, 16);
46
46
  scrollAnimationRef.current.unref?.();
47
- }, [stopSmoothScroll]);
47
+ }, [scrollPositionRef, scrollTargetRef, followingRef, setScrollOffset, stopSmoothScroll]);
48
48
 
49
49
  const cancelTranscriptFollow = useCallback(() => {
50
50
  followingRef.current = false;
51
- }, []);
51
+ }, [followingRef]);
52
52
 
53
53
  const resetTranscriptScroll = useCallback(() => {
54
54
  stopSmoothScroll();
@@ -65,7 +65,15 @@ export function useTranscriptFollow({
65
65
  // and every new row piled up below the fold.
66
66
  followingRef.current = true;
67
67
  setScrollOffset(0);
68
- }, [stopSmoothScroll]);
68
+ }, [
69
+ scrollPositionRef,
70
+ scrollTargetRef,
71
+ followingRef,
72
+ transcriptAnchorRef,
73
+ transcriptAnchorDirtyRef,
74
+ setScrollOffset,
75
+ stopSmoothScroll,
76
+ ]);
69
77
 
70
78
  const armTranscriptFollow = useCallback(() => {
71
79
  // Do not mutate scrollOffset here. During prompt submit the transcript rows
@@ -78,7 +86,7 @@ export function useTranscriptFollow({
78
86
  pendingReadbackRowsRef.current = 0;
79
87
  followingRef.current = true;
80
88
  stopSmoothScroll();
81
- }, [stopSmoothScroll]);
89
+ }, [followingRef, transcriptAnchorRef, transcriptAnchorDirtyRef, stopSmoothScroll]);
82
90
 
83
91
  return {
84
92
  pendingReadbackRowsRef,
@@ -141,7 +141,7 @@ export function useTranscriptScroll({
141
141
  if (!anchor) return;
142
142
  transcriptAnchorRef.current = anchor;
143
143
  transcriptAnchorDirtyRef.current = false;
144
- }, []);
144
+ }, [transcriptGeomRef, scrollTargetRef, transcriptAnchorRef, transcriptAnchorDirtyRef]);
145
145
 
146
146
  // A manual scroll moves the reading position. Capture the new anchor
147
147
  // SYNCHRONOUSLY from the latest published geometry so the very next render
@@ -149,20 +149,23 @@ export function useTranscriptScroll({
149
149
  // streaming growth could lurch the view. Only at the true bottom drop the
150
150
  // anchor so the bottom-follow path owns the viewport again: a positive
151
151
  // wheel offset is an explicit reading position, even inside the old slack.
152
- const captureReadingAnchor = useCallback((target) => {
153
- if (target === 0) {
154
- transcriptAnchorRef.current = null;
155
- transcriptAnchorDirtyRef.current = false;
156
- return;
157
- }
158
- const anchor = readingAnchorAt(transcriptGeomRef.current || {}, target);
159
- if (anchor) {
160
- transcriptAnchorRef.current = anchor;
161
- transcriptAnchorDirtyRef.current = false;
162
- } else {
163
- transcriptAnchorDirtyRef.current = true;
164
- }
165
- }, []);
152
+ const captureReadingAnchor = useCallback(
153
+ (target) => {
154
+ if (target === 0) {
155
+ transcriptAnchorRef.current = null;
156
+ transcriptAnchorDirtyRef.current = false;
157
+ return;
158
+ }
159
+ const anchor = readingAnchorAt(transcriptGeomRef.current || {}, target);
160
+ if (anchor) {
161
+ transcriptAnchorRef.current = anchor;
162
+ transcriptAnchorDirtyRef.current = false;
163
+ } else {
164
+ transcriptAnchorDirtyRef.current = true;
165
+ }
166
+ },
167
+ [transcriptGeomRef, transcriptAnchorRef, transcriptAnchorDirtyRef]
168
+ );
166
169
 
167
170
  // Scrolling past the oldest/newest loaded edge pages transcript history
168
171
  // instead of moving the target. Returns true when the edge owned the
@@ -190,7 +193,15 @@ export function useTranscriptScroll({
190
193
  }
191
194
  return true;
192
195
  },
193
- [store, captureRestoreAnchor, stopSmoothScroll, cancelTranscriptFollow]
196
+ [
197
+ store,
198
+ scrollTargetRef,
199
+ scrollPositionRef,
200
+ setScrollOffset,
201
+ captureRestoreAnchor,
202
+ stopSmoothScroll,
203
+ cancelTranscriptFollow,
204
+ ]
194
205
  );
195
206
 
196
207
  // Keep a live selection on its content after the viewport moved. An active
@@ -229,7 +240,14 @@ export function useTranscriptScroll({
229
240
  // (Ctrl+C after scrolling then copied just that fragment).
230
241
  paintSelectionRect(clippedRect, { rememberText: false });
231
242
  },
232
- [buildSpanRect, selectionPointAtCurrentScroll, withSelectionClip, cancelPendingSelectionPaint, paintSelectionRect]
243
+ [
244
+ dragRef,
245
+ buildSpanRect,
246
+ selectionPointAtCurrentScroll,
247
+ withSelectionClip,
248
+ cancelPendingSelectionPaint,
249
+ paintSelectionRect,
250
+ ]
233
251
  );
234
252
 
235
253
  const scrollTranscriptRows = useCallback(
@@ -294,6 +312,17 @@ export function useTranscriptScroll({
294
312
  setScrollOffset(Math.round(target));
295
313
  },
296
314
  [
315
+ maxScrollRowsRef,
316
+ transcriptGeomRef,
317
+ scrollTargetRef,
318
+ scrollPositionRef,
319
+ pendingReadbackRowsRef,
320
+ dragRef,
321
+ transcriptAnchorRef,
322
+ transcriptAnchorDirtyRef,
323
+ followingRef,
324
+ selectionLayoutRef,
325
+ setScrollOffset,
297
326
  pageTranscriptHistory,
298
327
  captureReadingAnchor,
299
328
  rebuildSelectionAfterScroll,
@@ -0,0 +1,27 @@
1
+ /*
2
+ * app/use-transcript-swap-reset.mjs — returns the viewport to the live tail
3
+ * when the transcript items are bulk-swapped.
4
+ *
5
+ * Item-count changes never infer follow permission from scrollTarget=0. A
6
+ * first read-back input can be waiting one frame for committed row geometry;
7
+ * only prompt submit, session reset, or an explicit return to bottom arms
8
+ * follow. Pure streaming height growth is handled in the row-delta effect.
9
+ */
10
+ import { useLayoutEffect } from 'react';
11
+ import { transcriptSwapReturnsToTail } from './transcript-window.mjs';
12
+
13
+ export function useTranscriptSwapReset({ items, lastItemsCountRef, lastFirstItemIdRef, resetTranscriptScroll }) {
14
+ useLayoutEffect(() => {
15
+ const count = items.length;
16
+ const previousCount = lastItemsCountRef.current;
17
+ lastItemsCountRef.current = count;
18
+ const firstId = count > 0 ? (items[0]?.id ?? null) : null;
19
+ const previousFirstId = lastFirstItemIdRef.current;
20
+ lastFirstItemIdRef.current = firstId;
21
+ // A bulk swap (compaction included) is an explicit return to the tail: the
22
+ // rows the reader was anchored to no longer exist.
23
+ if (transcriptSwapReturnsToTail({ count, previousCount, firstId, previousFirstId })) {
24
+ resetTranscriptScroll();
25
+ }
26
+ }, [items, lastItemsCountRef, lastFirstItemIdRef, resetTranscriptScroll]);
27
+ }
@@ -81,7 +81,12 @@ export function useTranscriptGeometry(state, props) {
81
81
  // settled-prefix row-index instead of re-walking all N items. Any structural
82
82
  // change misses the cache and falls back to a full rebuild, so the prefix
83
83
  // table is byte-identical to a full rebuild for the settled prefix. All those
84
- // invalidators are folded into the memo deps.
84
+ // invalidators are folded into the memo deps: revision + tailSig stand in
85
+ // for the items/tail identities, and measuredRowsVersion folds in measured
86
+ // corrections.
87
+ // biome-ignore lint/correctness/useExhaustiveDependencies(transcriptItems): keyed by revision + tailSig
88
+ // biome-ignore lint/correctness/useExhaustiveDependencies(streamingTailItem): keyed by tailSig
89
+ // biome-ignore lint/correctness/useExhaustiveDependencies(tailSig): tail id + height recompute key
85
90
  const transcriptRowIndex = useMemo(
86
91
  () =>
87
92
  buildTranscriptRowIndexIncremental(transcriptItems, {
@@ -92,9 +97,8 @@ export function useTranscriptGeometry(state, props) {
92
97
  cacheRef: state.incrementalRowIndexCacheRef,
93
98
  prefixRevision: revision,
94
99
  streamingTailItem,
95
- // eslint-disable-next-line react-hooks/exhaustive-deps -- revision/tail height capture structural geometry; measuredRowsVersion folds in measured corrections
96
100
  }),
97
- [revision, tailSig, frameColumns, toolOutputExpanded, measuredRowsVersion]
101
+ [revision, tailSig, frameColumns, toolOutputExpanded, measuredRowsVersion, state.incrementalRowIndexCacheRef]
98
102
  );
99
103
  const renderScrollOffset = resolveRenderScrollOffset({
100
104
  scrollOffset,
@@ -109,6 +113,10 @@ export function useTranscriptGeometry(state, props) {
109
113
  geomRef: transcriptGeomRef,
110
114
  prevViewportRef: state.prevViewportGeomRef,
111
115
  });
116
+ // transcriptStructureSig stands in for the items identity (it also encodes
117
+ // frameColumns and toolOutputExpanded); scroll/viewport capture the rest.
118
+ // biome-ignore lint/correctness/useExhaustiveDependencies(transcriptItems): keyed by transcriptStructureSig
119
+ // biome-ignore lint/correctness/useExhaustiveDependencies(transcriptStructureSig): items recompute key
112
120
  const transcriptWindow = useMemo(
113
121
  () =>
114
122
  transcriptRenderWindow(transcriptItems, {
@@ -117,9 +125,15 @@ export function useTranscriptGeometry(state, props) {
117
125
  columns: frameColumns,
118
126
  toolOutputExpanded,
119
127
  rowIndex: transcriptRowIndex,
120
- // eslint-disable-next-line react-hooks/exhaustive-deps -- intentional: sig+scroll/viewport capture the relevant changes
121
128
  }),
122
- [transcriptStructureSig, renderScrollOffset, transcriptContentHeight, transcriptRowIndex]
129
+ [
130
+ transcriptStructureSig,
131
+ renderScrollOffset,
132
+ transcriptContentHeight,
133
+ transcriptRowIndex,
134
+ frameColumns,
135
+ toolOutputExpanded,
136
+ ]
123
137
  );
124
138
  publishMaxScrollRows(state, transcriptWindow, { maxScrollRowsRef, frameColumns, toolOutputExpanded });
125
139
  // Publish this frame's geometry so a manual scroll can capture the reading
@@ -65,6 +65,10 @@ export function useTranscriptInstanceState({ sessionKey, scrollOffset, setScroll
65
65
  followingRef.current = true;
66
66
  selectionLayoutRef.current = null;
67
67
  }
68
+ // Runs on a session switch only: normalizedSessionKey is the trigger, and
69
+ // scrollOffset is read (not tracked) so scrolling never re-runs the reset.
70
+ // biome-ignore lint/correctness/useExhaustiveDependencies(normalizedSessionKey): session-switch trigger
71
+ // biome-ignore lint/correctness/useExhaustiveDependencies(scrollOffset): read at switch time only
68
72
  useLayoutEffect(() => {
69
73
  if (scrollOffset !== 0) setScrollOffset(0);
70
74
  }, [normalizedSessionKey, setScrollOffset]);
@@ -40,12 +40,16 @@ export function useSelectionLayoutShift({
40
40
  // with only the still-visible fragment (partial Ctrl+C after scrolling).
41
41
  paintSelectionRect(clippedRect, { rememberText: false });
42
42
  }, [
43
+ transcriptViewportRef,
44
+ selectionLayoutRef,
45
+ dragRef,
43
46
  transcriptContentHeight,
44
47
  transcriptWindow.totalRows,
45
48
  transcriptWindow.effectiveScrollOffset,
46
49
  withSelectionClip,
47
50
  paintSelectionRect,
48
51
  ]);
52
+ // biome-ignore lint/correctness/useExhaustiveDependencies(themeEpoch): theme-change repaint trigger
49
53
  useEffect(() => {
50
54
  if (!dragRef.current.rect) return;
51
55
  const clippedRect = withSelectionClip(dragRef.current.rect);
@@ -53,5 +57,5 @@ export function useSelectionLayoutShift({
53
57
  // Theme repaint: same cells, same text — no need to re-harvest (and a
54
58
  // clipped rect would clobber the remembered full text with a fragment).
55
59
  paintSelectionRect(clippedRect, { rememberText: false });
56
- }, [themeEpoch, withSelectionClip, paintSelectionRect]);
60
+ }, [themeEpoch, dragRef, withSelectionClip, paintSelectionRect]);
57
61
  }