mixdog 1.3.4 → 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 (472) hide show
  1. package/LICENSES/oh-my-pi-MIT.txt +23 -0
  2. package/NOTICE.md +17 -2
  3. package/README.md +11 -0
  4. package/package.json +3 -11
  5. package/scripts/daemon-stub.mjs +1 -1
  6. package/scripts/embed-google-oauth-client.mjs +49 -0
  7. package/scripts/gate-local.mjs +4 -2
  8. package/scripts/lib/test-spawn-ledger.mjs +46 -1
  9. package/scripts/native-release-status.mjs +2 -2
  10. package/scripts/recall-history-cases.json +1 -1
  11. package/scripts/suite-health.mjs +10 -1
  12. package/scripts/test.mjs +12 -11
  13. package/src/agents/reviewer/AGENT.md +7 -11
  14. package/src/agents/reviewer/agent.json +1 -1
  15. package/src/defaults/shipped-history.json +25 -1
  16. package/src/defaults/skills/browser-use/SKILL.md +77 -17
  17. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  18. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  19. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  20. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  21. package/src/defaults/skills/computer-use/SKILL.md +33 -9
  22. package/src/defaults/skills/setup/SKILL.md +29 -2
  23. package/src/defaults/skills/setup/references/actions.md +117 -28
  24. package/src/defaults/skills/setup/references/surfaces.md +77 -35
  25. package/src/defaults/skills/setup-guide/SKILL.md +3 -3
  26. package/src/defaults/skills/visualize/SKILL.md +2 -1
  27. package/src/lib/keychain-cjs.cjs +359 -29
  28. package/src/lib/rules-builder.cjs +10 -8
  29. package/src/rules/agent/AGENT.md +6 -6
  30. package/src/rules/agent-mode/AGENT_MODE.md +10 -2
  31. package/src/rules/agent-mode/MIXY.md +12 -0
  32. package/src/rules/lead/LEAD.md +18 -20
  33. package/src/rules/shared/05-tool-calls.md +5 -6
  34. package/src/rules/shared/10-tool-workflow.md +2 -0
  35. package/src/rules/shared/60-verification.md +7 -5
  36. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  37. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
  38. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  39. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  40. package/src/runtime/agent/orchestrator/config.mjs +34 -0
  41. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  42. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
  43. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
  44. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  45. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +177 -73
  46. package/src/runtime/agent/orchestrator/mcp/client.mjs +25 -2
  47. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
  48. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
  49. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
  50. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
  51. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
  52. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
  53. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +230 -137
  54. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +64 -7
  55. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
  56. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  58. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  59. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  60. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +160 -69
  61. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  62. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
  63. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  64. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
  65. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
  66. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
  67. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
  68. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
  69. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +142 -104
  70. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  71. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
  73. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
  74. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  75. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -6
  76. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
  77. package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
  78. package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
  79. package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
  80. package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
  81. package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
  82. package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
  83. package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
  84. package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
  85. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
  86. package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
  87. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
  88. package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
  89. package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
  90. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
  91. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
  92. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
  93. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
  94. package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
  95. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
  97. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  98. package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
  99. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  100. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  101. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  102. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  103. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +19 -1
  104. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  107. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  109. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  110. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  111. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  112. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  113. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
  114. package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
  115. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  116. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  117. package/src/runtime/agent/orchestrator/providers/registry.mjs +43 -3
  118. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  119. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  120. package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
  121. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
  122. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  123. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  124. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  125. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  126. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
  127. package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
  128. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
  129. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  130. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  131. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  132. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
  133. package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
  134. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
  135. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
  136. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
  137. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
  138. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
  139. package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
  140. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
  141. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +148 -25
  142. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  143. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  144. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -0
  145. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +47 -9
  146. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -2
  147. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  148. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +14 -2
  149. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
  150. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
  151. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
  152. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +11 -2
  153. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
  154. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +51 -3
  155. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
  156. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -2
  157. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  158. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +14 -4
  159. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  160. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  161. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
  162. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  163. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +23 -5
  164. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
  165. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  166. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  167. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
  168. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
  170. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
  171. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  172. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  173. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
  174. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  175. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  176. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
  177. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
  178. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  179. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
  180. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  181. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
  182. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
  183. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  184. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
  185. package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
  186. package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
  187. package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
  188. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
  189. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  190. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
  191. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
  192. package/src/runtime/agent/orchestrator/session/routine-result.mjs +47 -11
  193. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
  194. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  195. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  196. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  197. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  198. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  199. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  200. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  201. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  202. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  203. package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
  204. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +133 -18
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
  206. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
  207. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
  208. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  209. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
  210. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  211. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  212. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  213. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
  214. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
  215. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +25 -2
  216. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  217. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  218. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  219. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  221. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  222. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  224. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
  225. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
  226. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  227. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  228. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  229. package/src/runtime/browser-bridge/client.mjs +73 -8
  230. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  231. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  232. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  233. package/src/runtime/channels/lib/config.mjs +6 -61
  234. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  235. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  236. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  237. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  238. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  239. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  240. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  241. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  242. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  243. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  244. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  245. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  246. package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
  247. package/src/runtime/channels/lib/scheduler.mjs +135 -154
  248. package/src/runtime/channels/lib/schedules-db.mjs +83 -11
  249. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  250. package/src/runtime/channels/lib/tool-dispatch.mjs +14 -2
  251. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  252. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  253. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  254. package/src/runtime/channels/lib/worker-main.mjs +19 -34
  255. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  256. package/src/runtime/computer-bridge/actions.mjs +9 -1
  257. package/src/runtime/computer-bridge/client.mjs +180 -8
  258. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  259. package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
  260. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  261. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  262. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  263. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  264. package/src/runtime/connectors/google-mcp.mjs +10 -12
  265. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  266. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  267. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  268. package/src/runtime/office/com/com-adapter.mjs +17 -1
  269. package/src/runtime/office/com/office-com-host.ps1 +51 -1
  270. package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
  271. package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
  272. package/src/runtime/office/pdf/document-preview.mjs +326 -8
  273. package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
  274. package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
  275. package/src/runtime/office/portable/portable-soffice.mjs +45 -5
  276. package/src/runtime/session-search/session-search-db.mjs +73 -9
  277. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  278. package/src/runtime/shared/abort-race.mjs +89 -0
  279. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  280. package/src/runtime/shared/agent-kind.mjs +4 -3
  281. package/src/runtime/shared/bot-hops.mjs +62 -2
  282. package/src/runtime/shared/bounded-download.mjs +8 -3
  283. package/src/runtime/shared/config.mjs +51 -35
  284. package/src/runtime/shared/connector-accounts.mjs +20 -10
  285. package/src/runtime/shared/connector-catalog.d.mts +33 -2
  286. package/src/runtime/shared/connector-catalog.mjs +166 -8
  287. package/src/runtime/shared/connector-triggers.mjs +22 -19
  288. package/src/runtime/shared/defaults-separation.mjs +2 -14
  289. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  290. package/src/runtime/shared/developer-options.mjs +32 -1
  291. package/src/runtime/shared/err-text.mjs +24 -15
  292. package/src/runtime/shared/file-permissions.d.mts +0 -8
  293. package/src/runtime/shared/file-permissions.mjs +0 -11
  294. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  295. package/src/runtime/shared/google-oauth-client.generated.json +4 -0
  296. package/src/runtime/shared/google-oauth-client.mjs +34 -9
  297. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  298. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  299. package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
  300. package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
  301. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
  302. package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
  303. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  304. package/src/runtime/shared/llm/well-formed.mjs +66 -0
  305. package/src/runtime/shared/mixy-presence.mjs +22 -0
  306. package/src/runtime/shared/orchestration.d.mts +2 -0
  307. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  308. package/src/runtime/shared/profile-config.cjs +1 -1
  309. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  310. package/src/runtime/shared/prompt-origin.mjs +21 -0
  311. package/src/runtime/shared/provider-accounts.mjs +231 -59
  312. package/src/runtime/shared/provider-api-key.mjs +19 -8
  313. package/src/runtime/shared/provider-display-name.mjs +29 -0
  314. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  315. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  316. package/src/runtime/shared/routine-trigger.mjs +52 -0
  317. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  318. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  319. package/src/runtime/shared/session-activity-signal.mjs +34 -1
  320. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  321. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  322. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  323. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  324. package/src/runtime/shared/tool-result-summary.mjs +1 -14
  325. package/src/runtime/shared/transcript-metadata.mjs +38 -0
  326. package/src/runtime/shared/user-data-guard.mjs +30 -2
  327. package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
  328. package/src/runtime/shared/worktrees/test-support.mjs +9 -4
  329. package/src/runtime/terminal-bridge/client.mjs +10 -1
  330. package/src/runtime/visualize-bridge/client.mjs +27 -8
  331. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  332. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  333. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  334. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  335. package/src/session-runtime/agent-home-delivery.mjs +486 -179
  336. package/src/session-runtime/agent-room-delivery.mjs +28 -1
  337. package/src/session-runtime/agent-task-sessions.mjs +561 -199
  338. package/src/session-runtime/boot/apis.mjs +9 -0
  339. package/src/session-runtime/boot/begin.mjs +3 -2
  340. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  341. package/src/session-runtime/boot/providers.mjs +3 -0
  342. package/src/session-runtime/boot/tools.mjs +8 -1
  343. package/src/session-runtime/bot-chain.mjs +32 -0
  344. package/src/session-runtime/bot-status.mjs +7 -4
  345. package/src/session-runtime/channel-config-api.mjs +63 -17
  346. package/src/session-runtime/config-lifecycle.mjs +6 -0
  347. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  348. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
  349. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
  350. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
  351. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
  352. package/src/session-runtime/internal-tool-executor.mjs +4 -0
  353. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  354. package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
  355. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  356. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  357. package/src/session-runtime/mcp-glue/server-catalog.mjs +61 -3
  358. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  359. package/src/session-runtime/mixy-heartbeat.mjs +927 -0
  360. package/src/session-runtime/model-route/route-tuning.mjs +10 -6
  361. package/src/session-runtime/notification-bus.mjs +31 -117
  362. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  363. package/src/session-runtime/notification-listeners.mjs +76 -0
  364. package/src/session-runtime/owned-automation-run.mjs +35 -13
  365. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  366. package/src/session-runtime/provider-auth/login.mjs +7 -0
  367. package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
  368. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  369. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  370. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  371. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  372. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  373. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  374. package/src/session-runtime/routine-home-turn.mjs +33 -6
  375. package/src/session-runtime/routine-owner.mjs +40 -9
  376. package/src/session-runtime/schedule-session-run.mjs +7 -3
  377. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  378. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
  379. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
  380. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  381. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  382. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  383. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  384. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  385. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  386. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  387. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  388. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  389. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  390. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  391. package/src/session-runtime/services/channel-admin.mjs +73 -31
  392. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  393. package/src/session-runtime/services/channel-worker.mjs +1 -1
  394. package/src/session-runtime/services/provider-admin.mjs +128 -25
  395. package/src/session-runtime/services/schedule-access.mjs +14 -0
  396. package/src/session-runtime/services/seeds.mjs +0 -28
  397. package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
  398. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  399. package/src/session-runtime/session-create/session-options.mjs +8 -4
  400. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  401. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  402. package/src/session-runtime/settings-system-api.mjs +28 -1
  403. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  404. package/src/session-runtime/setup-tool/executor.mjs +187 -29
  405. package/src/session-runtime/setup-tool/extended-actions.mjs +33 -2
  406. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  407. package/src/session-runtime/setup-tool/settings-contract.mjs +68 -6
  408. package/src/session-runtime/setup-tool/tool-defs.mjs +92 -6
  409. package/src/session-runtime/task-session-route.mjs +99 -0
  410. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  411. package/src/session-runtime/tool-policy/policy-stage.mjs +21 -4
  412. package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
  413. package/src/session-runtime/tool-surface.mjs +4 -0
  414. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  415. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
  416. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  417. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
  418. package/src/session-runtime/workspace/transitions.mjs +10 -2
  419. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  420. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  421. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  422. package/src/standalone/channel-transport.mjs +1 -1
  423. package/src/standalone/daemon-channels-loader.mjs +10 -8
  424. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  425. package/src/standalone/daemon-session-control/request.mjs +51 -0
  426. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  427. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  428. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  429. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  430. package/src/standalone/daemon-session-control.mjs +161 -157
  431. package/src/standalone/daemon.mjs +33 -2
  432. package/src/standalone/session-client.mjs +7 -3
  433. package/src/standalone/session-protocol.mjs +10 -0
  434. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
  435. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  436. package/src/standalone/session-service/quota-resume.mjs +3 -0
  437. package/src/standalone/session-service/retention/busy.mjs +65 -1
  438. package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
  439. package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
  440. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  441. package/src/standalone/session-service.mjs +13 -0
  442. package/src/standalone/session-tool-output.mjs +21 -10
  443. package/src/tui/app/model-options.mjs +4 -27
  444. package/src/tui/dist/index.mjs +81 -65
  445. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  446. package/src/tui/session/initial-state.mjs +3 -0
  447. package/src/tui/session/notice-surface.mjs +23 -1
  448. package/src/tui/session/queue-helpers.mjs +3 -42
  449. package/src/tui/session/session-api/integrations.mjs +1 -0
  450. package/src/tui/session/session-api/lifecycle.mjs +8 -0
  451. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  452. package/src/tui/session/session-api/routes-write.mjs +5 -1
  453. package/src/tui/session/session-api/routes.mjs +1 -0
  454. package/src/tui/session/session-api/settings.mjs +30 -2
  455. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  456. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  457. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  458. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  459. package/src/tui/session/session-flow/drain.mjs +118 -149
  460. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  461. package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
  462. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  463. package/src/tui/session/tool-approval-request.mjs +39 -0
  464. package/src/tui/session/tool-approval-settle.mjs +62 -0
  465. package/src/tui/session/tool-approval.mjs +69 -115
  466. package/src/tui/session/tui-steering-persist.mjs +8 -1
  467. package/src/tui/session/turn-stream.mjs +36 -3
  468. package/src/tui/session/turn.mjs +23 -2
  469. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  470. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  471. package/scripts/code-graph-description-contract.mjs +0 -188
  472. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -6,71 +6,33 @@
