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
@@ -8,9 +8,13 @@
8
8
  */
9
9
  import { createHash, randomBytes } from 'node:crypto';
10
10
  import {
11
+ closeSync,
11
12
  existsSync,
13
+ fstatSync,
12
14
  mkdirSync,
15
+ openSync,
13
16
  readFileSync,
17
+ readSync,
14
18
  renameSync,
15
19
  statSync,
16
20
  unlinkSync,
@@ -303,6 +307,40 @@ function readAttachmentText(value) {
303
307
  return readAttachmentBuffer(value).toString('utf8');
304
308
  }
305
309
 
310
+ /**
311
+ * A referenced blob's UTF-8 text when the blob on disk holds at most
312
+ * `maxBytes`, else null. The size comes from the opened file, never from the
313
+ * reference's claimed sizeBytes, and at most `maxBytes + 1` bytes are read, so
314
+ * a blob that grows between the check and the read is rejected too. Missing,
315
+ * invalid or tampered blobs throw like readAttachmentBuffer.
316
+ */
317
+ export function readAttachmentTextWithin(value, maxBytes) {
318
+ const ref = typeof value === 'string' ? value : value?.attachmentRef;
319
+ const fd = openSync(attachmentPath(ref), 'r');
320
+ try {
321
+ const info = fstatSync(fd);
322
+ if (!info.isFile() || info.size <= 0) {
323
+ throw Object.assign(new Error('prompt attachment blob is invalid'), { code: ATTACHMENT_INVALID });
324
+ }
325
+ if (info.size > maxBytes) return null;
326
+ const buffer = Buffer.alloc(info.size + 1);
327
+ let length = 0;
328
+ while (length < buffer.length) {
329
+ const read = readSync(fd, buffer, length, buffer.length - length, length);
330
+ if (read === 0) break;
331
+ length += read;
332
+ }
333
+ if (length > maxBytes) return null;
334
+ const bytes = buffer.subarray(0, length);
335
+ if (attachmentRefForBuffer(bytes) !== ref) {
336
+ throw Object.assign(new Error('prompt attachment integrity check failed'), { code: ATTACHMENT_INTEGRITY });
337
+ }
338
+ return bytes.toString('utf8');
339
+ } finally {
340
+ closeSync(fd);
341
+ }
342
+ }
343
+
306
344
  export function attachmentTextForPart(part) {
307
345
  if (!isAttachmentReference(part)) return typeof part?.text === 'string' ? part.text : '';
308
346
  const text = readAttachmentText(part);
@@ -1,13 +1,9 @@
1
1
  // Thin facade for the channels worker runtime. The implementation was split
2
2
  // out into ./lib/worker-main.mjs plus focused lib/ modules; this file preserves
3
- // the exact public API and boot side-effects by re-exporting from worker-main.
3
+ // the current worker API and boot side-effects by re-exporting from worker-main.
4
4
  // Kept as the channels worker entrypoint the daemon loads.
5
5
  export {
6
- TOOL_DEFS,
7
6
  handleToolCall,
8
- handleToolCallWithBridgeRetry,
9
- init,
10
- instructions,
11
7
  isChannelBridgeActive,
12
8
  isChannelsDegraded,
13
9
  start,
@@ -114,8 +114,7 @@ function getControlResponsePath(instanceId) {
114
114
  function getStopFlagPath(instanceId) {
115
115
  return join(RUNTIME_ROOT, `stop-${sanitize(instanceId)}.flag`);
116
116
  }
117
- // Pure metadata-advert read: ownership is the OS seat lock, so a leftover
118
- // advert is never evicted here. A transient read during an atomic rename may
117
+ // Pure metadata-advert read. A transient read during an atomic rename may
119
118
  // yield empty/partial content: retry once after 50 ms before reporting the
120
119
  // advert as unreadable.
121
120
  function readActiveInstance() {
@@ -141,8 +140,6 @@ function buildActiveInstanceState(instanceId, meta) {
141
140
  supervisor_started_at: Date.now(),
142
141
  server_started_at: Date.now(),
143
142
  updatedAt: Date.now(),
144
- turnEndFile: getTurnEndPath(instanceId),
145
- statusFile: getStatusPath(instanceId),
146
143
  ...metaFields(meta),
147
144
  };
148
145
  }
@@ -193,26 +190,14 @@ function refreshActiveInstance(instanceId, meta, options) {
193
190
  (curRaw) => {
194
191
  const prevForPreserve = curRaw;
195
192
  const prev = activeInstanceStaleReason(curRaw) ? null : curRaw;
196
- // CAS guard (opt-in via options.onlyIfOwned): heartbeat/refresh ticks
197
- // check ownership OUTSIDE this lock, so a newer session can claim the
198
- // seat between that check and this locked update. Without this re-read,
199
- // the tick would overwrite the newer owner's instanceId (TOCTOU
200
- // re-steal -> ownership ping-pong / double provider connections).
201
- // Returning undefined aborts the update with no write. Explicit claims
202
- // (boot, claimBridgeOwnership) omit the option and stay last-wins.
203
- if (options?.onlyIfOwned && (!prev?.instanceId || prev.instanceId !== instanceId)) {
204
- return undefined;
205
- }
206
- // CAS guard (opt-in via options.onlyIfVacant): auto-start claim-if-vacant.
207
- // Abort the write when a live (non-stale) owner OTHER than us already holds
208
- // the seat — an auto-start must never steal from a live owner. A stale/dead
209
- // prior owner leaves prev=null above, so it does NOT block the claim; an
210
- // absent seat (prev=null) is claimable too.
211
- if (options?.onlyIfVacant && prev?.instanceId && prev.instanceId !== instanceId) {
212
- return undefined;
213
- }
214
193
  // Drop stale fields (pid/startedAt) written by older server versions.
215
- const { pid: _legacyPid, startedAt: _legacyStartedAt, ...prevRest } = prev ?? {};
194
+ const {
195
+ pid: _legacyPid,
196
+ startedAt: _legacyStartedAt,
197
+ turnEndFile: _turnEndFile,
198
+ statusFile: _statusFile,
199
+ ...prevRest
200
+ } = prev ?? {};
216
201
  const identity = buildRuntimeIdentity();
217
202
  // server_started_at tracks the CURRENT server_pid's start time so the
218
203
  // dev-sync barrier can verify the CHILD's freshness (the supervisor's
@@ -82,12 +82,6 @@ function createToolDispatch({ isChannelsDegraded, lifecycle }) {
82
82
  };
83
83
  break;
84
84
  }
85
- case 'rebind_current_transcript': {
86
- // Transcript forwarding is retired with channel messaging: accept
87
- // and no-op so legacy lead-side pushes never surface an error.
88
- result = { content: [{ type: 'text', text: 'transcript rebind retired' }] };
89
- break;
90
- }
91
85
  // memory — handled by memory-service.mjs MCP
92
86
  default:
93
87
  result = {
@@ -105,13 +99,7 @@ function createToolDispatch({ isChannelsDegraded, lifecycle }) {
105
99
  return result;
106
100
  }
107
101
 
108
- // IPC/HTTP wrapper: with channel messaging retired there is no transcript
109
- // pre-flush or tool-log relay — plain dispatch.
110
- async function handleToolCallWithBridgeRetry(toolName, args, signal) {
111
- return handleToolCall(toolName, args, signal);
112
- }
113
-
114
- return { handleToolCall, handleToolCallWithBridgeRetry };
102
+ return { handleToolCall };
115
103
  }
116
104
 
117
105
  export { createToolDispatch };
@@ -14,7 +14,7 @@ export function runWorkerIpc({
14
14
  getProvider: _getProvider,
15
15
  getConfig: _getConfig,
16
16
  handleMemoryCallResponse,
17
- handleToolCallWithBridgeRetry,
17
+ handleToolCall,
18
18
  bootProfile,
19
19
  }) {
20
20
  const sendToParent = (message) =>
@@ -94,7 +94,7 @@ export function runWorkerIpc({
94
94
  _inFlightChannelCalls.set(msg.callId, ac);
95
95
  let result;
96
96
  try {
97
- result = await handleToolCallWithBridgeRetry(msg.name, msg.args || {}, ac.signal);
97
+ result = await handleToolCall(msg.name, msg.args || {}, ac.signal);
98
98
  } finally {
99
99
  _inFlightChannelCalls.delete(msg.callId);
100
100
  }
@@ -4,7 +4,6 @@ import { createRequire } from 'node:module';
4
4
  import { loadConfig, createProvider, DATA_DIR } from './config.mjs';
5
5
  import { resolveVoiceRuntime } from './voice-runtime-fetcher.mjs';
6
6
  import { whisperThreadCount } from './voice-transcription.mjs';
7
- import { TOOL_DEFS } from '../tool-defs.mjs';
8
7
  import { ensureReady, stopVoiceWhisperServer } from './whisper-server.mjs';
9
8
  import { ensurePrivateRuntimeRoot, resolveRuntimeRoot } from '../../shared/runtime-root.mjs';
10
9
  import { Scheduler } from './scheduler.mjs';
@@ -102,7 +101,6 @@ runWorkerBootstrap({
102
101
  pruneStalePluginDataLogSiblings,
103
102
  DEFAULT_STALE_LOG_SIBLING_MAX,
104
103
  });
105
- const INSTRUCTIONS = '';
106
104
 
107
105
  // ── Parent notification helper ───────────────────────────────────────
108
106
  // This worker has no MCP transport of its own. All notifications flow
@@ -129,10 +127,7 @@ let _reloadDebounce = null;
129
127
  const STATUS_FILE = getStatusPath(INSTANCE_ID);
130
128
  const statusState = new JsonStateFile(STATUS_FILE, {});
131
129
  statusState.ensure();
132
- const scheduler = new Scheduler(
133
- config.nonInteractive ?? [],
134
- config.interactive ?? []
135
- );
130
+ const scheduler = new Scheduler(config.nonInteractive ?? [], config.interactive ?? []);
136
131
  // Schedules fire as visible sessions; the session runner belongs to the
137
132
  // session-runtime layer, so this worker entry injects it (lazy, like webhooks).
138
133
  scheduler.setScheduleRunner(async (schedule, opts) => {
@@ -250,19 +245,12 @@ function wireEventQueueHandlers(eventQueue) {
250
245
  // re-read at probe time so a stale-connected flag cannot mask a lost seat.
251
246
  eventQueue.setOwnerGetter(() => bridgeRuntimeConnected && currentOwnerState().owned);
252
247
  }
253
- // Inbound messaging, provider interaction handlers, and channel voice-message
254
- // transcription are DELETED with Discord/Telegram (user decision: PWA replaces
255
- // channels). The headless provider emits no events, so nothing wires here.
256
- // Tool dispatch in worker mode goes through the IPC `call` handler at the
257
- // bottom of this file (parent's `callWorker` → `handleToolCall`). There is no
258
- // orphan worker-level MCP Server: the parent (server.mjs) owns the single
259
- // connected transport and routes CallTool through the IPC `call` path.
260
248
  // ── Worker/HTTP tool-call dispatch ──────────────────────────────────────────
261
249
  // Runtime lifecycle dispatch only (activate_channel_bridge / reload_config):
262
250
  // threaded as a lifecycle bag of lazy getters so the module reads live
263
251
  // file-level references at call time. Used by the HTTP MCP CallTool path and
264
252
  // the worker IPC `call` handler at the bottom of this file.
265
- const { handleToolCall, handleToolCallWithBridgeRetry } = createToolDispatch({
253
+ const { handleToolCall } = createToolDispatch({
266
254
  isChannelsDegraded,
267
255
  lifecycle: {
268
256
  getChannelBridgeActive: () => channelBridgeActive,
@@ -277,14 +265,6 @@ const { handleToolCall, handleToolCallWithBridgeRetry } = createToolDispatch({
277
265
  reloadRuntimeConfig,
278
266
  },
279
267
  });
280
- async function init(_sharedMcp) {
281
- // _sharedMcp is no longer used. Notifications now flow via IPC to the parent
282
- // (sendNotifyToParent above). The parameter is retained for backward
283
- // compatibility with any caller that still passes a Server reference.
284
- scheduler.setInjectHandler((channelId, name, content, options) => {
285
- injectAndRecord(channelId, name, content, options);
286
- });
287
- }
288
268
  function ensureConfigWatcher() {
289
269
  if (_configWatcher) return;
290
270
  try {
@@ -374,19 +354,9 @@ if (_isWorkerMode && process.send && process.env.MIXDOG_DAEMON_HOST !== '1') {
374
354
  getProvider: () => provider,
375
355
  getConfig: () => config,
376
356
  handleMemoryCallResponse,
377
- handleToolCallWithBridgeRetry,
357
+ handleToolCall,
378
358
  bootProfile,
379
359
  });
380
360
  }
381
361
 
382
- export {
383
- TOOL_DEFS,
384
- handleToolCall,
385
- handleToolCallWithBridgeRetry,
386
- init,
387
- INSTRUCTIONS as instructions,
388
- isChannelBridgeActive,
389
- isChannelsDegraded,
390
- start,
391
- stop,
392
- };
362
+ export { handleToolCall, isChannelBridgeActive, isChannelsDegraded, start, stop };
@@ -240,6 +240,12 @@ export function writeJsonAtomicSync(filePath, value, opts = {}) {
240
240
  return writeFileAtomicSync(filePath, `${JSON.stringify(value, null, opts.compact ? 0 : 2)}\n`, opts);
241
241
  }
242
242
 
243
+ // Windows editors and PowerShell 5 save UTF-8 with a leading byte order mark,
244
+ // which JSON.parse rejects; a hand-edited state file must still load.
245
+ export function parseJsonText(text) {
246
+ return JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);
247
+ }
248
+
243
249
  function recoverJsonMutationRead(error) {
244
250
  // Missing/malformed JSON retains the existing initializer contract. An I/O
245
251
  // or permission failure is not an empty document and must never authorize
@@ -255,7 +261,7 @@ export function updateJsonAtomicSync(filePath, mutator, opts = {}) {
255
261
  () => {
256
262
  let cur = null;
257
263
  try {
258
- cur = JSON.parse(readFileSync(filePath, 'utf8'));
264
+ cur = parseJsonText(readFileSync(filePath, 'utf8'));
259
265
  } catch (error) {
260
266
  cur = recoverJsonMutationRead(error);
261
267
  }
@@ -336,7 +342,7 @@ export async function updateJsonAtomic(filePath, mutator, opts = {}) {
336
342
  async () => {
337
343
  let cur = null;
338
344
  try {
339
- cur = JSON.parse(await readFileAsync(filePath, 'utf8'));
345
+ cur = parseJsonText(await readFileAsync(filePath, 'utf8'));
340
346
  } catch (error) {
341
347
  cur = recoverJsonMutationRead(error);
342
348
  }
@@ -0,0 +1,8 @@
1
+ // stderr diagnostics that must never throw (closed or broken stderr).
2
+ export function writeStderrBestEffort(line) {
3
+ try {
4
+ process.stderr.write(line);
5
+ } catch {
6
+ /* diagnostics only */
7
+ }
8
+ }
@@ -74,6 +74,18 @@ export function markCodeGraphDirtyPaths(paths) {
74
74
  }
75
75
  }
76
76
 
77
+ /** Drop the resident graph, pending dirty paths and dirty generation of one
78
+ * root (exact canonical match; nested roots are other roots). Returns the
79
+ * names of the state that was actually dropped. */
80
+ export function forgetCodeGraphStateRoot(root) {
81
+ const key = canonicalGraphCwd(root);
82
+ const removed = [];
83
+ if (codeGraphCache.delete(key)) removed.push('resident-graph');
84
+ if (codeGraphDirtyPaths.delete(key)) removed.push('dirty-paths');
85
+ if (codeGraphDirtyGen.delete(key)) removed.push('dirty-generation');
86
+ return removed;
87
+ }
88
+
77
89
  export function registerCodeGraphDrain(fn) {
78
90
  drainCodeGraphCacheFn = typeof fn === 'function' ? fn : null;
79
91
  }
@@ -21,6 +21,7 @@ import { DEFAULTS_VERSION, DEFAULTS_VERSION_KEY, configPath, readConfig, updateC
21
21
  import { DEFAULT_DISABLED_AGENT_ROSTER, disabledAgentDelta, disabledAgentIds } from './agent-route-config.mjs';
22
22
  import { withGrandfatheredBuiltins } from './builtin-grandfathering.mjs';
23
23
  import { DEFAULT_ORCHESTRATION_MODE, legacyWorkflowOrchestrationMode } from './orchestration.mjs';
24
+ import { WORKTREE_SETTINGS_DEFAULTS } from './worktrees/settings.mjs';
24
25
 
25
26
  export { DEFAULTS_VERSION, DEFAULTS_VERSION_KEY };
26
27
 
@@ -33,6 +34,7 @@ const AGENT_SECTION_DEFAULTS = Object.freeze({
33
34
  update: Object.freeze({ auto: true }),
34
35
  recap: Object.freeze({ enabled: true }),
35
36
  memoryTools: Object.freeze({ enabled: true }),
37
+ worktree: WORKTREE_SETTINGS_DEFAULTS,
36
38
  });
37
39
  const MODULE_DEFAULTS = Object.freeze({ enabled: true });
38
40
 
@@ -6,7 +6,7 @@
6
6
  import { spawn } from 'node:child_process';
7
7
  import { serveWorkerRequests } from './worker-requests.mjs';
8
8
 
9
- function runGit({ args, cwd, input, env, timeoutMs, maxBytes }) {
9
+ function runGit({ args, cwd, input, env, timeoutMs, maxBytes, stdoutEncoding = 'utf8' }) {
10
10
  return new Promise((resolvePromise, rejectPromise) => {
11
11
  const hasInput = (typeof input === 'string' || ArrayBuffer.isView(input)) && input.length > 0;
12
12
  const child = spawn('git', args, {
@@ -55,7 +55,8 @@ function runGit({ args, cwd, input, env, timeoutMs, maxBytes }) {
55
55
  child.once('close', (code) => {
56
56
  const result = {
57
57
  code: Number(code ?? 1),
58
- stdout: Buffer.concat(stdout).toString('utf8'),
58
+ // 'base64' keeps non-UTF-8 bytes (a replayable patch) intact across the thread hop.
59
+ stdout: Buffer.concat(stdout).toString(stdoutEncoding === 'base64' ? 'base64' : 'utf8'),
59
60
  stderr: Buffer.concat(stderr).toString('utf8'),
60
61
  };
61
62
  // A failed stdin write only matters when git otherwise reported success.
@@ -13,8 +13,9 @@ const requestGit = createWorkerRequestClient(new URL('./git-runner-worker.mjs',
13
13
  /**
14
14
  * Resolves to { code, stdout, stderr }. Rejects with code ETIMEDOUT after
15
15
  * timeoutMs (the child is killed), EMAXBUFFER once stdout+stderr exceed
16
- * maxBytes, or the spawn error itself.
16
+ * maxBytes, or the spawn error itself. `stdoutEncoding: 'base64'` returns the
17
+ * exact stdout bytes base64-encoded instead of decoded as UTF-8.
17
18
  */
18
- export function runGitOffThread(args, { cwd, input = '', env = null, timeoutMs, maxBytes }) {
19
- return requestGit({ args, cwd, input, env, timeoutMs, maxBytes });
19
+ export function runGitOffThread(args, { cwd, input = '', env = null, timeoutMs, maxBytes, stdoutEncoding = 'utf8' }) {
20
+ return requestGit({ args, cwd, input, env, timeoutMs, maxBytes, stdoutEncoding });
20
21
  }
@@ -24,6 +24,12 @@ function positiveTokens(value) {
24
24
  return Number.isFinite(tokens) && tokens > 0 ? Math.floor(tokens) : 0;
25
25
  }
26
26
 
27
+ /** An exact context-window selection in tokens (`contextTokens`); undefined when unset or invalid. */
28
+ export function normalizeContextTokens(value) {
29
+ const tokens = Math.round(Number(value));
30
+ return Number.isFinite(tokens) && tokens > 0 ? tokens : undefined;
31
+ }
32
+
27
33
  /**
28
34
  * The default and the largest selectable window of one model row, in tokens.
29
35
  * `defaultWindow` is 0 when the row states no window to start from.
@@ -69,7 +69,8 @@ function projectModelsDevRow(row) {
69
69
  if (limit) out.limit = limit;
70
70
  const modalities = pickArrays(row.modalities, MODELSDEV_MODALITY_FIELDS);
71
71
  if (modalities) out.modalities = modalities;
72
- if (row.reasoning === true) out.reasoning = true;
72
+ // A declared `reasoning: false` must stay distinct from absent (capabilityFlag).
73
+ if (typeof row.reasoning === 'boolean') out.reasoning = row.reasoning;
73
74
  if (Array.isArray(row.reasoning_options) && row.reasoning_options.length > 0) {
74
75
  out.reasoning_options = row.reasoning_options;
75
76
  }
@@ -129,8 +130,8 @@ const LITELLM_NUMBER_FIELDS = [
129
130
  'output_cost_per_video_token',
130
131
  'output_cost_per_second',
131
132
  ];
132
- // _normalize tests each of these with `=== true`, so only a true value carries
133
- // information; anything else is indistinguishable from absent.
133
+ // _normalize keeps each declared boolean (an explicit false outranks a lower
134
+ // layer's true); any other value is indistinguishable from absent.
134
135
  const LITELLM_FLAG_FIELDS = [
135
136
  'supports_vision',
136
137
  'supports_function_calling',
@@ -164,7 +165,7 @@ function projectLitellmRow(row) {
164
165
  out[field] = value;
165
166
  }
166
167
  for (const field of LITELLM_FLAG_FIELDS) {
167
- if (row[field] === true) out[field] = true;
168
+ if (typeof row[field] === 'boolean') out[field] = row[field];
168
169
  }
169
170
  for (const field of LITELLM_STRING_FIELDS) {
170
171
  const value = row[field];