mixdog 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/README.md +1 -0
  2. package/package.json +2 -2
  3. package/scripts/lib/run-node-tests.mjs +9 -0
  4. package/scripts/prune-desktop-runtime.mjs +3 -0
  5. package/scripts/release-paths.mjs +39 -2
  6. package/scripts/test-direct.mjs +4 -2
  7. package/src/defaults/shipped-history.json +6 -0
  8. package/src/defaults/skills/setup/references/actions.md +5 -2
  9. package/src/defaults/skills/visualize/SKILL.md +157 -0
  10. package/src/defaults/skills/visualize/references/craft.md +88 -0
  11. package/src/headless-command.mjs +56 -3
  12. package/src/headless-exec.mjs +17 -1
  13. package/src/headless-role.mjs +2 -2
  14. package/src/help.mjs +2 -0
  15. package/src/lib/rules-builder.cjs +0 -23
  16. package/src/rules/lead/LEAD.md +2 -2
  17. package/src/rules/shared/70-delivery.md +2 -2
  18. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  19. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
  20. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
  21. package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
  22. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
  23. package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
  24. package/src/runtime/agent/orchestrator/config.mjs +9 -1
  25. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +47 -7
  26. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +51 -8
  27. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +25 -5
  28. package/src/runtime/agent/orchestrator/mcp/client.mjs +348 -122
  29. package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
  30. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
  31. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
  32. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +13 -1
  33. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
  34. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
  35. package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
  36. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +12 -4
  37. package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
  38. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  40. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
  41. package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
  42. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
  43. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
  44. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +67 -0
  45. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +521 -0
  46. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
  47. package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
  48. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
  49. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +3 -0
  50. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
  51. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
  52. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
  53. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
  54. package/src/runtime/agent/orchestrator/providers/registry.mjs +15 -1
  55. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
  56. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
  57. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +12 -11
  58. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +16 -1
  59. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +11 -0
  60. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +11 -8
  61. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
  62. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
  63. package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
  64. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +10 -3
  65. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +18 -11
  66. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
  67. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
  68. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
  69. package/src/runtime/agent/orchestrator/session/context-utils.mjs +12 -14
  70. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +1 -1
  71. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
  72. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
  73. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
  74. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -1
  75. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +1 -0
  76. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +17 -7
  77. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
  78. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +12 -2
  79. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -0
  80. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +5 -3
  81. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
  82. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
  83. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
  84. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
  85. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
  86. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
  87. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
  88. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
  89. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
  90. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
  91. package/src/runtime/agent/orchestrator/session/manager.mjs +1 -5
  92. package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
  93. package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
  94. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +29 -19
  95. package/src/runtime/agent/orchestrator/session/read-dedup.mjs +0 -1
  96. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
  98. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
  99. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +29 -0
  100. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +5 -1
  101. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +23 -4
  102. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
  103. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +28 -8
  104. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +140 -0
  105. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +52 -2
  106. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
  107. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
  108. package/src/runtime/agent/orchestrator/tools/builtin/read-cache-policy.mjs +8 -0
  109. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +31 -12
  110. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
  111. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
  112. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
  113. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +80 -66
  114. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
  115. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +5 -1
  116. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
  117. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
  118. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
  119. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
  120. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
  121. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
  122. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +56 -13
  123. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
  124. package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +25 -1
  125. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +78 -5
  126. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
  127. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +0 -10
  128. package/src/runtime/attachments/store.mjs +38 -0
  129. package/src/runtime/channels/index.mjs +1 -5
  130. package/src/runtime/channels/lib/runtime-paths.mjs +8 -23
  131. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -13
  132. package/src/runtime/channels/lib/worker-ipc.mjs +2 -2
  133. package/src/runtime/channels/lib/worker-main.mjs +4 -34
  134. package/src/runtime/shared/atomic-file.mjs +8 -2
  135. package/src/runtime/shared/best-effort-stderr.mjs +8 -0
  136. package/src/runtime/shared/code-graph-state.mjs +12 -0
  137. package/src/runtime/shared/defaults-separation.mjs +2 -0
  138. package/src/runtime/shared/git-runner-worker.mjs +3 -2
  139. package/src/runtime/shared/git-runner.mjs +4 -3
  140. package/src/runtime/shared/llm/default-context-window.mjs +6 -0
  141. package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
  142. package/src/runtime/shared/llm/model-catalog.mjs +240 -118
  143. package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
  144. package/src/runtime/shared/llm/provider-catalog-registry.mjs +156 -0
  145. package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
  146. package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
  147. package/src/runtime/shared/model-proxy-mode.mjs +19 -0
  148. package/src/runtime/shared/provider-accounts.mjs +2 -2
  149. package/src/runtime/shared/provider-api-key.mjs +21 -1
  150. package/src/runtime/shared/schedule-model-ref.mjs +11 -2
  151. package/src/runtime/shared/semver.d.mts +1 -0
  152. package/src/runtime/shared/semver.mjs +57 -0
  153. package/src/runtime/shared/session-usage-totals.mjs +19 -0
  154. package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
  155. package/src/runtime/shared/singleton-owner.mjs +36 -6
  156. package/src/runtime/shared/statusline/statusline-segments.mjs +68 -14
  157. package/src/runtime/shared/tool-surface.mjs +9 -2
  158. package/src/runtime/shared/tool-work-units.mjs +14 -0
  159. package/src/runtime/shared/transcript-metadata.mjs +17 -1
  160. package/src/runtime/shared/turn-changes.mjs +791 -0
  161. package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
  162. package/src/runtime/shared/turn-snapshot.mjs +690 -81
  163. package/src/runtime/shared/turn-worktree-snapshot.mjs +161 -11
  164. package/src/runtime/shared/update-checker.mjs +2 -31
  165. package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
  166. package/src/runtime/shared/worktrees/contract.mjs +551 -0
  167. package/src/runtime/shared/worktrees/disk.mjs +57 -0
  168. package/src/runtime/shared/worktrees/git.mjs +247 -0
  169. package/src/runtime/shared/worktrees/include.mjs +480 -0
  170. package/src/runtime/shared/worktrees/lock.mjs +46 -0
  171. package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
  172. package/src/runtime/shared/worktrees/manager.mjs +1215 -0
  173. package/src/runtime/shared/worktrees/merge.mjs +182 -0
  174. package/src/runtime/shared/worktrees/owner.mjs +46 -0
  175. package/src/runtime/shared/worktrees/paths.mjs +62 -0
  176. package/src/runtime/shared/worktrees/registry.mjs +110 -0
  177. package/src/runtime/shared/worktrees/settings.mjs +84 -0
  178. package/src/runtime/shared/worktrees/slug.mjs +62 -0
  179. package/src/runtime/shared/worktrees/test-support.mjs +96 -0
  180. package/src/runtime/visualize-bridge/client.mjs +181 -0
  181. package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
  182. package/src/session-runtime/boot/apis.mjs +35 -0
  183. package/src/session-runtime/boot/begin.mjs +0 -2
  184. package/src/session-runtime/boot/config.mjs +2 -0
  185. package/src/session-runtime/boot/facade.mjs +20 -0
  186. package/src/session-runtime/boot/infrastructure.mjs +1 -0
  187. package/src/session-runtime/boot/session.mjs +1 -0
  188. package/src/session-runtime/boot/tools.mjs +9 -4
  189. package/src/session-runtime/config-lifecycle.mjs +10 -1
  190. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +11 -1
  191. package/src/session-runtime/global-extensions.mjs +2 -2
  192. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
  193. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
  194. package/src/session-runtime/internal-tool-executor.mjs +9 -1
  195. package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
  196. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
  197. package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
  198. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
  199. package/src/session-runtime/mcp-glue/connect.mjs +11 -6
  200. package/src/session-runtime/mcp-glue/server-catalog.mjs +7 -3
  201. package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
  202. package/src/session-runtime/model-route/route-persist.mjs +3 -0
  203. package/src/session-runtime/model-route/set-route.mjs +15 -2
  204. package/src/session-runtime/notification-bus.mjs +9 -1
  205. package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
  206. package/src/session-runtime/resource-extension-sync.mjs +30 -7
  207. package/src/session-runtime/resource-mcp-api.mjs +27 -10
  208. package/src/session-runtime/route-resolution.mjs +10 -1
  209. package/src/session-runtime/route-state.mjs +16 -2
  210. package/src/session-runtime/runtime-bootstrap.mjs +0 -4
  211. package/src/session-runtime/runtime-core.mjs +5 -0
  212. package/src/session-runtime/runtime-facade.mjs +8 -0
  213. package/src/session-runtime/runtime-paths.mjs +0 -1
  214. package/src/session-runtime/runtime-review-api.mjs +9 -0
  215. package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
  216. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
  217. package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
  218. package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
  219. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
  220. package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
  221. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
  222. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
  223. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  224. package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
  225. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
  226. package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
  227. package/src/session-runtime/services/agent-tool.mjs +1 -0
  228. package/src/session-runtime/services/channel-worker.mjs +1 -1
  229. package/src/session-runtime/services/daemon-candidate.mjs +3 -2
  230. package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
  231. package/src/session-runtime/session-create/session-options.mjs +10 -1
  232. package/src/session-runtime/session-turn-api.mjs +1 -0
  233. package/src/session-runtime/settings-api.mjs +4 -2
  234. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
  235. package/src/session-runtime/settings-profile-api.mjs +27 -2
  236. package/src/session-runtime/settings-worktree-api.mjs +17 -0
  237. package/src/session-runtime/setup-tool/executor.mjs +11 -4
  238. package/src/session-runtime/setup-tool/settings-contract.mjs +3 -1
  239. package/src/session-runtime/setup-tool/tool-defs.mjs +31 -3
  240. package/src/session-runtime/starter-guide-state.mjs +62 -0
  241. package/src/session-runtime/turn/agent-ops.mjs +12 -1
  242. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +13 -3
  243. package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
  244. package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
  245. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
  246. package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
  247. package/src/session-runtime/turn/turn-run.mjs +6 -7
  248. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
  249. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -2
  250. package/src/session-runtime/workspace/admission-gate.mjs +197 -0
  251. package/src/session-runtime/workspace/project-branches.mjs +136 -0
  252. package/src/session-runtime/workspace/transition-steps.mjs +364 -0
  253. package/src/session-runtime/workspace/transitions.mjs +651 -0
  254. package/src/session-runtime/workspace/workspace-state.mjs +112 -0
  255. package/src/standalone/channel-binding.mjs +1 -2
  256. package/src/standalone/channel-transport/call-dispatch.mjs +4 -10
  257. package/src/standalone/channel-transport/http-routes.mjs +17 -0
  258. package/src/standalone/channel-transport.mjs +13 -1
  259. package/src/standalone/daemon-channels-loader.mjs +2 -3
  260. package/src/standalone/daemon-desktop-runtime.mjs +1 -0
  261. package/src/standalone/daemon-owner.mjs +372 -0
  262. package/src/standalone/daemon-stored-session-views.mjs +4 -1
  263. package/src/standalone/daemon.mjs +139 -5
  264. package/src/standalone/desktop-service-registry.mjs +20 -0
  265. package/src/standalone/local-session-runtime.mjs +13 -78
  266. package/src/standalone/session-client/attachment-calls.mjs +3 -1
  267. package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
  268. package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
  269. package/src/standalone/session-client.mjs +104 -13
  270. package/src/standalone/session-protocol.mjs +17 -0
  271. package/src/standalone/session-proxy.mjs +3 -0
  272. package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
  273. package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
  274. package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
  275. package/src/standalone/session-service/projection/revisions.mjs +2 -0
  276. package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
  277. package/src/standalone/session-service/projection/workspace.mjs +14 -0
  278. package/src/standalone/session-service/session-calls/session-action.mjs +11 -3
  279. package/src/standalone/session-transport/call-route.mjs +13 -0
  280. package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
  281. package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
  282. package/src/standalone/session-transport/client-registry.mjs +20 -3
  283. package/src/standalone/session-transport/routes.mjs +79 -2
  284. package/src/standalone/session-transport/stack.mjs +2 -0
  285. package/src/standalone/session-transport.mjs +24 -1
  286. package/src/tui/app/message-selector.mjs +2 -1
  287. package/src/tui/app/model-options.mjs +35 -5
  288. package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
  289. package/src/tui/app/model-picker.mjs +4 -2
  290. package/src/tui/dist/index.mjs +332 -36
  291. package/src/tui/index.jsx +10 -2
  292. package/src/tui/session/compaction-view.mjs +147 -0
  293. package/src/tui/session/context-state.mjs +6 -0
  294. package/src/tui/session/initial-state.mjs +3 -0
  295. package/src/tui/session/quota-resume.mjs +2 -1
  296. package/src/tui/session/session-api/commands.mjs +10 -2
  297. package/src/tui/session/session-api/controls.mjs +4 -0
  298. package/src/tui/session/session-api/extensions.mjs +12 -8
  299. package/src/tui/session/session-api/intake/rewind.mjs +2 -1
  300. package/src/tui/session/session-api/integrations.mjs +18 -0
  301. package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
  302. package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
  303. package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
  304. package/src/tui/session/session-api/routes.mjs +10 -1
  305. package/src/tui/session/session-api/settings.mjs +2 -0
  306. package/src/tui/session/session-api/shared.mjs +10 -6
  307. package/src/tui/session/session-api/worktree.mjs +60 -0
  308. package/src/tui/session/session-api.mjs +2 -0
  309. package/src/tui/session/session-flow/auto-clear.mjs +31 -12
  310. package/src/tui/session/session-flow/drain.mjs +15 -1
  311. package/src/tui/session/session-flow/session-reset.mjs +4 -3
  312. package/src/tui/session/session-flow.mjs +2 -0
  313. package/src/tui/session/transcript-intake.mjs +14 -5
  314. package/src/tui/session/turn-stream.mjs +32 -4
  315. package/src/tui/session/turn-tool-cards.mjs +10 -2
  316. package/src/tui/session/turn.mjs +39 -10
  317. package/src/runtime/channels/tool-defs.mjs +0 -17