6
6
  // row-store — the file, its parse cache, the locked writer
7
7
  // mutation-batch — spawn-path writes coalesced onto one immediate
8
8
  // row-liveness — stale-active detection and idle settlement
9
+ // row-reads — scoped row and tag-tombstone reads
10
+ // row-writes — upserts, removal, the owner's release mark
11
+ // awaiting-user-sync — approval waits kept in step with the runtime
12
+ // restart-settlement — rows a process exit or restart ended
13
+ // disposal — drain, then release the registrations
9
14
  import { resolve } from 'node:path';
10
15
 
11
16
  import { WORKER_INDEX_FILE } from './tool-def.mjs';
12
- import { clean, positiveInt, registerExitFlush, rowMatchesContext } from './helpers.mjs';
13
- import { applyWorkerRowUpsert, recoverTagTombstoneOwner, workerRowKey } from './worker-rows.mjs';
14
- import {
15
- applyAwaitingUser,
16
- awaitingUserWouldChange,
17
- clearAwaitingUser,
18
- registerApprovalWaitWriter,
19
- } from './worker-index/approval-wait.mjs';
17
+ import { registerExitFlush, rowMatchesContext } from './helpers.mjs';
18
+ import { registerApprovalWaitWriter } from './worker-index/approval-wait.mjs';
19
+ import { createAwaitingUserSync } from './worker-index/awaiting-user-sync.mjs';
20
+ import { createIndexDisposal } from './worker-index/disposal.mjs';
20
21
  import { createMutationBatch } from './worker-index/mutation-batch.mjs';
