mixdog 1.2.2 → 1.2.4

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 (692) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +6 -4
  4. package/scripts/lib/gate-scheduler.mjs +29 -11
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +599 -0
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/advisor/AGENT.md +1 -1
  9. package/src/agents/advisor/agent.json +1 -1
  10. package/src/agents/maintainer/AGENT.md +1 -1
  11. package/src/agents/maintainer/agent.json +1 -1
  12. package/src/agents/reviewer/AGENT.md +2 -4
  13. package/src/agents/security/AGENT.md +1 -2
  14. package/src/agents/writer/AGENT.md +2 -3
  15. package/src/defaults/shipped-history.json +11 -1
  16. package/src/defaults/skills/image/SKILL.md +21 -23
  17. package/src/defaults/skills/setup/SKILL.md +6 -1
  18. package/src/defaults/skills/setup/references/actions.md +44 -22
  19. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  20. package/src/headless-exec.mjs +15 -8
  21. package/src/lib/keychain-cjs.cjs +20 -15
  22. package/src/output-styles/common.md +11 -10
  23. package/src/rules/agent/AGENT.md +6 -4
  24. package/src/rules/lead/LEAD.md +7 -9
  25. package/src/rules/shared/45-destructive.md +4 -0
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  28. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  29. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  30. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  31. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  32. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  33. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  35. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  36. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
  41. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  42. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
  43. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  45. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
  46. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  48. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  49. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  50. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  51. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  52. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  53. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
  56. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  58. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
  59. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  60. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
  61. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
  63. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  65. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  66. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +39 -5
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
  73. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
  74. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
  75. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
  76. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
  77. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -6
  78. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  79. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  80. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  81. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +29 -5
  82. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  83. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
  84. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
  85. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  86. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  87. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  88. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
  89. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
  90. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
  92. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
  93. package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
  94. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  96. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  97. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  98. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +253 -42
  99. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  100. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  101. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +392 -0
  102. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  103. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  104. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  105. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  106. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  107. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +50 -22
  108. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
  109. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  110. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  111. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  112. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  113. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +92 -16
  114. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
  115. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
  117. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  118. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -7
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +155 -0
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
  128. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  129. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +183 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  138. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  140. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  141. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  142. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +28 -5
  143. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  144. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  145. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  147. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  148. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  150. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  151. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  152. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
  153. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  154. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
  155. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
  156. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  157. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -36
  158. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  159. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  160. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  161. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -9
  162. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
  163. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
  164. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
  165. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
  166. package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
  167. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
  168. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  169. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  170. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +164 -0
  171. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -0
  172. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  173. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +195 -0
  174. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
  175. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  176. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
  177. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  178. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  179. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  180. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  181. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  182. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  183. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +16 -3
  184. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  186. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  187. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  188. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +178 -71
  189. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
  190. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  191. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  192. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  193. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  194. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  195. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  196. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
  197. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  198. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  199. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
  200. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  201. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  202. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
  203. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  204. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  205. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  206. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  207. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  208. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
  209. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  210. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  211. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  212. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -1
  213. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  215. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  216. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -27
  217. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  219. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  220. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
  221. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
  222. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
  223. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  224. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  225. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
  226. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  227. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  228. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  229. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +29 -5
  230. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  231. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
  232. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
  233. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  234. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  235. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
  236. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  237. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
  238. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  239. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  240. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +11 -0
  241. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
  242. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  243. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  244. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  245. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  246. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  247. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
  248. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  249. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  250. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
  251. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
  252. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  253. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
  254. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  255. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
  256. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  257. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  258. package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
  259. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  260. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  261. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
  262. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  263. package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
  264. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
  265. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  266. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  267. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  269. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  270. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  271. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  272. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
  273. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  274. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  275. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  276. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  277. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
  278. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  279. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  280. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  281. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
  282. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  283. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  284. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  285. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
  286. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  287. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  288. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  289. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  290. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
  291. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  292. package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
  293. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
  294. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
  295. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  296. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  297. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  298. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  299. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +79 -0
  300. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  301. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  302. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  303. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  304. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  305. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  306. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  307. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  308. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
  309. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  310. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  311. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  312. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  313. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  314. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  315. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  316. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
  317. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  318. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  319. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  320. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  321. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  322. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  323. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  324. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  325. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  326. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  327. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  328. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  329. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  330. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  331. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  332. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  333. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  334. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  335. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  336. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  337. package/src/runtime/attachments/store.d.mts +9 -0
  338. package/src/runtime/attachments/store.mjs +80 -9
  339. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  340. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  341. package/src/runtime/computer-bridge/action-schema.mjs +219 -196
  342. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  343. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  344. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  345. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  346. package/src/runtime/github/tool.mjs +208 -17
  347. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  348. package/src/runtime/media/catalog.mjs +4 -4
  349. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  350. package/src/runtime/media/defaults.mjs +37 -0
  351. package/src/runtime/media/jobs.mjs +12 -2
  352. package/src/runtime/media/lanes.mjs +12 -0
  353. package/src/runtime/media/tool-defs.mjs +15 -4
  354. package/src/runtime/media/tool.mjs +41 -12
  355. package/src/runtime/media/upstream-error.mjs +72 -6
  356. package/src/runtime/memory/index.mjs +1 -0
  357. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  358. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  359. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  360. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  361. package/src/runtime/memory/lib/pg/process.mjs +36 -33
  362. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  363. package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
  364. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  365. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  366. package/src/runtime/office/README.md +1 -1
  367. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  368. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  369. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  370. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  371. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  372. package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
  373. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  374. package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
  375. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  376. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  377. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  378. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  379. package/src/runtime/office/core/office-sessions.mjs +5 -0
  380. package/src/runtime/office/core/office-transactions.mjs +3 -0
  381. package/src/runtime/office/core/office-write-ledger.mjs +94 -0
  382. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  383. package/src/runtime/office/index.mjs +29 -0
  384. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  385. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  386. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  387. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  388. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  389. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  390. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  391. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  392. package/src/runtime/shared/atomic-file.d.mts +1 -1
  393. package/src/runtime/shared/background-tasks.mjs +6 -1
  394. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  395. package/src/runtime/shared/bounded-line-diff.mjs +191 -0
  396. package/src/runtime/shared/browser-launch.mjs +15 -0
  397. package/src/runtime/shared/buffered-appender.mjs +18 -0
  398. package/src/runtime/shared/config.mjs +78 -18
  399. package/src/runtime/shared/err-text.mjs +48 -4
  400. package/src/runtime/shared/file-lock.mjs +6 -5
  401. package/src/runtime/shared/file-permissions.d.mts +6 -1
  402. package/src/runtime/shared/file-permissions.mjs +54 -6
  403. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  404. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  405. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  406. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  407. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  408. package/src/runtime/shared/loopback-listener.mjs +9 -0
  409. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  410. package/src/runtime/shared/model-route-chain.mjs +48 -0
  411. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  412. package/src/runtime/shared/pid-liveness.mjs +12 -0
  413. package/src/runtime/shared/provider-api-key.mjs +8 -0
  414. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  415. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  416. package/src/runtime/shared/quiet-progress.mjs +101 -0
  417. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  418. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  419. package/src/runtime/shared/remote-intent.mjs +2 -42
  420. package/src/runtime/shared/review-diff.mjs +52 -0
  421. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  422. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  423. package/src/runtime/shared/slow-span.mjs +121 -0
  424. package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
  425. package/src/runtime/shared/tool-card-model/card-header.mjs +7 -1
  426. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  427. package/src/runtime/shared/tool-card-model.mjs +5 -2
  428. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  429. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  430. package/src/runtime/shared/tool-primitives.mjs +13 -0
  431. package/src/runtime/shared/tool-result-summary.mjs +22 -1
  432. package/src/runtime/shared/tool-status.mjs +3 -2
  433. package/src/runtime/shared/tool-surface.mjs +20 -6
  434. package/src/runtime/shared/tool-work-units.mjs +54 -11
  435. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  436. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  437. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  438. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  439. package/src/runtime/shared/transcript-writer.mjs +24 -6
  440. package/src/runtime/shared/turn-changes.mjs +269 -100
  441. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  442. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  443. package/src/runtime/shared/turn-snapshot.mjs +865 -683
  444. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  445. package/src/runtime/shared/user-data-guard.mjs +262 -49
  446. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  447. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  448. package/src/runtime/shared/worktrees/carry.mjs +533 -0
  449. package/src/runtime/shared/worktrees/contract.mjs +60 -0
  450. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  451. package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
  452. package/src/runtime/shared/worktrees/git-head.mjs +214 -0
  453. package/src/runtime/shared/worktrees/git.mjs +8 -3
  454. package/src/runtime/shared/worktrees/include.mjs +125 -7
  455. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  456. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  457. package/src/runtime/shared/worktrees/manager.mjs +525 -31
  458. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  459. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  460. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  461. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  462. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  463. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  464. package/src/runtime/terminal-bridge/client.mjs +57 -20
  465. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  466. package/src/runtime/tidy/apply.mjs +47 -2
  467. package/src/runtime/tidy/run-engines.mjs +11 -5
  468. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  469. package/src/session-runtime/boot/apis.mjs +20 -6
  470. package/src/session-runtime/boot/config.mjs +2 -0
  471. package/src/session-runtime/boot/facade.mjs +4 -0
  472. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  473. package/src/session-runtime/boot/session.mjs +3 -3
  474. package/src/session-runtime/boot/tools.mjs +7 -1
  475. package/src/session-runtime/conversation-import/service.mjs +1 -1
  476. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  477. package/src/session-runtime/goal-facade-api.mjs +2 -2
  478. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
  479. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  480. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
  481. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
  482. package/src/session-runtime/internal-tool-executor.mjs +8 -2
  483. package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
  484. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  485. package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
  486. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  487. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
  488. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  489. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  490. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  491. package/src/session-runtime/lifecycle/teardown.mjs +70 -14
  492. package/src/session-runtime/lifecycle-api.mjs +1 -0
  493. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  494. package/src/session-runtime/media-api.mjs +8 -0
  495. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  496. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  497. package/src/session-runtime/model-route/set-route.mjs +116 -36
  498. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  499. package/src/session-runtime/model-route-api.mjs +4 -2
  500. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  501. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  502. package/src/session-runtime/native-web-search.mjs +19 -9
  503. package/src/session-runtime/new-session-config.mjs +4 -2
  504. package/src/session-runtime/provider-auth/login.mjs +4 -0
  505. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  506. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  507. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  508. package/src/session-runtime/provider-models.mjs +1 -0
  509. package/src/session-runtime/provider-usage.mjs +4 -0
  510. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  511. package/src/session-runtime/route-resolution.mjs +3 -1
  512. package/src/session-runtime/runtime-core.mjs +4 -0
  513. package/src/session-runtime/runtime-facade.mjs +6 -0
  514. package/src/session-runtime/runtime-review-api.mjs +8 -2
  515. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  516. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  517. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  518. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  519. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  520. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  521. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  522. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  523. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  524. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  525. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  526. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  527. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  528. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  529. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  530. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
  531. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  532. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  533. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  534. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  535. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  536. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  537. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  538. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  539. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  540. package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
  541. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  542. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  543. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  544. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  545. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  546. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  547. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  548. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  549. package/src/session-runtime/services/agent-tool/worker-index.mjs +74 -15
  550. package/src/session-runtime/services/agent-tool.mjs +7 -0
  551. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  552. package/src/session-runtime/services/channel-admin.mjs +19 -3
  553. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  554. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  555. package/src/session-runtime/services/provider-admin.mjs +158 -15
  556. package/src/session-runtime/session-create/session-options.mjs +7 -5
  557. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  558. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  559. package/src/session-runtime/session-transcript.mjs +4 -5
  560. package/src/session-runtime/session-turn-api.mjs +17 -14
  561. package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
  562. package/src/session-runtime/setup-tool/executor.mjs +57 -9
  563. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  564. package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
  565. package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
  566. package/src/session-runtime/skills-api.mjs +3 -5
  567. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  568. package/src/session-runtime/tool-surface.mjs +5 -1
  569. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  570. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  571. package/src/session-runtime/turn/session-ops.mjs +7 -5
  572. package/src/session-runtime/turn/side-question-ops.mjs +19 -0
  573. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
  574. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
  575. package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
  576. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  577. package/src/session-runtime/turn/turn-run.mjs +26 -45
  578. package/src/session-runtime/usage-stats-api.mjs +46 -11
  579. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  580. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  581. package/src/session-runtime/workspace/project-branches.mjs +35 -41
  582. package/src/session-runtime/workspace/transition-steps.mjs +215 -116
  583. package/src/session-runtime/workspace/transitions.mjs +428 -73
  584. package/src/standalone/channel-transport.mjs +3 -4
  585. package/src/standalone/daemon-agent-control.mjs +9 -1
  586. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  587. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  588. package/src/standalone/daemon-owner.mjs +17 -4
  589. package/src/standalone/daemon-pg-stop.mjs +49 -0
  590. package/src/standalone/daemon-session-control.mjs +88 -0
  591. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  592. package/src/standalone/daemon-stop-budget.mjs +18 -0
  593. package/src/standalone/daemon-stored-session-views.mjs +25 -3
  594. package/src/standalone/daemon-telemetry.mjs +19 -0
  595. package/src/standalone/daemon.mjs +63 -1
  596. package/src/standalone/desktop-service-registry.mjs +5 -0
  597. package/src/standalone/local-session-runtime.mjs +80 -30
  598. package/src/standalone/session-client.mjs +42 -0
  599. package/src/standalone/session-protocol.mjs +14 -0
  600. package/src/standalone/session-proxy/projection.mjs +41 -4
  601. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  602. package/src/standalone/session-runtime-inline-host.mjs +3 -0
  603. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  604. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  605. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  606. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  607. package/src/standalone/session-service/agent-tree.mjs +28 -2
  608. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  609. package/src/standalone/session-service/entries.mjs +1 -0
  610. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  611. package/src/standalone/session-service/quota-resume.mjs +28 -13
  612. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  613. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  614. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  615. package/src/standalone/session-service-api.mjs +6 -1
  616. package/src/standalone/session-state-patch.d.mts +2 -1
  617. package/src/standalone/session-state-patch.mjs +41 -1
  618. package/src/standalone/session-tool-output.mjs +82 -0
  619. package/src/tui/App.jsx +25 -0
  620. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  621. package/src/tui/app/app-view.jsx +2 -1
  622. package/src/tui/app/btw-controller.mjs +118 -0
  623. package/src/tui/app/create-app-pickers.mjs +2 -0
  624. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  625. package/src/tui/app/provider-setup-picker.mjs +15 -3
  626. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  627. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  628. package/src/tui/app/slash-commands.mjs +19 -3
  629. package/src/tui/app/slash-dispatch/session-commands.mjs +68 -6
  630. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  631. package/src/tui/app/use-global-key-input.mjs +5 -12
  632. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  633. package/src/tui/components/BtwPanel.jsx +53 -0
  634. package/src/tui/components/QuestionPanel.jsx +275 -0
  635. package/src/tui/components/Spinner.jsx +4 -0
  636. package/src/tui/components/SpinnerByline.jsx +21 -2
  637. package/src/tui/components/question-panel-model.mjs +156 -0
  638. package/src/tui/components/status-line/local-line.mjs +10 -2
  639. package/src/tui/dist/index.mjs +2897 -1722
  640. package/src/tui/session/active-tool-summary.mjs +1 -1
  641. package/src/tui/session/context-state.mjs +4 -5
  642. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  643. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  644. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  645. package/src/tui/session/quota-resume.mjs +140 -61
  646. package/src/tui/session/session-api/commands.mjs +14 -10
  647. package/src/tui/session/session-api/controls.mjs +14 -2
  648. package/src/tui/session/session-api/integrations.mjs +9 -2
  649. package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
  650. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  651. package/src/tui/session/session-api/lifecycle.mjs +14 -11
  652. package/src/tui/session/session-api/media.mjs +2 -0
  653. package/src/tui/session/session-api/routes.mjs +81 -57
  654. package/src/tui/session/session-api/settings.mjs +9 -3
  655. package/src/tui/session/session-api/worktree.mjs +3 -2
  656. package/src/tui/session/session-api.mjs +1 -0
  657. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  658. package/src/tui/session/session-flow/drain.mjs +6 -4
  659. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  660. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  661. package/src/tui/session/session-flow/queue.mjs +1 -1
  662. package/src/tui/session/tool-approval.mjs +20 -8
  663. package/src/tui/session/transcript-spill.mjs +14 -7
  664. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  665. package/src/tui/session/tui-steering-persist.mjs +3 -5
  666. package/src/tui/session/turn-quiet.mjs +53 -0
  667. package/src/tui/session/turn-stream.mjs +179 -32
  668. package/src/tui/session/turn.mjs +50 -36
  669. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  670. package/src/tui/spinner-meta.mjs +10 -0
  671. package/src/tui/spinner-verbs.mjs +3 -0
  672. package/src/ui/statusline.mjs +13 -3
  673. package/src/workflows/default/WORKFLOW.md +3 -1
  674. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  675. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  676. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  677. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
  678. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  679. package/src/session-runtime/turn/share-ops.mjs +0 -77
  680. package/src/tui/session/cross-surface-share.mjs +0 -406
  681. package/src/tui/session/live-share/delta.mjs +0 -153
  682. package/src/tui/session/live-share/mirror.mjs +0 -106
  683. package/src/tui/session/live-share/owner.mjs +0 -254
  684. package/src/tui/session/live-share/retry.mjs +0 -54
  685. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  686. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  687. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  688. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  689. package/src/tui/session/live-share/viewer.mjs +0 -99
  690. package/src/tui/session/live-share/wire.mjs +0 -44
  691. package/src/tui/session/live-share.mjs +0 -154
  692. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -8,6 +8,7 @@
