mixdog 1.3.5 → 1.4.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 (341) hide show
  1. package/NOTICE.md +2 -2
  2. package/README.md +2 -2
  3. package/package.json +2 -11
  4. package/scripts/daemon-stub.mjs +1 -1
  5. package/scripts/gate-local.mjs +4 -2
  6. package/scripts/native-release-status.mjs +2 -2
  7. package/scripts/recall-history-cases.json +1 -1
  8. package/scripts/suite-health.mjs +10 -1
  9. package/scripts/test.mjs +7 -11
  10. package/src/agents/reviewer/AGENT.md +7 -11
  11. package/src/agents/reviewer/agent.json +1 -1
  12. package/src/defaults/shipped-history.json +17 -1
  13. package/src/defaults/skills/browser-use/SKILL.md +59 -11
  14. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  15. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  16. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  17. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  18. package/src/defaults/skills/computer-use/SKILL.md +33 -9
  19. package/src/defaults/skills/setup/SKILL.md +22 -0
  20. package/src/defaults/skills/setup/references/actions.md +39 -5
  21. package/src/defaults/skills/setup/references/surfaces.md +11 -2
  22. package/src/defaults/skills/visualize/SKILL.md +2 -1
  23. package/src/lib/rules-builder.cjs +10 -8
  24. package/src/rules/agent/AGENT.md +6 -6
  25. package/src/rules/lead/LEAD.md +18 -20
  26. package/src/rules/shared/05-tool-calls.md +5 -6
  27. package/src/rules/shared/10-tool-workflow.md +2 -0
  28. package/src/rules/shared/60-verification.md +7 -5
  29. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  30. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  31. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  32. package/src/runtime/agent/orchestrator/config.mjs +17 -1
  33. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  34. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
  35. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
  36. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  37. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
  38. package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
  39. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +181 -133
  40. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
  41. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  42. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  43. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  45. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +145 -66
  46. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  47. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
  48. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  49. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
  50. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  51. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  52. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -13
  53. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  54. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  55. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  56. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  57. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  58. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
  59. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  60. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  61. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  62. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  63. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  64. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  65. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  66. package/src/runtime/agent/orchestrator/providers/registry.mjs +26 -0
  67. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  68. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  69. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
  70. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  71. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  72. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  73. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
  74. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  75. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  76. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
  77. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +133 -22
  78. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  79. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  80. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
  81. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
  82. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
  83. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  84. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
  85. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
  86. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
  87. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
  88. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
  89. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
  90. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -2
  91. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  92. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +3 -2
  93. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  94. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  95. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
  96. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  97. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
  98. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  99. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  100. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  101. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  102. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  103. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
  104. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  105. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  106. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
  107. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
  108. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  109. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
  110. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  111. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
  112. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  113. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
  114. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
  115. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  116. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
  117. package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
  118. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  119. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  120. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  121. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  122. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  123. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  124. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  125. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  126. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  127. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
  128. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
  129. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
  130. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
  131. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  132. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  133. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  134. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  135. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +18 -1
  136. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  137. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  138. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  139. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  140. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  141. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  142. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  143. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  144. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
  145. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
  146. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  147. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  148. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  149. package/src/runtime/browser-bridge/client.mjs +73 -8
  150. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  151. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  152. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  153. package/src/runtime/channels/lib/config.mjs +6 -61
  154. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  155. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  156. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  157. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  158. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  159. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  160. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  161. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  162. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  163. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  164. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  165. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  166. package/src/runtime/channels/lib/scheduler.mjs +33 -147
  167. package/src/runtime/channels/lib/schedules-db.mjs +34 -11
  168. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  169. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
  170. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  171. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  172. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  173. package/src/runtime/channels/lib/worker-main.mjs +10 -34
  174. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  175. package/src/runtime/computer-bridge/actions.mjs +9 -1
  176. package/src/runtime/computer-bridge/client.mjs +180 -8
  177. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  178. package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
  179. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  180. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  181. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  182. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  183. package/src/runtime/connectors/google-mcp.mjs +10 -12
  184. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  185. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  186. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  187. package/src/runtime/session-search/session-search-db.mjs +73 -9
  188. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  189. package/src/runtime/shared/abort-race.mjs +89 -0
  190. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  191. package/src/runtime/shared/agent-kind.mjs +4 -3
  192. package/src/runtime/shared/bounded-download.mjs +8 -3
  193. package/src/runtime/shared/config.mjs +2 -13
  194. package/src/runtime/shared/connector-accounts.mjs +20 -10
  195. package/src/runtime/shared/connector-catalog.d.mts +29 -0
  196. package/src/runtime/shared/connector-catalog.mjs +150 -0
  197. package/src/runtime/shared/connector-triggers.mjs +22 -19
  198. package/src/runtime/shared/defaults-separation.mjs +2 -14
  199. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  200. package/src/runtime/shared/err-text.mjs +24 -15
  201. package/src/runtime/shared/file-permissions.d.mts +0 -8
  202. package/src/runtime/shared/file-permissions.mjs +0 -11
  203. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  204. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  205. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  206. package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
  207. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  208. package/src/runtime/shared/mixy-presence.mjs +22 -0
  209. package/src/runtime/shared/orchestration.d.mts +2 -0
  210. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  211. package/src/runtime/shared/profile-config.cjs +1 -1
  212. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  213. package/src/runtime/shared/prompt-origin.mjs +21 -0
  214. package/src/runtime/shared/provider-accounts.mjs +7 -1
  215. package/src/runtime/shared/provider-display-name.mjs +29 -0
  216. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  217. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  218. package/src/runtime/shared/routine-trigger.mjs +10 -0
  219. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  220. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  221. package/src/runtime/shared/session-activity-signal.mjs +34 -1
  222. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  223. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  224. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  225. package/src/runtime/shared/tool-result-summary.mjs +1 -14
  226. package/src/runtime/shared/worktrees/test-support.mjs +9 -4
  227. package/src/runtime/terminal-bridge/client.mjs +10 -1
  228. package/src/runtime/visualize-bridge/client.mjs +27 -8
  229. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  230. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  231. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  232. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  233. package/src/session-runtime/agent-home-delivery.mjs +448 -185
  234. package/src/session-runtime/agent-task-sessions.mjs +329 -180
  235. package/src/session-runtime/boot/apis.mjs +9 -0
  236. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  237. package/src/session-runtime/boot/providers.mjs +3 -0
  238. package/src/session-runtime/boot/tools.mjs +6 -1
  239. package/src/session-runtime/config-lifecycle.mjs +6 -0
  240. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  241. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
  242. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
  243. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  244. package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
  245. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  246. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  247. package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
  248. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  249. package/src/session-runtime/mixy-heartbeat.mjs +153 -33
  250. package/src/session-runtime/notification-bus.mjs +31 -117
  251. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  252. package/src/session-runtime/notification-listeners.mjs +76 -0
  253. package/src/session-runtime/owned-automation-run.mjs +2 -1
  254. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  255. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  256. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  257. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  258. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  259. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  260. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  261. package/src/session-runtime/routine-owner.mjs +40 -9
  262. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  263. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
  264. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  265. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  266. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  267. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  268. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  269. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  270. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  271. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  272. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  273. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  274. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  275. package/src/session-runtime/services/channel-admin.mjs +7 -13
  276. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  277. package/src/session-runtime/services/seeds.mjs +0 -28
  278. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  279. package/src/session-runtime/session-create/session-options.mjs +1 -0
  280. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  281. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  282. package/src/session-runtime/settings-system-api.mjs +13 -1
  283. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  284. package/src/session-runtime/setup-tool/executor.mjs +145 -22
  285. package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
  286. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  287. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
  288. package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
  289. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  290. package/src/session-runtime/tool-policy/policy-stage.mjs +16 -2
  291. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  292. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  293. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  294. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  295. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  296. package/src/standalone/channel-transport.mjs +1 -1
  297. package/src/standalone/daemon-channels-loader.mjs +10 -8
  298. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  299. package/src/standalone/daemon-session-control/request.mjs +51 -0
  300. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  301. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  302. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  303. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  304. package/src/standalone/daemon-session-control.mjs +124 -188
  305. package/src/standalone/daemon.mjs +26 -3
  306. package/src/standalone/session-client.mjs +7 -3
  307. package/src/standalone/session-protocol.mjs +5 -0
  308. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  309. package/src/standalone/session-service/quota-resume.mjs +3 -0
  310. package/src/standalone/session-service/retention/busy.mjs +65 -1
  311. package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
  312. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  313. package/src/standalone/session-tool-output.mjs +15 -7
  314. package/src/tui/app/model-options.mjs +3 -28
  315. package/src/tui/dist/index.mjs +58 -64
  316. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  317. package/src/tui/session/initial-state.mjs +3 -0
  318. package/src/tui/session/notice-surface.mjs +7 -1
  319. package/src/tui/session/queue-helpers.mjs +3 -42
  320. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  321. package/src/tui/session/session-api/routes-write.mjs +5 -1
  322. package/src/tui/session/session-api/routes.mjs +1 -0
  323. package/src/tui/session/session-api/settings.mjs +17 -1
  324. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  325. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  326. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  327. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  328. package/src/tui/session/session-flow/drain.mjs +118 -149
  329. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  330. package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
  331. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  332. package/src/tui/session/tool-approval-request.mjs +39 -0
  333. package/src/tui/session/tool-approval-settle.mjs +62 -0
  334. package/src/tui/session/tool-approval.mjs +69 -115
  335. package/src/tui/session/tui-steering-persist.mjs +8 -1
  336. package/src/tui/session/turn-stream.mjs +19 -2
  337. package/src/tui/session/turn.mjs +1 -0
  338. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  339. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  340. package/scripts/code-graph-description-contract.mjs +0 -188
  341. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -0,0 +1,123 @@