21
- import {
22
- createRowLiveness,
23
- isActiveWorkerRow,
24
- isStaleApprovalWait,
25
- isUnnotifiedRestartFailure,
26
- PROCESS_RESTART_FAILURE,
27
- runtimeDied,
28
- } from './worker-index/row-liveness.mjs';
29
- import { normalizeWorkerRows, workerRowFromSession } from './worker-index/row-shape.mjs';
22
+ import { createRestartSettlement } from './worker-index/restart-settlement.mjs';
23
+ import { createWorkerRowReads } from './worker-index/row-reads.mjs';
30
24
  import { acquireWorkerRowStore } from './worker-index/row-store.mjs';
31
- import { findTagTombstone, tagTombstoneKey, tombstoneBlocksWork } from '../../../runtime/shared/agent-reap-state.mjs';
25
+ import { createWorkerRowWrites } from './worker-index/row-writes.mjs';
26
+ import { onSessionTurnStart } from '../../../runtime/shared/session-activity-signal.mjs';
32
27
 
33
28
  export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCwds }) {
34
29
  const file = dataDir ? resolve(dataDir, WORKER_INDEX_FILE) : null;
35
30
  // Shared with every other worker index of this process over the same file.
36
31
  const { store, release: releaseStore } = acquireWorkerRowStore(file);
37
- // Sessions whose deferred rows still wait in the batch; reconciled once the
38
- // batch lands in the store.
39
- const unreconciled = new Set();
40
- const batch = createMutationBatch(store.write, () => {
41
- const ids = [...unreconciled];
42
- unreconciled.clear();
43
- for (const id of ids) reconcileAwaitingUser(id);
44
- });
45
- const liveness = createRowLiveness({
46
- cfgMod,
47
- isSessionRunning: (sessionId) => mgr.isSessionTurnInFlight?.(sessionId) === true,
48
- });
49
- // Rows this process marked active; settled as failed on exit (their turn
50
- // dies with the process) so a crash of the host never leaves them
51
- // "running" forever.
52
- const activeWorkerKeys = new Set();
53
-
54
- function readWorkerRows(context = {}) {
55
- const { rows, tombstones: savedTombstones } = store.readSnapshot();
56
- if (rows.length === 0) return rows;
57
- const tombstones = new Map(recoverTombstoneOwners(savedTombstones).map((row) => [tagTombstoneKey(row), row]));
58
- return rows.filter(
59
- (row) => rowMatchesContext(row, context) && !tombstoneBlocksWork(row, findTagTombstone(row, tombstones))
60
- );
61
- }
62
-
63
- function readAllTagTombstones() {
64
- return recoverTombstoneOwners(store.readTombstones());
65
- }
66
-
67
- function recoverTombstoneOwners(rows) {
68
- if (!rows.some((row) => !clean(row.parentSessionId || row.ownerSessionId))) return rows;
69
- const sessions = typeof mgr.listSessions === 'function' ? mgr.listSessions({ includeClosed: true }) : [];
70
- // Resolve legacy ownership against all sessions, never just the caller's
71
- // scope: filtering first would conceal an ambiguous sibling owner.
72
- return rows.map((row) => recoverTagTombstoneOwner(row, sessions));
73
- }
32
+ const awaitingUser = createAwaitingUserSync(store, mgr);
33
+ const batch = createMutationBatch(store.write, awaitingUser.reconcileDeferred);
34
+ const settlement = createRestartSettlement({ store, cfgMod, mgr });
35
+ const { readWorkerRows, readAllTagTombstones } = createWorkerRowReads(store, mgr);
74
36
 
75
37
  // Every upsert also projects the row into the in-memory tag maps so tag
76
38
  // lookups never wait on a disk round-trip.
@@ -80,68 +42,20 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
80
42
  if (row.cwd) tagCwds.set(row.tag, row.cwd);
81
43
  }