@@ -23,7 +23,13 @@ const SHELL_JOBS_SEGMENT_CACHE_MS = 1000;
23
23
  // Session buckets ride along with the owner-wide totals: one host process can
24
24
  // own many sessions (the desktop pools every pane's engine), so a pane must be
25
25
  // able to ask for ITS OWN jobs instead of the process aggregate.
26
- const EMPTY_SHELL_JOBS_SESSION = Object.freeze({ count: 0, elapsedLabel: '', jobs: Object.freeze([]) });
26
+ const FINISHED_SHELL_JOB_TTL_MS = 30 * 60 * 1000;
27
+ const EMPTY_SHELL_JOBS_SESSION = Object.freeze({
28
+ count: 0,
29
+ elapsedLabel: '',
30
+ jobs: Object.freeze([]),
31
+ finished: Object.freeze([]),
32
+ });
27
33
  const EMPTY_SHELL_JOBS = Object.freeze({
28
34
  count: 0,
29
35
  elapsedLabel: '',
@@ -31,8 +37,20 @@ const EMPTY_SHELL_JOBS = Object.freeze({
31
37
  sessions: Object.freeze({}),
32
38
  });
33
39
 
34
- let _shellJobsSegmentCache = { ownerPid: 0, at: 0, value: EMPTY_SHELL_JOBS };
35
- let _shellJobsRefreshInFlight = false;
40
+ // One entry per owner pid: a desktop host polls under whichever session frame
41
+ // arrived last, so the owner can alternate between processes. A single shared
42
+ // slot answered every switch with "no jobs" and made the job list flicker.
43
+ const _shellJobsSegmentCache = new Map();
44
+ const _shellJobsRefreshInFlight = new Set();
45
+ const SHELL_JOBS_OWNER_CACHE_TTL_MS = 60_000;
46
+
47
+ function rememberShellJobs(ownerPid, value) {
48
+ const at = Date.now();
49
+ for (const [pid, entry] of _shellJobsSegmentCache) {
50
+ if (at - entry.at > SHELL_JOBS_OWNER_CACHE_TTL_MS) _shellJobsSegmentCache.delete(pid);
51
+ }
52
+ _shellJobsSegmentCache.set(ownerPid, { at, value });
53
+ }
36
54
 
37
55
  function dataDir() {
38
56
  return process.env.MIXDOG_DATA_DIR || DEFAULT_STANDALONE_DATA_DIR;
@@ -50,15 +68,15 @@ export function shellJobsStatus({ clientHostPid, sessionId } = {}) {
50
68
  const scope = String(sessionId ?? '').trim();
51
69
  if (!ownerPid) return scoped ? EMPTY_SHELL_JOBS_SESSION : EMPTY_SHELL_JOBS;
52
70
  const now = Date.now();
53
- const sameOwner = _shellJobsSegmentCache.ownerPid === ownerPid;
54
- const fresh = sameOwner && now - _shellJobsSegmentCache.at < SHELL_JOBS_SEGMENT_CACHE_MS;
55
- if (!fresh && !_shellJobsRefreshInFlight) {
56
- _shellJobsRefreshInFlight = true;
71
+ const cached = _shellJobsSegmentCache.get(ownerPid);
72
+ const fresh = cached && now - cached.at < SHELL_JOBS_SEGMENT_CACHE_MS;
73
+ if (!fresh && !_shellJobsRefreshInFlight.has(ownerPid)) {
74
+ _shellJobsRefreshInFlight.add(ownerPid);
57
75
  refreshShellJobsStatus(ownerPid).finally(() => {
58
- _shellJobsRefreshInFlight = false;
76
+ _shellJobsRefreshInFlight.delete(ownerPid);
59
77
  });
60
78
  }
61
- const value = sameOwner ? _shellJobsSegmentCache.value || EMPTY_SHELL_JOBS : EMPTY_SHELL_JOBS;
79
+ const value = cached?.value || EMPTY_SHELL_JOBS;
62
80
  if (!scoped) return value;
63
81
  return (scope && value.sessions?.[scope]) || EMPTY_SHELL_JOBS_SESSION;
64
82
  }
@@ -123,10 +141,10 @@ async function refreshShellJobsStatus(ownerPid) {
123
141
  try {
124
142
  names = await readdir(dir);
125
143
  } catch {
126
- _shellJobsSegmentCache = { ownerPid, at: Date.now(), value };
144
+ rememberShellJobs(ownerPid, value);
127
145
  return;
128
146
  }
129
- const { ids, ownerByJob } = listOpenShellJobs(names);
147
+ const { ids, ownerByJob, doneIds } = listOpenShellJobs(names);
130
148
  let count = 0;
131
149
  let oldestMs = Infinity;
132
150
  const jobs = [];
@@ -143,6 +161,10 @@ async function refreshShellJobsStatus(ownerPid) {
143
161
  continue;
144
162
  }
145
163
  if (!(await isShellJobAlive(detail, p, dir, id))) continue;
164
+ // A foreground command is awaited in its own tool card; listing it here
165
+ // made every short command flash in and out of the shell list. Only
166
+ // backgrounded jobs (including promoted ones) are background work.
167
+ if (detail?.foreground === true) continue;
146
168
  // Owner-wide totals stay this process's own; session buckets take every
147
169
  // live job regardless of which host published it.
148
170
  const ownedByThisHost = ownerByJob.get(id) === ownerPid;
@@ -162,12 +184,39 @@ async function refreshShellJobsStatus(ownerPid) {
162
184
  };
163
185
  if (ownedByThisHost) jobs.push(job);
164
186
  if (!owner) continue;
165
- const bucket = bySession.get(owner) || { count: 0, oldestMs: Infinity, jobs: [] };
187
+ const bucket = bySession.get(owner) || { count: 0, oldestMs: Infinity, jobs: [], finished: [] };
166
188
  bucket.count += 1;
167
189
  if (jobMs < bucket.oldestMs) bucket.oldestMs = jobMs;
168
190
  bucket.jobs.push(job);
169
191
  bySession.set(owner, bucket);
170
192
  }
193
+ // Recently finished background jobs ride in their session bucket only;
194
+ // they never touch the running counts.
195
+ const finishedCutoff = Date.now() - FINISHED_SHELL_JOB_TTL_MS;
196
+ for (const id of doneIds) {
197
+ let detail;
198
+ try {
199
+ detail = JSON.parse(await readFile(join(dir, `${id}.json`), 'utf-8'));
200
+ } catch {
201
+ continue;
202
+ }
203
+ if (detail?.foreground === true) continue;
204
+ const owner = String(detail?.ownerSessionId ?? '').trim();
205
+ if (!owner) continue;
206
+ const finishedMs = Date.parse(detail?.finishedAt || detail?.recordedAt || '');
207
+ if (Number.isFinite(finishedMs) && finishedMs < finishedCutoff) continue;
208
+ const bucket = bySession.get(owner) || { count: 0, oldestMs: Infinity, jobs: [], finished: [] };
209
+ bucket.finished.push({
210
+ taskId: id,
211
+ command: String(detail?.command || '').trim(),
212
+ cwd: String(detail?.cwd || '').trim(),
213
+ startedAt: detail?.startedAt || null,
214
+ status: String(detail?.status || ''),
215
+ exitCode: Number.isInteger(detail?.exitCode) ? detail.exitCode : null,
216
+ finishedAt: detail?.finishedAt || detail?.recordedAt || null,
217
+ });
218
+ bySession.set(owner, bucket);
219
+ }
171
220
  // A desktop pane's job lands in a session bucket while the owner-wide
172
221
  // count stays 0 (its publisher is a shard, not this host), so an empty
173
222
  // aggregate must NOT discard the session buckets.
@@ -175,7 +224,7 @@ async function refreshShellJobsStatus(ownerPid) {
175
224
  } catch {
176
225
  value = EMPTY_SHELL_JOBS;
177
226
  }
178
- _shellJobsSegmentCache = { ownerPid, at: Date.now(), value };
227
+ rememberShellJobs(ownerPid, value);
179
228
  }
180
229
 
181
230
  // Newest-first, capped ids of job records with no `.done` marker, plus the
@@ -209,7 +258,11 @@ function listOpenShellJobs(names) {
209
258
  // the per-refresh cap doubles with it; a live (non-.done) record set is
210
259
  // a handful in practice and terminal ones age out on their own.
211
260
  .slice(0, 60);
212
- return { ids, ownerByJob };
261
+ const doneIds = [...done]
262
+ .filter((id) => names.includes(`${id}.json`))
263
+ .sort((a, b) => jobStampMs(b) - jobStampMs(a))
264
+ .slice(0, 30);
265
+ return { ids, ownerByJob, doneIds };
213
266
  }
214
267
 
215
268
  function summarizeShellJobs({ count, oldestMs, jobs, bySession }) {
@@ -221,6 +274,7 @@ function summarizeShellJobs({ count, oldestMs, jobs, bySession }) {
221
274
  count: bucket.count,
222
275
  elapsedLabel: Number.isFinite(bucket.oldestMs) ? formatElapsed(now - bucket.oldestMs) : '',
223
276
  jobs: bucket.jobs,
277
+ finished: bucket.finished,
224
278
  };
225
279
  }
226
280
  return { count, elapsedLabel, jobs, sessions };
@@ -1,6 +1,6 @@
1
1
  // ── Facade: tool-surface primitives + result summaries are re-exported from
2
- // their cohesive modules so every existing importer resolves unchanged. This
3
- // file keeps the display-name / arg-summary and aggregate-card clusters.
2
+ // their cohesive modules. This file keeps the display-name / arg-summary and
3
+ // aggregate-card clusters.
4
4
  import {
5
5
  DEFAULT_SUMMARY_MAX,
6
6
  AGENT_SURFACE_BRIEF_MAX,
@@ -140,6 +140,8 @@ export function displayToolName(name, args = {}) {
140
140
  return 'Media';
141
141
  case 'tidy':
142
142
  return 'Tidy';
143
+ case 'visualize':
144
+ return 'Visualize';
143
145
  case 'list_mcp_resources':
144
146
  case 'list_mcp_resource_templates':
145
147
  case 'cwd':
@@ -310,6 +312,11 @@ export function summarizeToolArgs(name, args, { max = DEFAULT_SUMMARY_MAX } = {}
310
312
  }
311
313
  case 'terminal':
312
314
  return compactParts([String(a.action || ''), a.tab ? `tab ${a.tab}` : '']);
315
+ case 'visualize': {
316
+ const input = a.input && typeof a.input === 'object' ? a.input : {};
317
+ const targets = Array.isArray(input.targets) ? input.targets.map(String).join(', ') : '';
318
+ return compactParts([String(a.action || ''), targets || String(input.tab || '')]);
319
+ }
313
320
  case 'office':
314
321
  return compactParts([String(a.action || ''), pathOrId(a.path, a.session, max)]);
315
322
  case 'media':
@@ -82,6 +82,7 @@ const TOOL_CATEGORY = new Map([
82
82
  ['office', 'Office'],
83
83
  ['media', 'Media'],
84
84
  ['tidy', 'Tidy'],
85
+ ['visualize', 'Visualize'],
85
86
  ['list_mcp_resources', 'Setup'],
86
87
  ['list_mcp_resource_templates', 'Setup'],
87
88
  ['cwd', 'Setup'],
@@ -124,6 +125,7 @@ const CATEGORY_COPY = new Map([
124
125
  ['Office', { active: 'Editing', done: 'Edited', noun: 'document action' }],
125
126
  ['Media', { active: 'Generating', done: 'Generated', noun: 'media action' }],
126
127
  ['Tidy', { active: 'Tidying', done: 'Tidied', noun: 'cleanup pass' }],
128
+ ['Visualize', { active: 'Showing', done: 'Showed', noun: 'artifact' }],
127
129
  ['Other', { active: 'Calling', done: 'Called', noun: 'tool' }],
128
130
  ]);
129
131
 
@@ -338,6 +340,17 @@ function officeUnit(a) {
338
340
  return unitDescriptor('Office', { count: 1, active, done, noun: 'document action', effect: true });
339
341
  }
340
342
 
343
+ function visualizeUnit(a) {
344
+ const action = String(a.action || '').toLowerCase();
345
+ if (action === 'capture') return unitDescriptor('Visualize', { count: 1, active: 'Capturing', done: 'Captured', noun: 'screenshot' });
346
+ if (action === 'export') return unitDescriptor('Visualize', { count: 1, active: 'Exporting', done: 'Exported', noun: 'file' });
347
+ if (action === 'annotate') return unitDescriptor('Visualize', { count: 1, active: 'Marking', done: 'Marked', noun: 'annotation' });
348
+ if (action === 'check') return unitDescriptor('Visualize', { count: 1, active: 'Checking', done: 'Checked', noun: 'page' });
349
+ if (action === 'inspect') return unitDescriptor('Visualize', { count: 1, active: 'Inspecting', done: 'Inspected', noun: 'page' });
350
+ if (action === 'close') return unitDescriptor('Visualize', { count: 1, active: 'Closing', done: 'Closed', noun: 'tab' });
351
+ return unitDescriptor('Visualize', { count: 1, active: 'Showing', done: 'Showed', noun: 'artifact' });
352
+ }
353
+
341
354
  function terminalUnit(a) {
342
355
  return String(a.action || '').toLowerCase() === 'list'
343
356
  ? unitDescriptor('Terminal', { count: 1, active: 'Listing', done: 'Listed', noun: 'terminal tab' })
@@ -642,6 +655,7 @@ const TOOL_UNITS = new Map([
642
655
  ['setup', setupUnit],
643
656
  ['media', mediaUnit],
644
657
  ['tidy', tidyUnit],
658
+ ['visualize', visualizeUnit],
645
659
  ['fetch', fetchUnit],
646
660
  ['recall', memoryReadUnit],
647
661
  ['recall_memory', memoryReadUnit],
@@ -21,14 +21,29 @@ export function createTranscriptRouteMetadata(session, route = {}, at = Date.now
21
21
  return { at, ...transcriptRouteMetadataFields({ modelId, model, provider, agent }) };
22
22
  }
23
23
 
24
+ /** A new stable message id (`meta.transcript.messageId`). */
25
+ export function newTranscriptMessageId() {
26
+ return `msg_${globalThis.crypto.randomUUID().replaceAll('-', '')}`;
27
+ }
28
+
29
+ export const stableMessageId = (value) => (typeof value === 'string' && value ? value : newTranscriptMessageId());
30
+
31
+ // Every persisted prompt/reply carries a stable `messageId` from creation on.
32
+ // Compaction rewrites copy `meta`, so the id survives them; the display-only
33
+ // compaction archive and a live view tell dropped rows from rewritten ones
34
+ // by it. A surface that drew the row first passes its id in.
24
35
  export function persistedUserTranscriptMetadata(value) {
25
36
  if (!value || typeof value !== 'object') return null;
26
37
  return {
38
+ messageId: stableMessageId(value.messageId),
27
39
  ...(Number.isFinite(Number(value.at)) ? { at: Number(value.at) } : {}),
28
40
  ...transcriptRouteMetadataFields(value),
29
41
  ...(typeof value.sender === 'string' && value.sender ? { sender: value.sender } : {}),
30
42
  // The device that submitted the prompt (host-stamped display name).
31
43
  ...(typeof value.device === 'string' && value.device ? { device: value.device } : {}),
44
+ // The turn's change-record key (the outer prompt id), so a restored user
45
+ // row still addresses its turn's Undo/Reapply.
46
+ ...(typeof value.checkpointId === 'string' && value.checkpointId ? { checkpointId: value.checkpointId } : {}),
32
47
  };
33
48
  }
34
49
 
@@ -37,5 +52,6 @@ export function persistedAssistantTranscriptMetadata(value, fallbackAt = Date.no
37
52
  const candidateAt = Number(value.assistantAt);
38
53
  const assistantAt = Number.isFinite(candidateAt) && candidateAt > 0 ? candidateAt : fallbackAt;
39
54
  value.assistantAt = assistantAt;
40
- return { at: assistantAt, ...transcriptRouteMetadataFields(value) };
55
+ value.assistantMessageId = stableMessageId(value.assistantMessageId);
56
+ return { messageId: value.assistantMessageId, at: assistantAt, ...transcriptRouteMetadataFields(value) };
41
57
  }