8
8
  import { useInput } from 'ink';
9
9
  import { overlayBlocksGlobalTranscriptScroll } from './slash-commands.mjs';
10
10
  import { copyActiveSelection } from './use-global-key-input/copy-first.mjs';
11
+ import { approvalShortcutDecision } from './use-global-key-input/approval-shortcut.mjs';
11
12
  import { decodeSelectionMoveChord } from './use-global-key-input/shift-arrow.mjs';
12
13
  export function useGlobalKeyInput({
13
14
  store,
@@ -43,18 +44,10 @@ export function useGlobalKeyInput({
43
44
  // settle it through the same path a real release takes, before any branch
44
45
  // below reads the selection.
45
46
  settleStuckDrag?.();
46
- if (toolApproval) {
47
- const value = String(input || '')
48
- .trim()
49
- .toLowerCase();
50
- if (key.escape || value === 'd' || value === 'n') {
51
- store.resolveToolApproval?.(toolApproval.id, { approved: false, reason: 'denied by user' });
52
- return;
53
- }
54
- if (value === 'a' || value === 'y') {
55
- store.resolveToolApproval?.(toolApproval.id, { approved: true, reason: 'approved by user' });
56
- return;
57
- }
47
+ const decision = approvalShortcutDecision(toolApproval, input, key);
48
+ if (decision) {
49
+ store.resolveToolApproval?.(toolApproval.id, decision);
50
+ return;
58
51
  }
59
52
  if (key.ctrl && (input === 'c' || input === 'C')) {
60
53
  copyActiveSelection({ promptSelectionRef, dragRef, copySelection, showSelectionCopyHint });
@@ -36,6 +36,8 @@ export function usePromptHandlers({
36
36
  usagePanel,
37
37
  closeUsagePanel,
38
38
  contextPanel,
39
+ btwPanel,
40
+ closeBtwPanel,
39
41
  // paste-attachment helpers (owned by App, threaded in explicitly)
40
42
  installPastedImages,
41
43
  clearPastedImagesSnapshot,
@@ -72,6 +74,13 @@ export function usePromptHandlers({
72
74
  return true;
73
75
  }
74
76
 
77
+ // /btw side panel: Esc closes it (cancelling a pending ask) before the
78
+ // turn interrupt / draft handling sees the key.
79
+ if (btwPanel) {
80
+ closeBtwPanel();
81
+ return true;
82
+ }
83
+
75
84
  if (meta.phase === 'clear-arm') {
76
85
  showPromptHint('Esc again to clear', 'plain', PROMPT_ESCAPE_HINT_TIMEOUT_MS);
77
86
  return true;
@@ -107,6 +116,8 @@ export function usePromptHandlers({
107
116
  },
108
117
  [
109
118
  contextPanel,
119
+ btwPanel,
120
+ closeBtwPanel,
110
121
  surface,
111
122
  usagePanel,
112
123
  closeUsagePanel,
@@ -0,0 +1,53 @@
1
+ /**
2
+ * components/BtwPanel.jsx — transient `/btw` side-question panel above the prompt.
3
+ */
4
+ import { useEffect, useState } from 'react';
5
+ import { Box, Text, useInput } from 'ink';
6
+ import { theme } from '../theme.mjs';
7
+ import { Markdown } from './Markdown.jsx';
8
+ import { BTW_CHROME_ROWS, btwContentRows, btwScrollMax, btwScrollOffset } from '../app/btw-controller.mjs';
9
+
10
+ export function BtwPanel({ panel, columns = 80, panelRows, themeEpoch = 0 }) {
11
+ const bodyRows = Math.max(1, (panelRows ?? BTW_CHROME_ROWS + 1) - BTW_CHROME_ROWS);
12
+ const total = btwContentRows(panel, columns);
13
+ const maxOffset = btwScrollMax(total, bodyRows);
14
+ const [offset, setOffset] = useState(0);
15
+ const top = Math.min(offset, maxOffset);
16
+ const scrollable = maxOffset > 0;
17
+
18
+ // A new question or a settled answer starts from the top.
19
+ useEffect(() => {
20
+ setOffset(0);
21
+ }, [panel.question, panel.status]);
22
+
23
+ useInput((_input, key) => {
24
+ if (!scrollable || (!key.pageUp && !key.pageDown)) return;
25
+ setOffset((current) => btwScrollOffset(key, current, bodyRows, total));
26
+ });
27
+
28
+ let body;
29
+ if (panel.status === 'pending') body = <Text color={theme.inactive}>answering… (Esc to cancel)</Text>;
30
+ else if (panel.status === 'error') body = <Text color={theme.error}>{panel.text}</Text>;
31
+ else
32
+ body = (
33
+ <Markdown themeEpoch={themeEpoch} columns={columns}>
34
+ {panel.text}
35
+ </Markdown>
36
+ );
37
+ return (
38
+ <Box flexDirection="column" flexShrink={0} width="100%">
39
+ <Box borderStyle="round" borderColor={theme.promptBorder} paddingX={1} width="100%" flexDirection="column">
40
+ <Text color={theme.panelTitle} wrap="truncate-end">{`btw · ${panel.question}`}</Text>
41
+ <Box flexDirection="column" height={bodyRows} overflow="hidden">
42
+ <Box flexDirection="column" flexShrink={0} marginTop={-top}>
43
+ {body}
44
+ </Box>
45
+ </Box>
46
+ <Text color={theme.inactive}>
47
+ {scrollable ? `PgUp/PgDn scroll (${top + 1}-${Math.min(total, top + bodyRows)}/${total}) · ` : ''}
48
+ Esc to close · not saved to the conversation
49
+ </Text>
50
+ </Box>
51
+ </Box>
52
+ );
53
+ }
@@ -0,0 +1,275 @@
1
+ /**
2
+ * components/QuestionPanel.jsx — ask_user multiple-choice panel.
3
+ *
4
+ * Same round-border chrome as Picker. Digits/↑↓ choose, Space toggles
5
+ * (multi-select), ←/→ switch questions, Enter confirms the current question
6
+ * (and sends on the last), Esc dismisses. The last row is an inline text
7
+ * input; while typing, every key belongs to the input (no slash commands).
8
+ */
9
+ import { useRef, useState } from 'react';
10
+ import { Box, Text, useInput, usePaste, useStdin } from 'ink';
11
+ import stringWidth from 'string-width';
12
+ import { theme } from '../theme.mjs';
13
+ import { truncatePanelText, padPanelCells } from './panel-cell-text.mjs';
14
+ import { isCsiPrivateReply } from './prompt-input/key-signals.mjs';
15
+ import {
16
+ CUSTOM_LABEL,
17
+ appendCapped,
18
+ answerFor,
19
+ buildAnswers,
20
+ initialCursor,
21
+ optionLayout,
22
+ planQuestionView,
23
+ questionHelp,
24
+ } from './question-panel-model.mjs';
25
+
26
+ const MAX_TAB_CELLS = 10;
27
+
28
+ function cleanTyped(value) {
29
+ return String(value ?? '')
30
+ .replace(/\x1b\[[\d;?<]*[A-Za-z~]/g, '')
31
+ .replace(/[\r\n\t]+/g, ' ')
32
+ .replace(/[\x00-\x1f\x7f]/g, '');
33
+ }
34
+
35
+ export function QuestionPanel({ questions, columns = 80, rows, onSubmit, onDismiss }) {
36
+ const { isRawModeSupported } = useStdin();
37
+ const [state, setState] = useState(() => ({
38
+ qi: 0,
39
+ cursors: questions.map(initialCursor),
40
+ drafts: questions.map(() => ({ selected: [], text: '' })),
41
+ typing: false,
42
+ buf: '',
43
+ }));
44
+ const ref = useRef(state);
45
+ ref.current = state;
46
+ const commit = (next) => {
47
+ ref.current = next;
48
+ setState(next);
49
+ };
50
+ const last = questions.length - 1;
51
+
52
+ const withDraft = (s, qi, patch) => ({
53
+ ...s,
54
+ drafts: s.drafts.map((d, i) => (i === qi ? { ...d, ...patch } : d)),
55
+ });
56
+
57
+ // Confirm the current question and advance (or send on the last one).
58
+ const advance = (s) => {
59
+ if (s.qi >= last) {
60
+ onSubmit(buildAnswers(questions, s.drafts));
61
+ return;
62
+ }
63
+ commit({ ...s, qi: s.qi + 1, typing: false, buf: '' });
64
+ };
65
+
66
+ const typeInto = (input) => {
67
+ const s = ref.current;
68
+ const text = cleanTyped(input);
69
+ if (text) commit({ ...s, buf: appendCapped(s.buf, text) });
70
+ };
71
+
72
+ usePaste((text) => {
73
+ if (ref.current.typing) typeInto(text);
74
+ }, { isActive: isRawModeSupported });
75
+
76
+ useInput(
77
+ (input, key) => {
78
+ const s = ref.current;
79
+ const raw = String(input ?? '');
80
+ if (/(?:\x1b)?\[<\d+;\d+;\d+[Mm]/.test(raw) || isCsiPrivateReply(raw)) return;
81
+ const question = questions[s.qi];
82
+ const n = question.options.length;
83
+ const multi = question.multi_select === true;
84
+
85
+ if (s.typing) {
86
+ if (key.escape) return commit({ ...s, typing: false, buf: '' });
87
+ if (key.return) {
88
+ const text = s.buf.trim();
89
+ const draft = s.drafts[s.qi];
90
+ const next = withDraft(s, s.qi, { text, selected: multi ? draft.selected : [] });
91
+ if (text) return advance({ ...next, typing: false, buf: '' });
92
+ return commit({ ...next, typing: false, buf: '' });
93
+ }
94
+ if (key.backspace || key.delete) return commit({ ...s, buf: Array.from(s.buf).slice(0, -1).join('') });
95
+ if (key.ctrl || key.meta || key.upArrow || key.downArrow || key.leftArrow || key.rightArrow || key.tab) return;
96
+ return typeInto(raw);
97
+ }
98
+
99
+ if (key.escape) return onDismiss();
100
+ const setCursor = (cursor) => commit({ ...s, cursors: s.cursors.map((c, i) => (i === s.qi ? cursor : c)) });
101
+ const choose = (idx, toggle) => {
102
+ const draft = s.drafts[s.qi];
103
+ let selected;
104
+ if (multi && toggle) {
105
+ selected = draft.selected.includes(idx) ? draft.selected.filter((i) => i !== idx) : [...draft.selected, idx];
106
+ } else {
107
+ selected = multi ? draft.selected : [idx];
108
+ }
109
+ const cursors = s.cursors.map((c, i) => (i === s.qi ? idx : c));
110
+ commit({ ...withDraft(s, s.qi, { selected, text: multi ? draft.text : '' }), cursors });
111
+ };
112
+ const cursor = s.cursors[s.qi];
113
+ if (key.upArrow) return setCursor((cursor - 1 + n + 1) % (n + 1));
114
+ if (key.downArrow) return setCursor((cursor + 1) % (n + 1));
115
+ if (key.leftArrow || key.rightArrow) {
116
+ const qi = Math.max(0, Math.min(last, s.qi + (key.leftArrow ? -1 : 1)));
117
+ return commit({ ...s, qi });
118
+ }
119
+ if (key.return) {
120
+ if (cursor === n) return commit({ ...s, typing: true, buf: s.drafts[s.qi].text });
121
+ const draft = s.drafts[s.qi];
122
+ let next = s;
123
+ if (!multi) next = withDraft(s, s.qi, { selected: [cursor], text: '' });
124
+ else if (draft.selected.length === 0 && !draft.text.trim()) next = withDraft(s, s.qi, { selected: [cursor] });
125
+ return advance(next);
126
+ }
127
+ if (raw === ' ' && !key.ctrl && !key.meta) {
128
+ if (cursor < n) choose(cursor, true);
129
+ return;
130
+ }
131
+ if (/^[1-9]$/.test(raw)) {
132
+ const idx = Number(raw) - 1;
133
+ if (idx < n) choose(idx, true);
134
+ else if (idx === n) setCursor(n);
135
+ }
136
+ },
137
+ { isActive: isRawModeSupported }
138
+ );
139
+
140
+ const question = questions[state.qi];
141
+ const multi = question.multi_select === true;
142
+ const layout = optionLayout(question, columns);
143
+ const n = question.options.length;
144
+ const cursor = state.cursors[state.qi];
145
+ const draft = state.drafts[state.qi];
146
+ const avail = layout.avail;
147
+
148
+ const title = questions.length > 1 ? `Question ${state.qi + 1}/${questions.length}` : 'Question';
149
+ const tabs =
150
+ questions.length > 1
151
+ ? questions.map((q, i) => ({
152
+ text: truncatePanelText(String(q.header || `Q${i + 1}`), MAX_TAB_CELLS),
153
+ answered: answerFor(q, state.drafts[i]) !== null,
154
+ current: i === state.qi,
155
+ }))
156
+ : [];
157
+
158
+ const indexText = (i) => padPanelCells(`${i + 1}.`, layout.indexCells - 1) + ' ';
159
+ const renderLine = (selected, children, key) => {
160
+ const text = selected ? { backgroundColor: theme.selectionBackground, color: theme.selectionText } : {};
161
+ return (
162
+ <Text key={key} {...text} wrap="truncate">
163
+ {children}
164
+ </Text>
165
+ );
166
+ };
167
+
168
+ const plan = planQuestionView(question, columns, rows ?? Infinity, cursor);
169
+ const out = [];
170
+ const optionRow = (i) => {
171
+ const row = layout.rows[i];
172
+ const selected = i === cursor;
173
+ const checked = draft.selected.includes(i);
174
+ const lead = `${selected ? '› ' : ' '}${indexText(i)}`;
175
+ const fill = ' '.repeat(Math.max(0, avail - layout.prefixCells - stringWidth(row.label + row.suffix + row.detail)));
176
+ out.push(
177
+ renderLine(
178
+ selected,
179
+ <>
180
+ {lead}
181
+ {multi ? (
182
+ <Text color={selected ? theme.selectionText : checked ? theme.success : undefined}>
183
+ {checked ? '[x] ' : '[ ] '}
184
+ </Text>
185
+ ) : null}
186
+ {row.label}
187
+ {row.suffix ? <Text color={selected ? theme.selectionText : theme.suggestion}>{row.suffix}</Text> : null}
188
+ {row.detail ? <Text color={selected ? theme.selectionText : theme.subtle}>{row.detail}</Text> : null}
189
+ {selected ? fill : ''}
190
+ </>,
191
+ `o${i}`
192
+ )
193
+ );
194
+ };
195
+
196
+ const customSelected = cursor === n;
197
+ const customLead = `${customSelected ? '› ' : ' '}${indexText(n)}`;
198
+ const markerPad = multi ? ' ' : '';
199
+ let customBody;
200
+ if (state.typing) {
201
+ const room = Math.max(1, avail - stringWidth(customLead) - stringWidth(markerPad) - 1);
202
+ let shown = Array.from(state.buf).slice(-room).join('');
203
+ while (stringWidth(shown) > room) shown = Array.from(shown).slice(1).join('');
204
+ customBody = `${shown}▌`;
205
+ } else if (draft.text) {
206
+ customBody = truncatePanelText(draft.text, Math.max(1, avail - stringWidth(customLead) - stringWidth(markerPad)));
207
+ } else {
208
+ customBody = CUSTOM_LABEL;
209
+ }
210
+ const customColor = customSelected ? theme.selectionText : draft.text && !state.typing ? theme.text : theme.inactive;
211
+ const customRow = () =>
212
+ renderLine(
213
+ customSelected,
214
+ <>
215
+ {customLead}
216
+ {markerPad}
217
+ <Text color={state.typing ? undefined : customColor}>{customBody}</Text>
218
+ {customSelected ? ' '.repeat(Math.max(0, avail - stringWidth(customLead + markerPad + customBody))) : ''}
219
+ </>,
220
+ 'custom'
221
+ );
222
+
223
+ const moreRow = (key, text) => (
224
+ <Text key={key} color={theme.subtle} wrap="truncate">
225
+ {` ${text}`}
226
+ </Text>
227
+ );
228
+ if (plan.above > 0) out.push(moreRow('above', `↑ ${plan.above} more`));
229
+ for (const item of plan.items) {
230
+ if (item.index === n) out.push(customRow());
231
+ else optionRow(item.index);
232
+ }
233
+ if (plan.below > 0) out.push(moreRow('below', `↓ ${plan.below} more`));
234
+
235
+ const help = questionHelp({ multi, typing: state.typing, last: state.qi >= last, count: n, questionCount: questions.length });
236
+
237
+ return (
238
+ <Box flexDirection="column" flexShrink={0} width="100%">
239
+ <Box flexDirection="column" borderStyle="round" borderColor={theme.promptBorder} paddingX={1} width="100%">
240
+ <Box flexDirection="row" justifyContent="space-between">
241
+ <Box flexShrink={1}>
242
+ <Text wrap="truncate">
243
+ <Text color={theme.panelTitle}>{title}</Text>
244
+ {tabs.map((tab, i) => (
245
+ <Text key={i}>
246
+ {' '}
247
+ {tab.current ? (
248
+ <Text backgroundColor={theme.selectionBackground} color={theme.selectionText}>
249
+ {` ${tab.answered ? '✓ ' : ''}${tab.text} `}
250
+ </Text>
251
+ ) : tab.answered ? (
252
+ <Text color={theme.success}>{`✓ ${tab.text}`}</Text>
253
+ ) : (
254
+ <Text color={theme.subtle}>{tab.text}</Text>
255
+ )}
256
+ </Text>
257
+ ))}
258
+ </Text>
259
+ </Box>
260
+ <Box flexShrink={0} marginLeft={2}>
261
+ <Text color={theme.subtle}>{help}</Text>
262
+ </Box>
263
+ </Box>
264
+ <Text> </Text>
265
+ {plan.qLines.map((line, i) => (
266
+ <Text key={i} color={theme.text} wrap="truncate">
267
+ {line}
268
+ </Text>
269
+ ))}
270
+ <Text> </Text>
271
+ {out}
272
+ </Box>
273
+ </Box>
274
+ );
275
+ }
@@ -66,6 +66,8 @@ export function Spinner({
66
66
  thinkingActiveSince = 0,
67
67
  thinkingMs = 0,
68
68
  effort = '',
69
+ // The turn's quiet state (`spinner.quiet`), shown as the quiet-time cue.
70
+ quiet = null,
69
71
  hasActiveTools = false,
70
72
  paused = false,
71
73
  interruptible = false,
@@ -126,6 +128,8 @@ export function Spinner({
126
128
  thinkingActiveSince={thinkingActiveSince}
127
129
  thinkingMs={thinkingMs}
128
130
  effort={effort}
131
+ quiet={quiet}
132
+ now={now}
129
133
  interruptible={interruptible}
130
134
  columns={columns}
131
135
  reducedMotion={reducedMotion}
@@ -20,6 +20,7 @@ const THINKING_DELAY_MS = 3000;
20
20
  // One-way shimmer. The tail runs past the final character before restarting.
21
21
  const GLIMMER_SPEED_MS = {
22
22
  requesting: 70,
23
+ 'model-thinking': 70,
23
24
  reconnecting: 70,
24
25
  compacting: 120,
25
26
  'auto-clear': 120,
@@ -91,7 +92,9 @@ function tokenModeGlyph(mode) {
91
92
  case 'responding':
92
93
  case 'thinking':
93
94
  return DOWN_ARROW;
95
+ // The request is sent and nothing has come back yet.
94
96
  case 'requesting':
97
+ case 'model-thinking':
95
98
  return UP_ARROW;
96
99
  default:
97
100
  return '';
@@ -108,6 +111,8 @@ export function SpinnerByline({
108
111
  thinkingActiveSince,
109
112
  thinkingMs,
110
113
  effort,
114
+ quiet = null,
115
+ now = Date.now(),
111
116
  interruptible,
112
117
  columns,
113
118
  reducedMotion,
@@ -151,6 +156,8 @@ export function SpinnerByline({
151
156
  thinkingSince: thinkingActiveSince,
152
157
  thinkingMs,
153
158
  effort,
159
+ quiet,
160
+ now,
154
161
  });
155
162
  const tokenGlyph = tokenModeGlyph(mode);
156
163
  let tokenText = '';
@@ -176,8 +183,13 @@ export function SpinnerByline({
176
183
  const interruptW = interruptText.length;
177
184
  const showInterrupt = Boolean(interruptText) && avail > interruptW;
178
185
  const usedAfterInterrupt = showInterrupt ? interruptW + SEP_WIDTH : 0;
179
- const showThinkingStatus = Boolean(thinkingStatusText) && avail > usedAfterInterrupt + thinkingStatusW;
180
- const usedAfterThinking = usedAfterInterrupt + (showThinkingStatus ? thinkingStatusW + SEP_WIDTH : 0);
186
+ // A quiet turn says so before any other stat: it is the one that explains a
187
+ // long silence (the interrupt hint beside it is how to stop it).
188
+ const quietText = meta.quietText;
189
+ const showQuiet = Boolean(quietText) && avail > usedAfterInterrupt + quietText.length;
190
+ const usedAfterQuiet = usedAfterInterrupt + (showQuiet ? quietText.length + SEP_WIDTH : 0);
191
+ const showThinkingStatus = Boolean(thinkingStatusText) && avail > usedAfterQuiet + thinkingStatusW;
192
+ const usedAfterThinking = usedAfterQuiet + (showThinkingStatus ? thinkingStatusW + SEP_WIDTH : 0);
181
193
  const showTimer = Boolean(timerLabel) && avail > usedAfterThinking + timerW;
182
194
  const usedAfterTimer = usedAfterThinking + (showTimer ? timerW + SEP_WIDTH : 0);
183
195
  const showTokens = wantsTokens && tokenText && avail > usedAfterTimer + tokenW;
@@ -223,6 +235,13 @@ export function SpinnerByline({
223
235
  )
224
236
  );
225
237
  }
238
+ if (showQuiet) {
239
+ segments.push(
240
+ <Text key="quiet" color={meta.quietParts?.escalated ? theme.warning : theme.statusSubtle}>
241
+ {quietText}
242
+ </Text>
243
+ );
244
+ }
226
245
  if (showInterrupt) {
227
246
  segments.push(
228
247
  <Text key="interrupt" color={theme.statusSubtle}>
@@ -0,0 +1,156 @@
1
+ /**
2
+ * components/question-panel-model.mjs — pure model for the ask_user
3
+ * QuestionPanel: answer building, row layout and reserved panel height.
4
+ */
5
+ import stringWidth from 'string-width';
6
+ import wrapAnsi from 'wrap-ansi';
7
+ import { truncatePanelText } from './panel-cell-text.mjs';
8
+
9
+ export const CUSTOM_LABEL = '직접 입력…';
10
+ export const RECOMMENDED_SUFFIX = ' (추천)';
11
+ export const MULTI_HINT = ' (여러 개 선택 가능)';
12
+ // border(2) + title + blank + blank-after-question; question rows added separately.
13
+ const FIXED_ROWS = 5;
14
+ // Panel interior = frame − 2 border − 2 paddingX.
15
+ const CHROME_COLUMNS = 4;
16
+
17
+ export function questionsOf(toolApproval) {
18
+ const list = toolApproval?.args?.questions;
19
+ return Array.isArray(list) ? list : [];
20
+ }
21
+
22
+ // One question's answer from its draft ({ selected: optionIndex[], text? }).
23
+ export function answerFor(question, draft) {
24
+ const options = Array.isArray(question?.options) ? question.options : [];
25
+ const selected = [...new Set(draft?.selected || [])]
26
+ .filter((i) => Number.isInteger(i) && i >= 0 && i < options.length)
27
+ .sort((a, b) => a - b)
28
+ .map((i) => options[i].label);
29
+ const text = String(draft?.text ?? '').trim();
30
+ if (selected.length === 0 && !text) return null;
31
+ return text ? { selected, text } : { selected };
32
+ }
33
+
34
+ export function buildAnswers(questions, drafts) {
35
+ return questions.map((question, i) => answerFor(question, drafts?.[i]));
36
+ }
37
+
38
+ const DETAIL_GAP = ' ';
39
+ const MIN_DETAIL_CELLS = 6;
40
+
41
+ // Geometry of one question's option rows at `columns` frame width: one line
42
+ // per option (its label, the recommended mark, then its one-sentence
43
+ // tradeoff in the cells left, cut with an ellipsis).
44
+ export function optionLayout(question, columns) {
45
+ const options = Array.isArray(question?.options) ? question.options : [];
46
+ const total = options.length + 1;
47
+ const indexCells = stringWidth(`${total}. `);
48
+ const markerCells = question?.multi_select ? 4 : 0; // "[x] "
49
+ const prefixCells = 2 + indexCells + markerCells; // "› " + "1. " + marker
50
+ const avail = Math.max(10, columns - CHROME_COLUMNS);
51
+ const labelCap = Math.max(4, avail - prefixCells);
52
+ const rows = options.map((option, i) => {
53
+ const suffix = question?.recommended === i ? RECOMMENDED_SUFFIX : '';
54
+ const label = truncatePanelText(String(option.label ?? ''), Math.max(1, labelCap - stringWidth(suffix)));
55
+ const left = labelCap - stringWidth(label + suffix) - DETAIL_GAP.length;
56
+ const text = String(option.description ?? '').trim();
57
+ const detail = text && left >= MIN_DETAIL_CELLS ? `${DETAIL_GAP}${truncatePanelText(text, left)}` : '';
58
+ return { label, suffix, detail };
59
+ });
60
+ return { rows, prefixCells, avail, indexCells };
61
+ }
62
+
63
+ export const MAX_ANSWER_CHARS = 4000;
64
+ const MIN_OPTION_ROWS = 3;
65
+
66
+ // Append `text` to `base`, never exceeding MAX_ANSWER_CHARS UTF-16 units (the
67
+ // unit the runtime checks), and never splitting a character.
68
+ export function appendCapped(base, text) {
69
+ let out = base;
70
+ for (const char of text) {
71
+ if (out.length + char.length > MAX_ANSWER_CHARS) break;
72
+ out += char;
73
+ }
74
+ return out;
75
+ }
76
+
77
+ export function questionLines(question, columns) {
78
+ const shown = `${question?.question ?? ''}${question?.multi_select ? MULTI_HINT : ''}`;
79
+ return wrapAnsi(shown, Math.max(1, columns - CHROME_COLUMNS), { trim: false, hard: true }).split('\n');
80
+ }
81
+
82
+ function ellipsize(line, width) {
83
+ return `${truncatePanelText(line, Math.max(1, width - 1)).replace(/…$/, '')}…`;
84
+ }
85
+
86
+ // Fit the panel into `rows` (Infinity = unbudgeted). Always keeps the question
87
+ // text (capped, leaving MIN_OPTION_ROWS for options) and the highlighted
88
+ // option; the rest scroll with ↑/↓ more indicators.
89
+ export function planQuestionView(question, columns, rows, cursor) {
90
+ const layout = optionLayout(question, columns);
91
+ const n = layout.rows.length;
92
+ let qLines = questionLines(question, columns);
93
+ const optionBudget = rows - FIXED_ROWS;
94
+ const qCap = Number.isFinite(rows) ? Math.max(1, optionBudget - MIN_OPTION_ROWS) : Infinity;
95
+ if (qLines.length > qCap) {
96
+ qLines = qLines.slice(0, qCap);
97
+ qLines[qCap - 1] = ellipsize(qLines[qCap - 1], Math.max(1, columns - CHROME_COLUMNS));
98
+ }
99
+ const avail = Number.isFinite(rows) ? Math.max(1, rows - FIXED_ROWS - qLines.length) : Infinity;
100
+ const full = Array(n + 1).fill(1);
101
+ const total = n + 1;
102
+ let heights = full;
103
+ if (full.reduce((a, b) => a + b, 0) > avail) {
104
+ heights = full.map((h, i) => (i === cursor ? Math.min(h, Math.max(1, avail - 2)) : 1));
105
+ }
106
+ let start = Math.min(cursor, total - 1);
107
+ let end = start + 1;
108
+ let used = heights[start];
109
+ const fits = (s, e, sum) => sum + (s > 0 ? 1 : 0) + (e < total ? 1 : 0) <= avail;
110
+ if (!fits(start, end, used) && avail < Infinity) {
111
+ // highlighted option alone exceeds budget with indicators: shrink it.
112
+ heights = heights.map((h, i) => (i === cursor ? 1 : h));
113
+ used = 1;
114
+ }
115
+ for (let grew = true; grew; ) {
116
+ grew = false;
117
+ if (end < total && fits(start, end + 1, used + heights[end])) {
118
+ used += heights[end++];
119
+ grew = true;
120
+ }
121
+ if (start > 0 && fits(start - 1, end, used + heights[start - 1])) {
122
+ used += heights[--start];
123
+ grew = true;
124
+ }
125
+ }
126
+ const items = [];
127
+ for (let i = start; i < end; i++) items.push({ index: i, lines: heights[i] });
128
+ return { qLines, items, above: start, below: total - end };
129
+ }
130
+
131
+ function questionRows(question, columns) {
132
+ const optionRows = Array.isArray(question?.options) ? question.options.length : 0;
133
+ return FIXED_ROWS + questionLines(question, columns).length + optionRows + 1; // +1 custom-input row
134
+ }
135
+
136
+ // Reserved floating-panel rows: the tallest question, so switching questions
137
+ // never resizes the panel.
138
+ export function questionPanelRows(questions, columns) {
139
+ return Math.max(FIXED_ROWS + 3, ...questions.map((q) => questionRows(q, columns)));
140
+ }
141
+
142
+ export function initialCursor(question) {
143
+ const n = Array.isArray(question?.options) ? question.options.length : 0;
144
+ const r = question?.recommended;
145
+ return Number.isInteger(r) && r >= 0 && r < n ? r : 0;
146
+ }
147
+
148
+ export function questionHelp({ multi, typing, last, count, questionCount = 1 }) {
149
+ if (typing) return 'Enter Send · Esc Back to list';
150
+ // Several questions: the title row also holds the tabs, so keep help short.
151
+ const parts = questionCount > 1 ? [] : [`1–${count} Choose`, '↑/↓ Move'];
152
+ if (multi) parts.push('Space Toggle');
153
+ if (questionCount > 1) parts.push('←/→ Question');
154
+ parts.push(last ? 'Enter Send' : 'Enter Next', 'Esc Dismiss');
155
+ return parts.join(' · ');
156
+ }
@@ -10,7 +10,7 @@ import { normalizeStatuslineAnsi } from '../../statusline-ansi-bridge.mjs';
10
10
  // Cache-only synchronous read (never touches fs on the render path), so the
11
11
  // instant-local L2 can render the Shell segment itself instead of grafting it
12
12
  // out of the previous full line.
13
- import { shellJobsStatus } from '../../../runtime/shared/statusline/statusline-segments.mjs';
13
+ import { shellJobsStatus, unconfirmedShellCount } from '../../../runtime/shared/statusline/statusline-segments.mjs';
14
14
  import { formatElapsed, num, terminalColumns, timeMs } from '../../../runtime/shared/statusline/statusline-format.mjs';
15
15
  import { isTerminalStatus } from './boot-schedule.mjs';
16
16
 
@@ -137,11 +137,19 @@ export function localStatusLineL2(
137
137
  const shellStatus = shellScope
138
138
  ? shellJobsStatus({ clientHostPid, sessionId: shellScope })
139
139
  : shellJobsStatus({ clientHostPid });
140
- const shellCount = Number(shellStatus?.count) || 0;
140
+ // A shell whose termination is unconfirmed is not "running": it is held,
141
+ // with /shells as the way to inspect or release it.
142
+ const unconfirmed = unconfirmedShellCount(shellStatus);
143
+ const shellCount = (Number(shellStatus?.count) || 0) - unconfirmed;
141
144
  if (shellCount > 0) {
142
145
  const label = `Running ${shellCount} Shell${shellCount === 1 ? '' : 's'}`;
143
146
  l2Parts.push(`${spin} ${STATUS}${label}${RESET}${elapsedSuffix(shellStatus.elapsedLabel || '')}`);
144
147
  }
148
+ if (unconfirmed > 0) {
149
+ const { WARNING } = statusColors();
150
+ const label = `⚠ ${unconfirmed} Shell${unconfirmed === 1 ? '' : 's'} termination unconfirmed`;
151
+ l2Parts.push(`${WARNING}${label}${RESET} ${SUBTLE}·${RESET} /shells`);
152
+ }
145
153
  // `web_search` is the key the producers publish (session/active-tool-summary
146
154
  // and app/use-transcript-activity); the async full render reads the same key,
147
155
  // so both paths light the segment on the same snapshot.