82
44
 
83
- function upsertWorkerRow(row, { defer = false } = {}) {
84
- const normalized = normalizeWorkerRows({ workers: [row] })[0];
85
- if (!normalized) return false;
86
- const key = workerRowKey(normalized);
87
- if (isActiveWorkerRow(normalized)) activeWorkerKeys.add(key);
88
- else activeWorkerKeys.delete(key);
89
- bindTag(normalized);
90
- if (defer) {
91
- if (!file) return false;
92
- unreconciled.add(normalized.sessionId);
93
- return batch.queue((byKey) => applyWorkerRowUpsert(byKey, normalized));
94
- }
95
- store.write((byKey) => {
96
- applyWorkerRowUpsert(byKey, normalized);
97
- });
98
- reconcileAwaitingUser(normalized.sessionId);
99
- return true;
100
- }
101
-
102
- const rowFromSession = (session, fallbackTag = '', extra = {}) =>
103
- workerRowFromSession(session, fallbackTag, extra, (sessionId) => mgr.getSessionRuntime?.(sessionId));
104
-
105
- // A row whose owner is still owed its restart failure stays: closing the
106
- // worker (a process exit closes every one) must not lose that result.
107
- function removeWorkerRow({ tag = '', sessionId = '' } = {}) {
108
- const targetTag = clean(tag);
109
- const targetSessionId = clean(sessionId);
110
- batch.flush();
111
- store.write((byKey) => {
112
- for (const [key, row] of [...byKey.entries()]) {
113
- if (isUnnotifiedRestartFailure(row)) continue;
114
- if ((targetSessionId && row.sessionId === targetSessionId) || (targetTag && row.tag === targetTag)) {
115
- byKey.delete(key);
116
- }
117
- }
118
- });
119
- }
120
-
121
- /** Persist (or clear) a worker's approval wait as a field update fenced to
122
- * the session and its turn (`turnAt`, ms): a row whose turn started later is
123
- * left alone. Writes only when a row of that session exists and would
124
- * change, so a Lead's own approvals cost nothing; a row that is not in the
125
- * store yet takes the wait when it lands (reconcileAwaitingUser). */
126
- function setAwaitingUser(sessionId, awaitingUser, { turnAt = 0 } = {}) {
127
- const fence = {
128
- sessionId: clean(sessionId),
129
- awaitingUser: awaitingUser === 'approval' ? 'approval' : null,
130
- turnAt: Number(turnAt) || 0,
131
- };
132
- if (!fence.sessionId || !awaitingUserWouldChange(store.readAll(), fence)) return false;
133
- store.update((byKey) => applyAwaitingUser(byKey, fence));
134
- return true;
135
- }
45
+ const { upsertWorkerRow, rowFromSession, markReleased, removeWorkerRow } = createWorkerRowWrites({
46
+ file,
47
+ store,
48
+ batch,
49
+ mgr,
50
+ bindTag,
51
+ settlement,
52
+ awaitingUser,
53
+ });
136
54
 