1
+ // worker-index/released-store.mjs
2
+ // Which agent sessions their owner closed (the agent tool's `close`): session
3
+ // id → when. A closed session stays open and resumable, so a session scan
4
+ // (also after a daemon restart) would list it again; the marker is what keeps
5
+ // its rows `released` until a new turn starts on it. It lives in a file of its
6
+ // own beside the worker index, so a writer that rebuilds the index document
7
+ // (an older daemon) can never drop it. Entries expire after the tombstone TTL,
8
+ // judged on every read, not only when the file changes.
9
+ import { readFileSync, statSync } from 'node:fs';
10
+
11
+ import { parseJsonText } from '../../../../runtime/shared/atomic-file.mjs';
12
+ import { createIndexWriteQueue } from '../index-write-queue.mjs';
13
+ import { TAG_TOMBSTONE_TTL_MS } from '../worker-rows.mjs';
14
+
15
+ export const RELEASED_FILE = 'agent-workers-released.json';
16
+
17
+ /** id → epoch ms of every entry of a raw document (expired ones included). */
18
+ function parseReleased(doc) {
19
+ const raw = doc?.released && typeof doc.released === 'object' ? doc.released : {};
20
+ return new Map(
21
+ Object.entries(raw)
22
+ .map(([sessionId, at]) => [sessionId, Date.parse(String(at)) || 0])
23
+ .filter(([sessionId]) => sessionId)
24
+ );
25
+ }
26
+
27
+ /** The next document: unexpired entries plus the mutator's changes. */
28
+ function rewriteReleased(cur, mutator) {
29
+ const cutoff = Date.now() - TAG_TOMBSTONE_TTL_MS;
30
+ const entries = new Map();
31
+ for (const [sessionId, at] of parseReleased(cur)) {
32
+ if (at >= cutoff) entries.set(sessionId, new Date(at).toISOString());
33
+ }
34
+ mutator(entries);
35
+ return { version: 1, released: Object.fromEntries(entries) };
36
+ }
37
+
38
+ /** `file` may be null (no data dir): reads are empty and writes are no-ops. */
39
+ export function createReleasedStore(file) {
40
+ let cache = null; // { mtimeMs, size, doc, at }
41
+ let dirty = true;
42
+ // Unpersisted writes are read from the queue's projection.
43
+ let projected = null; // { version, at }
44
+
45
+ const queue = createIndexWriteQueue({
46
+ file,
47
+ rewrite: rewriteReleased,
48
+ readDoc: () => {
49
+ dirty = true;
50
+ entries();
51
+ return cache?.doc ?? null;
52
+ },
53
+ onPersisted: () => {
54
+ dirty = true;
55
+ },
56
+ });
57
+
58
+ /** id → epoch ms, as written (not yet filtered by expiry). */
59
+ function entries() {
60
+ const doc = queue.projection();
61
+ if (doc) {
62
+ if (!projected || projected.version !== queue.version()) {
63
+ projected = { version: queue.version(), at: parseReleased(doc) };
64
+ }
65
+ return projected.at;
66
+ }
67
+ if (!file) return new Map();
68
+ // Only a missing file is an empty store; any other read error propagates
69
+ // (queue.write reports it and queues nothing; a reader sees it thrown).
70
+ let st;
71
+ try {
72
+ st = statSync(file);
73
+ } catch (error) {
74
+ if (error?.code !== 'ENOENT') throw error;
75
+ cache = null;
76
+ return new Map();
77
+ }
78
+ if (!dirty && cache && cache.mtimeMs === st.mtimeMs && cache.size === st.size) return cache.at;
79
+ let parsed = null;
80
+ let text = null;
81
+ try {
82
+ text = readFileSync(file, 'utf8');
83
+ } catch (error) {
84
+ if (error?.code !== 'ENOENT') throw error;
85
+ }
86
+ if (text !== null) {
87
+ try {
88
+ parsed = parseJsonText(text);
89
+ } catch (error) {
90
+ // Left on disk and reported; the next save moves it aside to
91
+ // `<file>.corrupt-<ts>` (atomic-file's damaged-state recovery) instead
92
+ // of overwriting it.
93
+ process.stderr.write(`[released-store] ${file} is malformed (${error.message}); markers unreadable\n`);
94
+ }
95
+ }
96
+ cache = { mtimeMs: st.mtimeMs, size: st.size, doc: parsed, at: parseReleased(parsed) };
97
+ dirty = false;
98
+ return cache.at;
99
+ }
100
+
101
+ return {
102
+ /** Whether the owner closed this session less than the TTL ago. */
103
+ isReleased: (sessionId) => entries().get(sessionId) >= Date.now() - TAG_TOMBSTONE_TTL_MS,
104
+ mark(sessionIds) {
105
+ const at = new Date().toISOString();
106
+ queue.write((entriesById) => {
107
+ for (const sessionId of sessionIds) entriesById.set(sessionId, at);
108
+ });
109
+ },
110
+ clear(sessionId) {
111
+ if (!entries().has(sessionId)) return;
112
+ queue.write((entriesById) => {
113
+ entriesById.delete(sessionId);
114
+ });
115
+ },
116
+ flush: queue.flush,
117
+ flushSync: queue.flushSync,
118
+ hasUnpersisted: queue.hasUnpersisted,
119
+ invalidate: () => {
120
+ dirty = true;
121
+ },
122
+ };
123
+ }
@@ -0,0 +1,112 @@
1
+ // worker-index/restart-settlement.mjs
2
+ // Rows whose turn a process exit or restart ended: this process's active rows
3
+ // settled as failed on exit, stale active rows and approval waits settled at
4
+ // startup and on later sweeps, and the owner's restart-failure notification
5
+ // stamped once queued. Owns the keys of the rows this process marked active.
6
+ import { positiveInt } from '../helpers.mjs';
7
+ import { workerRowKey } from '../worker-rows.mjs';
8
+ import { clearAwaitingUser } from './approval-wait.mjs';
9
+ import {
10
+ createRowLiveness,
11
+ isActiveWorkerRow,
12
+ isStaleApprovalWait,
13
+ isUnnotifiedRestartFailure,
14
+ PROCESS_RESTART_FAILURE,
15
+ runtimeDied,
16
+ } from './row-liveness.mjs';
17
+
18
+ export function createRestartSettlement({ store, cfgMod, mgr }) {
19
+ const liveness = createRowLiveness({
20
+ cfgMod,
21
+ isSessionRunning: (sessionId) => mgr.isSessionTurnInFlight?.(sessionId) === true,
22
+ });
23
+ // Rows this process marked active; settled as failed on exit (their turn
24
+ // dies with the process) so a crash of the host never leaves them
25
+ // "running" forever.
26
+ const activeWorkerKeys = new Set();
27
+
28
+ /** Track whether the row written under `key` is one this process runs. */
29
+ function trackActiveRow(key, row) {
30
+ if (isActiveWorkerRow(row)) activeWorkerKeys.add(key);
31
+ else activeWorkerKeys.delete(key);
32
+ }
33
+
34
+ function flushActiveWorkerRows() {
35
+ if (!activeWorkerKeys.size) return;
36
+ const keys = [...activeWorkerKeys];
37
+ activeWorkerKeys.clear();
38
+ const now = Date.now();
39
+ store.write((byKey) => {
40
+ for (const key of keys) {
41
+ const current = byKey.get(key);
42
+ if (!current || positiveInt(current.runtimePid) !== process.pid) continue;
43
+ if (isActiveWorkerRow(current)) {
44
+ byKey.set(key, liveness.failedRow(current, now, PROCESS_RESTART_FAILURE, true));
45
+ }
46
+ }
47
+ });
48
+ }
49
+
50
+ // Startup recovery: stale active rows settle — as failed when another
51
+ // process ran their turn (it is gone, or is the predecessor still shutting
52
+ // down: either way the turn never finished), otherwise to idle — and an
53
+ // approval wait left behind by a runtime that is gone (daemon restart) is
54
+ // cleared. `deadOnly` (later sweeps) settles only rows whose runtime is
55
+ // provably dead, never a live process's quiet turn.
56
+ function recoverStaleWorkerRows({ deadOnly = false } = {}) {
57
+ const now = Date.now();
58
+ const rows = store.readAll();
59
+ const isStale = deadOnly
60
+ ? (row) => isActiveWorkerRow(row) && runtimeDied(row)
61
+ : (row) => liveness.isStaleActive(row, now);
62
+ const staleActive = rows.filter(isStale);
63
+ const staleWaits = rows.some(isStaleApprovalWait);
64
+ if (!staleActive.length && !staleWaits) return false;
65
+ if (staleActive.length) {
66
+ store.write((byKey) => {
67
+ for (const row of staleActive) {
68
+ const key = workerRowKey(row);
69
+ const current = byKey.get(key);
70
+ if (!current || !isStale(current)) continue;
71
+ const ranElsewhere = positiveInt(current.runtimePid) && positiveInt(current.runtimePid) !== process.pid;
72
+ byKey.set(
73
+ key,
74
+ ranElsewhere ? liveness.failedRow(current, now, PROCESS_RESTART_FAILURE) : liveness.idleRow(current, now)
75
+ );
76
+ }
77
+ });
78
+ }
79
+ if (staleWaits) store.update((byKey) => clearAwaitingUser(byKey, isStaleApprovalWait));
80
+ return true;
81
+ }
82
+
83
+ /** Rows whose turn a process restart ended and whose owner has not been told
84
+ * yet — whoever settled the row (this process at startup, or the
85
+ * predecessor's exit flush). Read-only: the caller enqueues the owner's
86
+ * notification durably, THEN calls `markRestartNotified`, so a crash in
87
+ * between retries (the notification's stable id makes the retry exactly-once). */
88
+ function pendingRestartFailures() {
89
+ return store.readAll().filter(isUnnotifiedRestartFailure);
90
+ }
91
+
92
+ /** Stamp these rows as told, once their notification is durably queued. */
93
+ function markRestartNotified(rows) {
94
+ const stamp = new Date().toISOString();
95
+ store.write((byKey) => {
96
+ for (const row of rows) {
97
+ const key = workerRowKey(row);
98
+ const current = byKey.get(key);
99
+ if (!current || !isUnnotifiedRestartFailure(current)) continue;
100
+ byKey.set(key, { ...current, restartNotified: stamp });
101
+ }
102
+ });
103
+ }
104
+
105
+ return {
106
+ trackActiveRow,
107
+ flushActiveWorkerRows,
108
+ recoverStaleWorkerRows,
109
+ pendingRestartFailures,
110
+ markRestartNotified,
111
+ };
112
+ }
@@ -0,0 +1,36 @@
1
+ // worker-index/row-reads.mjs
2
+ // Scoped reads of the worker rows and tag tombstones: a row a tombstone still
3
+ // blocks never reads as work, and a legacy tombstone without an owner takes
4
+ // the one its session resolves to.
5
+ import { clean, rowMatchesContext } from '../helpers.mjs';
6
+ import { recoverTagTombstoneOwner } from '../worker-rows.mjs';
7
+ import {
8
+ findTagTombstone,
9
+ tagTombstoneKey,
10
+ tombstoneBlocksWork,
11
+ } from '../../../../runtime/shared/agent-reap-state.mjs';
12
+
13
+ export function createWorkerRowReads(store, mgr) {
14
+ function readWorkerRows(context = {}) {
15
+ const { rows, tombstones: savedTombstones } = store.readSnapshot();
16
+ if (rows.length === 0) return rows;
17
+ const tombstones = new Map(recoverTombstoneOwners(savedTombstones).map((row) => [tagTombstoneKey(row), row]));
18
+ return rows.filter(
19
+ (row) => rowMatchesContext(row, context) && !tombstoneBlocksWork(row, findTagTombstone(row, tombstones))
20
+ );
21
+ }
22
+
23
+ function readAllTagTombstones() {
24
+ return recoverTombstoneOwners(store.readTombstones());
25
+ }
26
+
27
+ function recoverTombstoneOwners(rows) {
28
+ if (!rows.some((row) => !clean(row.parentSessionId || row.ownerSessionId))) return rows;
29
+ const sessions = typeof mgr.listSessions === 'function' ? mgr.listSessions({ includeClosed: true }) : [];
30
+ // Resolve legacy ownership against all sessions, never just the caller's
31
+ // scope: filtering first would conceal an ambiguous sibling owner.
32
+ return rows.map((row) => recoverTagTombstoneOwner(row, sessions));
33
+ }
34
+
35
+ return { readWorkerRows, readAllTagTombstones };
36
+ }
@@ -65,6 +65,8 @@ export function normalizeWorkerRows(value) {
65
65
  // Additive and transient: present only while the worker's turn waits on
66
66
  // a user approval (worker-index setAwaitingUser).
67
67
  ...(row.awaitingUser === 'approval' ? { awaitingUser: 'approval' } : {}),
68
+ // Present only on an agent its owner closed (the agent tool's `close`).
69
+ ...(row.released === true ? { released: true } : {}),
68
70
  }))