137
- /** The runtime of a session this process runs is the authority on its
138
- * approval wait (the runtime-liveness counter behind `awaitingUser`): every
139
- * row it creates or refreshes takes that state, so a missed or stale
140
- * transition heals on the next write. No runtime here: not ours to judge. */
141
- function reconcileAwaitingUser(sessionId) {
142
- const runtime = mgr.getSessionRuntime?.(sessionId);
143
- if (runtime) setAwaitingUser(sessionId, runtime.awaitingUser, { turnAt: runtime.askStartedAt });
144
- }
55
+ // The one boundary every turn start passes through (user input, an answer,
56
+ // auto-resume, a send, a room/bot turn): the session is in use again, for
57
+ // good, whatever started the turn.
58
+ const stopTurnStartListener = onSessionTurnStart((sessionId) => store.clearReleased(sessionId));
145
59
 
146
60
  function refreshTagsFromIndex(context = {}) {
147
61
  const rows = readWorkerRows(context);
@@ -149,142 +63,27 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
149
63
  return rows;
150
64
  }
151
65
 
152
- function flushActiveWorkerRows() {
153
- if (!activeWorkerKeys.size) return;
154
- const keys = [...activeWorkerKeys];
155
- activeWorkerKeys.clear();
156
- const now = Date.now();
157
- store.write((byKey) => {
158
- for (const key of keys) {
159
- const current = byKey.get(key);
160
- if (!current || positiveInt(current.runtimePid) !== process.pid) continue;
161
- if (isActiveWorkerRow(current)) {
162
- byKey.set(key, liveness.failedRow(current, now, PROCESS_RESTART_FAILURE, true));
163
- }
164
- }
165
- });
166
- }
167
-
168
- // Startup recovery: stale active rows settle — as failed when another
169
- // process ran their turn (it is gone, or is the predecessor still shutting
170
- // down: either way the turn never finished), otherwise to idle — and an
171
- // approval wait left behind by a runtime that is gone (daemon restart) is
172
- // cleared. `deadOnly` (later sweeps) settles only rows whose runtime is
173
- // provably dead, never a live process's quiet turn.
174
- function recoverStaleWorkerRows({ deadOnly = false } = {}) {
175
- const now = Date.now();
176
- const rows = store.readAll();
177
- const isStale = deadOnly
178
- ? (row) => isActiveWorkerRow(row) && runtimeDied(row)
179
- : (row) => liveness.isStaleActive(row, now);
180
- const staleActive = rows.filter(isStale);
181
- const staleWaits = rows.some(isStaleApprovalWait);
182
- if (!staleActive.length && !staleWaits) return false;
183
- if (staleActive.length) {
184
- store.write((byKey) => {
185
- for (const row of staleActive) {
186
- const key = workerRowKey(row);
187
- const current = byKey.get(key);
188
- if (!current || !isStale(current)) continue;
189
- const ranElsewhere = positiveInt(current.runtimePid) && positiveInt(current.runtimePid) !== process.pid;
190
- byKey.set(
191
- key,
192
- ranElsewhere ? liveness.failedRow(current, now, PROCESS_RESTART_FAILURE) : liveness.idleRow(current, now)
193
- );
194
- }
195
- });
196
- }
197
- if (staleWaits) store.update((byKey) => clearAwaitingUser(byKey, isStaleApprovalWait));
198
- return true;
199
- }
200
-
201
- /** Rows whose turn a process restart ended and whose owner has not been told
202
- * yet — whoever settled the row (this process at startup, or the
203
- * predecessor's exit flush). Read-only: the caller enqueues the owner's
204
- * notification durably, THEN calls `markRestartNotified`, so a crash in
205
- * between retries (the notification's stable id makes the retry exactly-once). */
206
- function pendingRestartFailures() {
207
- return store.readAll().filter(isUnnotifiedRestartFailure);
208
- }
209
-
210
- /** Stamp these rows as told, once their notification is durably queued. */
211
- function markRestartNotified(rows) {
212
- const stamp = new Date().toISOString();
213
- store.write((byKey) => {
214
- for (const row of rows) {
215
- const key = workerRowKey(row);
216
- const current = byKey.get(key);
217
- if (!current || !isUnnotifiedRestartFailure(current)) continue;
218
- byKey.set(key, { ...current, restartNotified: stamp });
219
- }
220
- });
221
- }
222
-
223
66
  function flushWorkerIndexOnExit() {
224
67
  batch.flush();
225
- flushActiveWorkerRows();
68
+ settlement.flushActiveWorkerRows();
226
69
  // Writes are persisted by an async queue; the loop is gone at exit. This
227
70
  // is the best-effort last resort: a persist still running is left alone
228
71
  // (the graceful shutdown path drains before exit).
229
72
  store.flushSync();
230
73
  }
231
74
 
232
- recoverStaleWorkerRows();
75
+ settlement.recoverStaleWorkerRows();
233
76
  const unregisterExitFlush = registerExitFlush(flushWorkerIndexOnExit);
234
- const unregisterApprovalWaits = registerApprovalWaitWriter(file, setAwaitingUser);
235
- let disposed = false;
236
- let disposePromise = null;
77
+ const unregisterApprovalWaits = registerApprovalWaitWriter(file, awaitingUser.setAwaitingUser);
237
78
 