69
71
  .filter((row) => !isLeadPoolAgent(row.agent) && keepWorkerRow(row));
70
72
  }
@@ -4,10 +4,11 @@
4
4
  // worker index of a process over one file shares one store (acquireWorkerRowStore),
5
5
  // so all of them serialize through the same projection and queue.
6
6
  import { readFileSync, statSync } from 'node:fs';
7
- import { resolve } from 'node:path';
7
+ import { dirname, join, resolve } from 'node:path';
8
8
 
9
9
  import { createIndexWriteQueue } from '../index-write-queue.mjs';
10
10
  import { normalizeTagTombstones, tagTombstoneKey, workerRowKey } from '../worker-rows.mjs';
11
+ import { RELEASED_FILE, createReleasedStore } from './released-store.mjs';
11
12
  import { settleAwaitingUser } from './approval-wait.mjs';
12
13
  import { keepWorkerRow, normalizeWorkerRows } from './row-shape.mjs';
13
14
 
@@ -62,6 +63,9 @@ function rewriteIndexDocument(cur, mutator) {
62
63
 
63
64
  /** `file` may be null (no data dir): reads are empty and writes are no-ops. */
64
65
  export function createWorkerRowStore(file) {
66
+ // The release markers live in their own file beside the index, so a writer
67
+ // that rebuilds the index document never drops them.
68
+ const released = createReleasedStore(file ? join(dirname(file), RELEASED_FILE) : null);
65
69
  // Mtime-keyed parse cache. A single spawn calls refreshTagsFromSessions /
66
70
  // resolveTag / nextTag, which each re-read and re-parse this file; across a
67
71
  // parallel fanout that is O(spawns^2) synchronous reads of the same bytes.
@@ -148,18 +152,27 @@ export function createWorkerRowStore(file) {
148
152
  readAll,
149
153
  readSnapshot,
150
154
  readTombstones,
155
+ isReleased: released.isReleased,
156
+ markReleased: released.mark,
157
+ clearReleased: released.clear,
151
158
  write,
152
159
  /** Conditional field update: `mutator` runs now on the projection and again
153
160
  * on the locked document when persisted, so its condition is re-checked
154
161
  * against what is on disk. The one writer of `awaitingUser`. */
155
162
  update: (mutator) => queue.write(mutator, { rerun: true }),
156
163
  /** Resolves once every write so far is on disk. */
157
- flush: queue.flush,
164
+ flush: async () => {
165
+ await Promise.all([queue.flush(), released.flush()]);
166
+ },
158
167
  /** Exit path: persist what is still queued, synchronously. */
159
- flushSync: queue.flushSync,
160
- hasUnpersisted: queue.hasUnpersisted,
168
+ flushSync: () => {
169
+ const flushed = [queue.flushSync(), released.flushSync()];
170
+ return flushed.every(Boolean);
171
+ },
172
+ hasUnpersisted: () => queue.hasUnpersisted() || released.hasUnpersisted(),
161
173
  invalidate: () => {
162
174
  dirty = true;
175
+ released.invalidate();
163
176
  },
164
177
  };
165
178
  }
@@ -0,0 +1,58 @@
1
+ // worker-index/row-writes.mjs
2
+ // Row upserts (immediate or batched), removal, and the owner's release mark:
3
+ // every upsert projects the row into the tag maps (`bindTag`), tracks whether
4
+ // this process runs it, and brings its approval wait in step.
5
+ import { clean } from '../helpers.mjs';
6
+ import { applyWorkerRowUpsert, workerRowKey } from '../worker-rows.mjs';
7
+ import { isUnnotifiedRestartFailure } from './row-liveness.mjs';
8
+ import { normalizeWorkerRows, workerRowFromSession } from './row-shape.mjs';
9
+
10
+ export function createWorkerRowWrites({ file, store, batch, mgr, bindTag, settlement, awaitingUser }) {
11
+ function upsertWorkerRow(row, { defer = false } = {}) {
12
+ const normalized = normalizeWorkerRows({ workers: [row] })[0];
13
+ if (!normalized) return false;
14
+ const key = workerRowKey(normalized);
15
+ settlement.trackActiveRow(key, normalized);
16
+ bindTag(normalized);
17
+ if (defer) {
18
+ if (!file) return false;
19
+ awaitingUser.deferReconcile(normalized.sessionId);
20
+ return batch.queue((byKey) => applyWorkerRowUpsert(byKey, normalized));
21
+ }
22
+ store.write((byKey) => {
23
+ applyWorkerRowUpsert(byKey, normalized);
24
+ });
25
+ awaitingUser.reconcileAwaitingUser(normalized.sessionId);
26
+ return true;
27
+ }
28
+
29
+ // A session its owner closed keeps `released` on every row written for it,
30
+ // until a turn starts on it.
31
+ const rowFromSession = (session, fallbackTag = '', extra = {}) => {
32
+ const row = workerRowFromSession(session, fallbackTag, extra, (sessionId) => mgr.getSessionRuntime?.(sessionId));
33
+ return row && store.isReleased(row.sessionId) ? { ...row, released: true } : row;
34
+ };
35
+
36
+ /** Persist that the owner closed these sessions (survives a restart). */
37
+ function markReleased(sessionIds) {
38
+ store.markReleased(sessionIds.map(clean).filter(Boolean));
39
+ }
40
+
41
+ // A row whose owner is still owed its restart failure stays: closing the
42
+ // worker (a process exit closes every one) must not lose that result.
43
+ function removeWorkerRow({ tag = '', sessionId = '' } = {}) {
44
+ const targetTag = clean(tag);
45
+ const targetSessionId = clean(sessionId);
46
+ batch.flush();
47
+ store.write((byKey) => {
48
+ for (const [key, row] of [...byKey.entries()]) {
49
+ if (isUnnotifiedRestartFailure(row)) continue;
50
+ if ((targetSessionId && row.sessionId === targetSessionId) || (targetTag && row.tag === targetTag)) {
51
+ byKey.delete(key);
52
+ }
53
+ }
54
+ });
55
+ }
56
+
57
+ return { upsertWorkerRow, rowFromSession, markReleased, removeWorkerRow };
58
+ }