238
79
  function teardown() {
80
+ stopTurnStartListener();
239
81
  unregisterExitFlush();
240
82
  unregisterApprovalWaits();
241
83
  releaseStore();
242
84
  }
243
85
 
244
- async function drainThenTeardown() {
245
- batch.flush();
246
- await store.flush();
247
- teardown();
248
- }
249
-
250
- /** Persist queued rows, then release the exit registration. Active rows are
251
- * NOT settled: they are keyed by process pid, which every inline runtime in
252
- * the daemon shares, so settling here would idle other runtimes' workers.
253
- * When the sync flush cannot run (this process's async writer holds the
254
- * lock) the exit hook and store ref stay until the async drain settles. */
255
- function dispose() {
256
- if (disposed) return;
257
- disposed = true;
258
- let flushed = false;
259
- try {
260
- batch.flush();
261
- flushed = store.flushSync();
262
- } catch {}
263
- if (flushed) {
264
- teardown();
265
- return;
266
- }
267
- disposePromise = drainThenTeardown().catch(reopenAfterFailedDrain);
268
- }
269
-
270
- /** A failed drain tears nothing down; allow a later dispose to retry it. */
271
- function reopenAfterFailedDrain() {
272
- disposed = false;
273
- disposePromise = null;
274
- }
275
-
276
- /** Awaitable dispose: drain everything, then tear down. A failed drain
277
- * rejects and leaves the registrations in place. */
278
- function disposeAsync() {
279
- if (!disposePromise) {
280
- disposed = true;
281
- disposePromise = drainThenTeardown().catch((error) => {
282
- reopenAfterFailedDrain();
283
- throw error;
284
- });
285
- }
286
- return disposePromise;
287
- }
86
+ const { dispose, disposeAsync } = createIndexDisposal({ batch, store, teardown });
288
87
 
289
88
  return {
290
89
  dispose,
@@ -310,12 +109,13 @@ export function createWorkerIndex({ dataDir, cfgMod, mgr, tags, tagAgents, tagCw
310
109
  upsertWorkerSessionDeferred: (session, fallbackTag = '', extra = {}) =>
311
110
  upsertWorkerRow(rowFromSession(session, fallbackTag, extra), { defer: true }),
312
111
  removeWorkerRow,
313
- setAwaitingUser,
112
+ markReleased,
113
+ setAwaitingUser: awaitingUser.setAwaitingUser,
314
114
  refreshTagsFromIndex,
315
- flushActiveWorkerRows,
115
+ flushActiveWorkerRows: settlement.flushActiveWorkerRows,
316
116
  flushWorkerIndexOnExit,
317
- recoverStaleWorkerRows,
318
- pendingRestartFailures,
319
- markRestartNotified,
117
+ recoverStaleWorkerRows: settlement.recoverStaleWorkerRows,
118
+ pendingRestartFailures: settlement.pendingRestartFailures,
119
+ markRestartNotified: settlement.markRestartNotified,
320
120
  };
321
121
  }
@@ -129,6 +129,9 @@ export function applyWorkerRowUpsert(byKey, normalized) {
129
129
  merged[field] = prev[field];
130
130
  }
131
131
  }
132
+ // A whole-row write carries the session's release state: a row written
133
+ // without it (the agent was reused) is no longer released.
134
+ if (normalized.released !== true) delete merged.released;
132
135
  // `awaitingUser` is not decided here: the worker row store keeps the current
133
136
  // row's flag across every whole-row write and drops it once the row settles.
134
137
  byKey.set(key, {
@@ -11,6 +11,7 @@ import {
11
11
  listSchedules as dbListSchedules,
12
12
  getSchedule as dbGetSchedule,
13
13
  upsertSchedule,
14
+ renameSchedule as dbRenameSchedule,
14
15
  deleteSchedule as dbDeleteSchedule,
15
16
  setEnabled as dbSetEnabled,
16
17
  } from '../../runtime/channels/lib/schedules-db.mjs';
@@ -26,6 +27,7 @@ import { normalizeAutomationAttachments } from '../../runtime/shared/automation-
26
27
  import { assertRoutineOwner, routineOwnerProblem } from '../routine-owner.mjs';
27
28
  import { hasEnabledAutomation } from '../../runtime/shared/automation-presence.mjs';
28
29
  import { resolveScheduleTimezone, validateScheduleCron } from '../../runtime/shared/schedule-time.mjs';
30
+ import { scheduleNameTakenError, scheduleRenameRunningError } from '../../runtime/channels/lib/schedule-errors.mjs';
29
31
  import { pgClusterExists } from '../../runtime/memory/lib/pg/adapter.mjs';
30
32
  import { resolvePluginData } from '../../runtime/shared/plugin-paths.mjs';
31
33
  import { readHookPublicBase } from '../../runtime/channels/lib/webhook/relay-tunnel.mjs';
@@ -60,7 +62,6 @@ function normalizeChannelsConfig(raw = {}) {
60
62
  return {
61
63
  ...CHANNELS_DEFAULTS,
62
64
  ...stored,
63
- access: { ...CHANNELS_DEFAULTS.access, ...(stored.access || {}) },
64
65
  webhook: { ...CHANNELS_DEFAULTS.webhook, ...(stored.webhook || {}) },
65
66
  };
66
67
  }
@@ -187,7 +188,7 @@ function parseAtDatetime(at) {
187
188
 
188
189
  // Map the store's def shape onto the flat display shape every schedule reader
189
190
  // (channelSetup, renderChannelStatus, TUI pickers) consumes: `.time` renders
190
- // the cron or the one-shot datetime, `.route` the channel/session target.
191
+ // the cron or the one-shot datetime.
191
192
  function scheduleToDisplay(s, ownerProblem = '') {
192
193
  return {
193
194
  name: s.name,
@@ -200,7 +201,6 @@ function scheduleToDisplay(s, ownerProblem = '') {
200
201
  attachments: s.attachments || undefined,
201
202
  enabled: s.enabled !== false,
202
203
  instructions: s.prompt,
203
- route: 'session',
204
204
  // The bot it belongs to: each run is a turn in that bot's chat.
205
205
  owner: s.ownerAgentId || MIXY_AGENT_ID,
206
206
  // Why it is paused for its owner (routine-owner.mjs); absent when it runs.
@@ -250,7 +250,8 @@ function scheduleOwner(owner, existing) {
250
250
  return existing?.ownerAgentId || MIXY_AGENT_ID;
251
251
  }
252
252
 
253
- /** Each owner's problem (routine-owner.mjs), probed once per owner. */
253
+ /** Each owner's problem (routine-owner.mjs) for its stored rows, probed once
254
+ * per owner. */
254
255
  function ownerProblems() {
255
256
  const seen = new Map();
256
257
  return (ownerAgentId) => {
@@ -258,7 +259,7 @@ function ownerProblems() {
258
259
  if (!seen.has(owner))
259
260
  seen.set(
260
261
  owner,
261
- routineOwnerProblem(owner).catch(() => '')
262
+ routineOwnerProblem(owner, null, { stored: true }).catch(() => '')
262
263
  );
263
264
  return seen.get(owner);
264
265
  };
@@ -270,26 +271,62 @@ export async function listSchedules() {
270
271
  return Promise.all(rows.map(async (row) => scheduleToDisplay(row, await problemOf(row.ownerAgentId))));
271
272
  }
272
273
 
274
+ /**
275
+ * Run `step` (the move of schedule `name`'s row) with `name` reserved against
276
+ * runs in this process (the app's "Run now"). Refused when one is in flight.
277
+ */
278
+ export async function withScheduleRenameReserved(name, step) {
279
+ const { beginAutomationRename } = await import('../owned-automation-run.mjs');
280
+ const release = beginAutomationRename('schedule', name);
281
+ if (!release) throw scheduleRenameRunningError(name);
282
+ try {
283
+ return await step();
284
+ } finally {
285
+ release();
286
+ }
287
+ }
288
+
289
+ // Whether `next` fires when `existing` does: the same cron in the same zone (a
290
+ // stored row without a zone runs in the default one, as the scheduler arms
291
+ // it), or the same instant, whatever its spelling.
292
+ function sameTiming(existing, next) {
293
+ const instant = (value) => (value ? new Date(value).getTime() : null);
294
+ if ((existing.whenCron || null) !== next.whenCron) return false;
295
+ if (next.whenCron && resolveScheduleTimezone(existing.timezone) !== next.timezone) return false;
296
+ return instant(existing.whenAt) === instant(next.whenAt);
297
+ }
298
+
299
+ // The rename when no channels worker owns the scheduler: this process's runs
300
+ // are the only ones there are.
301
+ export const renameScheduleHere = (oldName, def, opts) =>
302
+ withScheduleRenameReserved(oldName, () => dbRenameSchedule(oldName, def, opts));
303
+
273
304
  // Register or update a schedule in the PG store. Recurring input maps `time`
274
305
  // (+ optional `days`) to a cron; one-shot input maps an `at` datetime; the two
275
306
  // are mutually exclusive (also enforced by the store's when_at/when_cron XOR).
276
307
  // Every schedule runs as a turn in its owner bot's chat; a bot that does not
277
308
  // exist (no representative bot yet, an archived bot) cannot own one.
278
- export async function saveSchedule({
279
- name,
280
- description = '',
281
- time,
282
- at,
283
- timezone,
284
- days,
285
- cwd,
286
- attachments,
287
- enabled,
288
- instructions,
289
- owner,
290
- overwrite = false,
291
- } = {}) {
309
+ export async function saveSchedule(
310
+ {
311
+ name,
312
+ description = '',
313
+ time,
314
+ at,
315
+ timezone,
316
+ days,
317
+ cwd,
318
+ attachments,
319
+ enabled,
320
+ instructions,
321
+ owner,
322
+ overwrite = false,
323
+ newName,
324
+ } = {},
325
+ { rename = renameScheduleHere } = {}
326
+ ) {
292
327
  const id = assertScheduleName(name);
328
+ const renameTo = newName != null && String(newName).trim() !== '' ? assertScheduleName(newName) : id;
329
+ const renaming = renameTo !== id;
293
330
  const body = String(instructions || '').trim();
294
331
  if (!body) throw new Error('schedule instructions are required');
295
332
  const hasTime = time != null && String(time).trim() !== '';
@@ -297,22 +334,21 @@ export async function saveSchedule({
297
334
  if (hasTime && hasAt) throw new Error('provide either `time` (recurring) or `at` (one-shot), not both');
298
335
  if (!hasTime && !hasAt) throw new Error('either `time` (recurring cron) or `at` (one-shot datetime) is required');
299
336
  const existing = await dbGetSchedule(id);
337
+ if (renaming && !existing) throw new Error(`schedule "${id}" does not exist`);
300
338
  if (overwrite !== true && existing) {
301
- throw new Error(`schedule "${id}" already exists`);
339
+ throw scheduleNameTakenError(id);
302
340
  }
303
341
  const ownerAgentId = scheduleOwner(owner, existing);
304
342
  await assertRoutineOwner(ownerAgentId);
305
343
  const whenCron = hasTime ? validateScheduleCron(foldDaysIntoCron(normalizeCron(time), days)) : null;
306
344
  const whenAt = hasAt ? parseAtDatetime(at) : null;
307
345
  const scheduleTimezone = hasTime ? resolveScheduleTimezone(timezone) : null;
308
- const saved = await upsertSchedule({
309
- name: id,
346
+ const def = {
347
+ name: renameTo,
310
348
  description: String(description || '').trim(),
311
349
  whenCron,
312
350
  whenAt,
313
351
  timezone: scheduleTimezone,
314
- target: 'session',
315
- channelId: null,
316
352
  cwd: cwd ? String(cwd).trim() : null,
317
353
  attachments: normalizeAutomationAttachments(attachments),
318
354
  delivery: 'app',
@@ -320,7 +356,16 @@ export async function saveSchedule({
320
356
  enabled: enabled !== false,
321
357
  nextFireAt: whenAt,
322
358
  ownerAgentId,
323
- });
359
+ };
360
+ let saved;
361
+ if (renaming) {
362
+ if (await dbGetSchedule(renameTo)) throw scheduleNameTakenError(renameTo);
363
+ const timingChanged = !sameTiming(existing, { whenCron, whenAt, timezone: scheduleTimezone });
364
+ saved = await rename(id, def, { timingChanged });
365
+ if (!saved) throw new Error(`schedule "${id}" does not exist`);
366
+ } else {
367
+ saved = await upsertSchedule(def);
368
+ }
324
369
  automationProbe.invalidate();
325
370
  return scheduleToDisplay(saved);
326
371
  }
@@ -360,7 +405,6 @@ async function listWebhooks() {
360
405
  secretSet: ep.secretSet === true,
361
406
  secret: undefined,
362
407
  instructions: ep.instructions,
363
- route: 'session',
364
408
  // The bot it belongs to: each run is a turn in that bot's chat.
365
409
  owner: ep.ownerAgentId || MIXY_AGENT_ID,
366
410
  ...(problems[index] ? { ownerProblem: problems[index] } : {}),
@@ -413,7 +457,6 @@ export async function saveWebhook({
413
457
  name: id,
414
458
  description: String(description || '').trim(),
415
459
  parser: nextParser,
416
- channelId: null,
417
460
  cwd: cwd ? String(cwd).trim() : null,
418
461
  attachments: normalizeAutomationAttachments(attachments),
419
462
  delivery: 'app',
@@ -530,9 +573,8 @@ export async function testWebhook(name) {
530
573
  }
531
574
 
532
575
  // Automation presence: any enabled schedule or webhook endpoint. Drives the
533
- // worker boot decision independently of the messaging channels — schedules
534
- // and webhooks run sessions, so they must not require Discord/Telegram
535
- // tokens or an explicit remote toggle.
576
+ // worker boot decision — schedules and webhooks run sessions, so they must
577
+ // not require an explicit remote toggle.
536
578
  async function checkActiveAutomation() {
537
579
  const { schedules, webhooks } = await readAutomationRows();
538
580
  return hasEnabledAutomation({ schedules, webhooks });
@@ -555,7 +597,7 @@ async function readAutomationRows() {
555
597
  // at once; writes from other processes are picked up after ttlMs. A failed
556
598
  // check (e.g. PG still booting) answers false to its callers but is never
557
599
  // reused, so the next runtime checks again.
558
- export const AUTOMATION_PROBE_TTL_MS = 60_000;
600
+ const AUTOMATION_PROBE_TTL_MS = 60_000;
559
601
 
560
602
  export function createAutomationProbe(check, { ttlMs = AUTOMATION_PROBE_TTL_MS, now = Date.now } = {}) {
561
603
  let pending = null;
@@ -1,4 +1,5 @@
1
1
  import { channelNotificationModelContent } from '../../runtime/shared/channel-notification-routing.mjs';
2
+ import { PROMPT_ORIGIN_CHANNEL } from '../../runtime/agent/orchestrator/session/manager/pending-message-entry.mjs';
2
3
 
3
4
  /** The one inbound channel notification method. Exported so every consumer
4
5
  * (daemon router, session runtime) matches the same wire name. */
@@ -21,8 +22,9 @@ export function createChannelSessionRouter({ getSessionService, getSessionId, lo
21
22
  prompt: content,
22
23
  // A channel notification (webhook event rules carry fenced external
23
24
  // values) is queued as a task notification, never as typed input, so
24
- // nothing inside it selects a skill.
25
- options: { source: 'channel', mode: 'task-notification' },
25
+ // nothing inside it selects a skill. Its provenance (`origin`) says
26
+ // it is real external activity, which the mode alone does not.
27
+ options: { source: 'channel', mode: 'task-notification', origin: PROMPT_ORIGIN_CHANNEL },
26
28
  })
27
29
  ).catch((error) => {
28
30
  log(`channel session delivery failed session=${sessionId}: ${error?.message || error}`);
@@ -18,7 +18,7 @@ import { daemonEnv, spawnDaemonCandidate } from './channel-worker/daemon-spawn.m
18
18
 
19
19
  export { pruneStaleChannelClientHeartbeats };
20
20
 
21
- const CHANNEL_TOOLS = new Set(['activate_channel_bridge', 'reload_config']);
21
+ const CHANNEL_TOOLS = new Set(['activate_channel_bridge', 'reload_config', 'rename_schedule']);
22
22
  const CALL_RETRIES = 3;
23
23
 
24
24
  function logLine(path, line) {