mixdog 1.4.0 → 1.4.2

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 (493) hide show
  1. package/package.json +3 -2
  2. package/scripts/build-shipped-history.mjs +115 -33
  3. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  4. package/scripts/gate-local.mjs +183 -63
  5. package/scripts/latest-guard.mjs +21 -9
  6. package/scripts/lib/gate-scheduler.mjs +138 -32
  7. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +91 -66
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +124 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/lib/test-failure-records.mjs +14 -1
  14. package/scripts/lib/test-failure-summary.mjs +16 -4
  15. package/scripts/lib/test-spawn-ledger.mjs +12 -3
  16. package/scripts/post-release-check.mjs +1 -6
  17. package/scripts/pptx-kit-index.mjs +17 -5
  18. package/scripts/suite-health.mjs +115 -24
  19. package/scripts/test-data-dir.mjs +10 -7
  20. package/scripts/test.mjs +9 -14
  21. package/src/agents/advisor/AGENT.md +4 -4
  22. package/src/agents/advisor/agent.json +1 -1
  23. package/src/agents/explore/AGENT.md +22 -0
  24. package/src/agents/explore/agent.json +6 -0
  25. package/src/app.mjs +4 -0
  26. package/src/cli.mjs +7 -0
  27. package/src/defaults/agents.json +7 -0
  28. package/src/defaults/shipped-history.json +23 -2
  29. package/src/defaults/skills/browser-use/SKILL.md +10 -5
  30. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  31. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  32. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  33. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  34. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  35. package/src/defaults/skills/computer-use/SKILL.md +16 -4
  36. package/src/defaults/skills/goal-management/SKILL.md +1 -1
  37. package/src/defaults/skills/setup/references/actions.md +12 -6
  38. package/src/defaults/skills/setup/references/surfaces.md +2 -2
  39. package/src/defaults/skills/setup-guide/SKILL.md +5 -2
  40. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  41. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  42. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  43. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  44. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  45. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  46. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  47. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  48. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  49. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  50. package/src/defaults/skills/visualize/SKILL.md +6 -2
  51. package/src/lib/rules-builder.cjs +35 -42
  52. package/src/output-styles/common.md +2 -2
  53. package/src/output-styles/simple.md +1 -1
  54. package/src/rules/agent/AGENT.md +5 -4
  55. package/src/rules/lead/LEAD.md +12 -7
  56. package/src/rules/shared/10-tool-workflow.md +3 -1
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/45-destructive.md +0 -2
  60. package/src/rules/shared/50-execution.md +2 -0
  61. package/src/rules/shared/60-verification.md +10 -9
  62. package/src/rules/shared/70-delivery.md +8 -9
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
  65. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
  66. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  69. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  70. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
  71. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
  72. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
  79. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
  80. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
  81. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
  82. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
  84. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  85. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  86. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  90. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
  91. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
  92. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  93. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  94. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  95. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  97. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
  99. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  100. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  101. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  102. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  103. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  104. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  105. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  106. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  107. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
  108. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  109. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  110. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  113. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  114. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  115. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  116. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  117. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  128. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  129. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  130. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  131. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  132. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  133. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
  135. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  136. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
  137. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  138. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  139. package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
  140. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  141. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  142. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  143. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
  145. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  146. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
  147. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
  148. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  149. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
  150. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
  151. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  152. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  153. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  154. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  155. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  156. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
  157. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  158. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  159. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  160. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  161. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
  162. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  163. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
  164. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
  165. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  166. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  167. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
  168. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  169. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
  170. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
  171. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
  172. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  174. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
  175. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
  176. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
  177. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
  178. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  179. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
  180. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  181. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
  182. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  183. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  184. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
  185. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
  186. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
  187. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
  188. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
  189. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
  190. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  191. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
  192. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
  193. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  194. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  195. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
  196. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  197. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
  198. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
  199. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  200. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
  201. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
  202. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
  203. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  204. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
  209. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  210. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
  211. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  212. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
  213. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  214. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  215. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  217. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
  218. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
  219. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
  221. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
  222. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  223. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  224. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  225. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  226. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  227. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  228. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  229. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  231. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
  232. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  233. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  234. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  235. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  236. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  237. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  238. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  239. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
  240. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  241. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  243. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
  244. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
  245. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  246. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  248. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  249. package/src/runtime/channels/lib/whisper-port.mjs +29 -11
  250. package/src/runtime/channels/lib/whisper-server.mjs +10 -1
  251. package/src/runtime/computer-bridge/action-schema.mjs +2 -2
  252. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  253. package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
  254. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  255. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  256. package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
  257. package/src/runtime/connectors/gmail-app-password.mjs +3 -3
  258. package/src/runtime/explore/explorer.mjs +93 -0
  259. package/src/runtime/explore/tool-defs.mjs +35 -0
  260. package/src/runtime/explore/tool.mjs +123 -0
  261. package/src/runtime/local-provider/server-process.mjs +2 -1
  262. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  263. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  264. package/src/runtime/memory/index.mjs +4 -0
  265. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  266. package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
  267. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  268. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  269. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  270. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  271. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  272. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  273. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  274. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  275. package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
  276. package/src/runtime/office/quality/design-review.mjs +1 -5
  277. package/src/runtime/office/quality/document-brief.mjs +1 -5
  278. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  279. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  280. package/src/runtime/shared/agent-route-config.mjs +17 -2
  281. package/src/runtime/shared/atomic-file.mjs +103 -2
  282. package/src/runtime/shared/background-tasks.mjs +15 -6
  283. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  284. package/src/runtime/shared/connector-accounts.mjs +5 -5
  285. package/src/runtime/shared/connector-catalog.d.mts +11 -4
  286. package/src/runtime/shared/connector-catalog.mjs +60 -52
  287. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  288. package/src/runtime/shared/defaults-separation.mjs +1 -4
  289. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  290. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  291. package/src/runtime/shared/file-has-data.mjs +26 -2
  292. package/src/runtime/shared/file-lock.mjs +13 -15
  293. package/src/runtime/shared/git-launch.d.mts +9 -0
  294. package/src/runtime/shared/git-launch.mjs +213 -0
  295. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  296. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  297. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  298. package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
  299. package/src/runtime/shared/llm/cost.mjs +11 -2
  300. package/src/runtime/shared/llm/http-agent.mjs +313 -29
  301. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  302. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  303. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  304. package/src/runtime/shared/llm/system-proxy.mjs +452 -0
  305. package/src/runtime/shared/loopback-listener.mjs +25 -2
  306. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  307. package/src/runtime/shared/model-route-chain.mjs +22 -4
  308. package/src/runtime/shared/open-url.mjs +10 -0
  309. package/src/runtime/shared/provider-accounts.mjs +52 -2
  310. package/src/runtime/shared/session-activity-signal.mjs +14 -0
  311. package/src/runtime/shared/session-scratch.mjs +37 -0
  312. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  313. package/src/runtime/shared/staged-update.mjs +47 -2
  314. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  315. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  316. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  317. package/src/runtime/shared/tool-surface.mjs +113 -36
  318. package/src/runtime/shared/tool-work-units.mjs +6 -0
  319. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  320. package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
  321. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  322. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  323. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  324. package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
  325. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  326. package/src/runtime/shared/worktrees/git.mjs +72 -0
  327. package/src/runtime/shared/worktrees/manager.mjs +285 -168
  328. package/src/runtime/shared/worktrees/test-support.mjs +6 -10
  329. package/src/runtime/tidy/install.mjs +95 -15
  330. package/src/runtime/tidy/languages.mjs +17 -15
  331. package/src/runtime/tidy/process.mjs +7 -4
  332. package/src/runtime/tidy/resolve.mjs +19 -16
  333. package/src/runtime/tidy/runners/biome.mjs +3 -3
  334. package/src/runtime/tidy/tool.mjs +1 -1
  335. package/src/runtime/tidy/worktree.mjs +10 -6
  336. package/src/runtime/visualize-bridge/client.mjs +6 -1
  337. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  338. package/src/runtime/web-search/index.mjs +1 -1
  339. package/src/session-runtime/agent-home-delivery.mjs +41 -0
  340. package/src/session-runtime/agent-task-sessions.mjs +458 -312
  341. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  342. package/src/session-runtime/boot/tools.mjs +7 -1
  343. package/src/session-runtime/bot-status.mjs +107 -101
  344. package/src/session-runtime/bot-target.mjs +38 -0
  345. package/src/session-runtime/channel-config-api.mjs +6 -1
  346. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  347. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  348. package/src/session-runtime/conversation-import/discovery.mjs +401 -36
  349. package/src/session-runtime/conversation-import/service.mjs +35 -8
  350. package/src/session-runtime/handoff-attachments.mjs +82 -31
  351. package/src/session-runtime/held-requests.mjs +3 -1
  352. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
  353. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
  354. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
  355. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  356. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  357. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
  358. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  359. package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
  360. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
  361. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  362. package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
  363. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  364. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  365. package/src/session-runtime/model-route/set-route.mjs +11 -2
  366. package/src/session-runtime/provider-auth/login.mjs +2 -2
  367. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  368. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  369. package/src/session-runtime/provider-models.mjs +4 -2
  370. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  371. package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
  372. package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
  373. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  374. package/src/session-runtime/resource-recall-api.mjs +6 -1
  375. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  376. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  377. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  378. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  379. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  380. package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
  381. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  382. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
  383. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
  384. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  385. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  386. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  387. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  388. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  389. package/src/session-runtime/services/plugin-admin.mjs +10 -6
  390. package/src/session-runtime/services/provider-admin.mjs +283 -11
  391. package/src/session-runtime/session-turn-api.mjs +2 -0
  392. package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
  393. package/src/session-runtime/settings-system-api.mjs +1 -1
  394. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  395. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  396. package/src/session-runtime/setup-tool/executor.mjs +6 -2
  397. package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
  398. package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
  399. package/src/session-runtime/turn/agent-ops.mjs +23 -0
  400. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
  401. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  402. package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
  403. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  404. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  405. package/src/session-runtime/workspace/session-view.mjs +149 -0
  406. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  407. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  408. package/src/session-runtime/workspace/transitions.mjs +108 -1041
  409. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  410. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  411. package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
  412. package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
  413. package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
  414. package/src/standalone/daemon-desktop-runtime.mjs +2 -0
  415. package/src/standalone/daemon-session-control.mjs +169 -138
  416. package/src/standalone/daemon.mjs +7 -0
  417. package/src/standalone/desktop-service-registry.mjs +9 -0
  418. package/src/standalone/local-session-runtime.mjs +5 -1
  419. package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
  420. package/src/standalone/session-client.mjs +5 -1
  421. package/src/standalone/session-frame-stream.mjs +83 -11
  422. package/src/standalone/session-protocol.mjs +4 -0
  423. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  424. package/src/standalone/session-service/agent-tree.mjs +45 -9
  425. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  426. package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
  427. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  428. package/src/standalone/session-service/stored-reader.mjs +127 -40
  429. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  430. package/src/tui/App.jsx +154 -164
  431. package/src/tui/app/app-view/floating-panel.jsx +10 -4
  432. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  433. package/src/tui/app/clipboard.mjs +21 -10
  434. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  435. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  436. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  437. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  438. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  439. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  440. package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
  441. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  442. package/src/tui/app/provider-setup-picker.mjs +29 -18
  443. package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
  444. package/src/tui/app/slash-commands.mjs +1 -0
  445. package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
  446. package/src/tui/app/slash-dispatch.mjs +1 -1
  447. package/src/tui/app/use-btw-panel.mjs +29 -0
  448. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  449. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  450. package/src/tui/app/use-mouse-input.mjs +11 -0
  451. package/src/tui/app/use-onboarding-start.mjs +8 -3
  452. package/src/tui/app/use-panel-transition.mjs +10 -1
  453. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  454. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  455. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  456. package/src/tui/app/use-prompt-queue-history.mjs +3 -2
  457. package/src/tui/app/use-selection-focus.mjs +11 -2
  458. package/src/tui/app/use-selection-geometry.mjs +18 -9
  459. package/src/tui/app/use-selection-paint.mjs +4 -4
  460. package/src/tui/app/use-selection-stitch.mjs +3 -3
  461. package/src/tui/app/use-slash-palette.mjs +62 -0
  462. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  463. package/src/tui/app/use-transcript-activity.mjs +47 -32
  464. package/src/tui/app/use-transcript-follow.mjs +12 -4
  465. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  466. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  467. package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
  468. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  469. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  470. package/src/tui/app/use-transcript-window.mjs +21 -11
  471. package/src/tui/app/use-tui-ready.mjs +18 -0
  472. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  473. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  474. package/src/tui/components/Picker.jsx +27 -3
  475. package/src/tui/components/QuestionPanel.jsx +13 -4
  476. package/src/tui/components/SignInUrl.jsx +68 -0
  477. package/src/tui/components/TextEntryPanel.jsx +76 -46
  478. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  479. package/src/tui/dist/index.mjs +1963 -1361
  480. package/src/tui/session/goal-turn-state.mjs +6 -2
  481. package/src/tui/session/session-api/controls.mjs +4 -0
  482. package/src/tui/session/session-api/extensions.mjs +8 -0
  483. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  484. package/src/tui/session/session-api/intake.mjs +2 -0
  485. package/src/tui/session/session-api/integrations.mjs +2 -2
  486. package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
  487. package/src/tui/session/session-api/settings.mjs +2 -2
  488. package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
  489. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  490. package/src/tui/session/transcript-spill.mjs +92 -4
  491. package/src/tui/session/transcript-store.mjs +2 -0
  492. package/src/ui/statusline-agents.mjs +1 -3
  493. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
@@ -5,55 +5,22 @@
5
5
  */
6
6
 
7
7
  import { clean } from '../runtime/shared/clean.mjs';
8
-
9
- const lower = (value) => clean(value).toLowerCase();
10
-
11
- // A pinned model named by its catalog display name ("GPT-6.1-Sol") is not a
12
- // wire id. Canonicalize it only on an unambiguous EXACT match: the id itself,
13
- // or a display name / label, case-insensitively, within the requested provider
14
- // (or across providers when none is given and exactly one row matches).
15
- // Anything else — no match, several matches, an empty or partial catalog —
16
- // returns the args unchanged: the catalog never refuses a model and never
17
- // substitutes a near one.
18
- export function canonicalizePinnedModel(args, rows) {
19
- const model = clean(args?.model);
20
- if (!model || !Array.isArray(rows)) return args;
21
- const provider = lower(args.provider);
22
- const pool = rows.filter((row) => row && (!provider || lower(row.provider) === provider));
23
- const wanted = model.toLowerCase();
24
- const exactId = pool.filter((row) => row.id === model);
25
- // A partial catalog may lack the real id a display name collides with, so
26
- // only an exact id can pass there; aliases wait for a complete catalog.
27
- const partial = pool.some((row) => row.catalogPartial === true);
28
- const hits = exactId.length
29
- ? exactId
30
- : partial
31
- ? []
32
- : pool.filter((row) => lower(row.id) === wanted || lower(row.display) === wanted || lower(row.label) === wanted);
33
- const distinct = [...new Map(hits.map((row) => [`${row.provider}\n${row.id}`, row])).values()];
34
- if (distinct.length !== 1) return args;
35
- const [hit] = distinct;
36
- if (hit.id === model && hit.provider === args.provider) return args;
37
- return { ...args, provider: hit.provider, model: hit.id };
38
- }
8
+ import { resolveRequestedModel } from './services/agent-tool/model-select.mjs';
39
9
 
40
10
  // `listProviderModels` is this runtime's provider catalog. The agent control
41
11
  // behind `executeAgentControl` (the daemon's canonical agent) has none, so a
42
- // display-name model is canonicalized here before it is forwarded. Only the
43
- // cached/quick catalog is read, so a spawn never waits on provider listings.
12
+ // pinned model is resolved here, by the same rule the in-process agent tool
13
+ // applies (exact id, display name, then every query word; ambiguous or
14
+ // unknown names fail with candidates), and forwarded as the exact route.
44
15
  export function createRoutedAgentTool({ rt, agentTool, executeAgentControl = null, listProviderModels = null }) {
45
16
  const routedAgentTool = {
46
17
  ...agentTool,
47
18
  async execute(args, context = {}) {
48
19
  if (typeof executeAgentControl !== 'function') return agentTool.execute(args, context);
49
- let routedArgs = args;
50
- if (typeof listProviderModels === 'function' && clean(args?.model) && (clean(args.type) || 'spawn') === 'spawn') {
51
- try {
52
- routedArgs = canonicalizePinnedModel(args, await listProviderModels({ quick: true }));
53
- } catch {
54
- routedArgs = args;
55
- }
56
- }
20
+ const routedArgs =
21
+ typeof listProviderModels === 'function' && clean(args?.model) && (clean(args.type) || 'spawn') === 'spawn'
22
+ ? await resolveRequestedModel(args, listProviderModels)
23
+ : args;
57
24
  return executeAgentControl(routedArgs, context);
58
25
  },
59
26
  closeAll(reason, scope = {}) {
@@ -22,7 +22,11 @@ import { TOOL_DEFS as OFFICE_TOOL_DEFS } from '../../runtime/office/tool-defs.mj
22
22
  import { TOOL_DEFS as MEDIA_TOOL_DEFS } from '../../runtime/media/tool-defs.mjs';
23
23
  import { TOOL_DEFS as TIDY_TOOL_DEFS } from '../../runtime/tidy/tool-defs.mjs';
24
24
  import { TOOL_DEFS as VISUALIZE_BRIDGE_TOOL_DEFS } from '../../runtime/visualize-bridge/tool-defs.mjs';
25
- import { ASK_USER_TOOL_DEFS } from '../../runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs';
25
+ import { TOOL_DEFS as EXPLORE_TOOL_DEFS } from '../../runtime/explore/tool-defs.mjs';
26
+ import {
27
+ ASK_USER_TOOL_DEFS,
28
+ HANDOFF_USER_TOOL_DEFS,
29
+ } from '../../runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs';
26
30
  import { REACTION_TOOL_DEFS } from '../../runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs';
27
31
  import { SETUP_TOOL_DEFS } from '../setup-tool/tool-defs.mjs';
28
32
  import { createSetupToolExecutor } from '../setup-tool/executor.mjs';
@@ -169,8 +173,10 @@ function wireToolSurface(boot) {
169
173
  mediaToolDefs: MEDIA_TOOL_DEFS,
170
174
  tidyToolDefs: TIDY_TOOL_DEFS,
171
175
  visualizeToolDefs: VISUALIZE_BRIDGE_TOOL_DEFS,
176
+ exploreToolDefs: EXPLORE_TOOL_DEFS,
172
177
  setupToolDefs: SETUP_TOOL_DEFS,
173
178
  askUserToolDefs: ASK_USER_TOOL_DEFS,
179
+ handoffUserToolDefs: HANDOFF_USER_TOOL_DEFS,
174
180
  reactionToolDefs: REACTION_TOOL_DEFS,
175
181
  goalTools: goalRuntime.tools,
176
182
  agentTools: agentTool.tools,
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * `session bots`: the state of the user's bots, read on demand (never injected
3
3
  * into a turn). One line per bot: its home chat (`sess_home_<id>`), the last
4
- * activity there and its latest line, whether it works now (its chat, or a
5
- * task session it runs), approvals waiting on the user, its routines and what
4
+ * activity there and its latest line, whether it works now (its chat, or work
5
+ * it sent running in a task session; a turn the user typed there is the
6
+ * user's), approvals waiting on the user, its routines and what
6
7
  * needs attention. With one bot (`session_id`: its id or chat id): its
7
8
  * routines, its held requests and its recent sessions.
8
9
  *
@@ -143,7 +144,7 @@ function span(ms) {
143
144
  const ago = (at, now) => `${span(now - at)} ago`;
144
145
  const until = (at, now) => (at <= now ? 'due now' : `in ${span(at - now)}`);
145
146
 
146
- async function defaultListBots() {
147
+ export async function defaultListBots() {
147
148
  const [{ workflowHelpers }, { getPluginData, loadConfig }, { isAgentDisabled, isContactAgentId }] = await Promise.all(
148
149
  [
149
150
  import('./boot/shared.mjs'),
@@ -203,6 +204,109 @@ function routineDetail(routine, now) {
203
204
  return cut(`${routine.kind} ${quotedText(routine.name, 64)}: ${parts.join(', ')}`, 240);
204
205
  }
205
206
 
207
+ /** Everything known about one bot, from the gathered state. */
208
+ function botState(bot, ctx) {
209
+ const homeId = agentHomeSessionId(bot.id);
210
+ const owned = ctx.owned.get(bot.id) || [];
211
+ const home = ctx.rows.get(homeId) || null;
212
+ // Work this bot sent that is running now: a session working with the bot's
213
+ // send in flight (`handedBy`, bot-owned-work.mjs). A turn the user typed
214
+ // in the bot's task session is the user's, not the bot working.
215
+ const sentWork = (row) => isWorking(row) && row.handedBy?.includes(bot.id);
216
+ // Running task sessions: a turn whose report is still owed, or the bot's
217
+ // work running now.
218
+ const tasks = new Map();
219
+ const addTask = (id, title, at) => {
220
+ const known = tasks.get(id);
221
+ if (!known) tasks.set(id, { id, title, at });
222
+ else if (at && (!known.at || at < known.at)) known.at = at;
223
+ };
224
+ for (const watch of ctx.watches) {
225
+ if (watch.agentId !== bot.id || watch.target === 'session' || !watch.taskSessionId) continue;
226
+ addTask(watch.taskSessionId, watch.title, Number(watch.at) || 0);
227
+ }
228
+ for (const row of owned) {
229
+ if (row.id === homeId || roomMemberOfSession(row.id) || !sentWork(row)) continue;
230
+ addTask(row.id, row.title, Number(row.createdAt) || 0);
231
+ }
232
+ const running = [...tasks.values()].sort((left, right) => left.at - right.at || (left.id < right.id ? -1 : 1));
233
+ const held = ctx.held.filter((entry) => entry.agentId === bot.id);
234
+ const approvals = held.length + [homeId, ...running.map((task) => task.id)].filter(ctx.awaitingApproval).length;
235
+ const routines = ctx.routines.rows
236
+ .filter((routine) => (routine.owner || MIXY_AGENT_ID) === bot.id)
237
+ .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
238
+ const flags = [];
239
+ if (approvals) flags.push(`${plural(approvals, 'approval')} waiting`);
240
+ for (const routine of routines) {
241
+ const trouble = routineTrouble(routine);
242
+ if (trouble.length) flags.push(`${quotedText(routine.name, 20)} ${trouble.join(', ')}`);
243
+ }
244
+ if (bot.disabled) flags.push('disabled');
245
+ return {
246
+ bot,
247
+ homeId,
248
+ home,
249
+ owned,
250
+ running,
251
+ held,
252
+ approvals,
253
+ routines,
254
+ flags,
255
+ working: isWorking(home) || running.some((task) => sentWork(ctx.rows.get(task.id))),
256
+ lastAt: activityOf(home),
257
+ };
258
+ }
259
+
260
+ function botLine(state, now) {
261
+ const { bot } = state;
262
+ const parts = [`${quotedText(bot.name, 40)} (${bot.id})`, `chat ${state.homeId}`];
263
+ if (bot.self) parts.push('you');
264
+ parts.push(state.working ? 'working' : 'idle');
265
+ if (state.flags.length) parts.push(`attention: ${state.flags.join('; ')}`);
266
+ parts.push(state.lastAt ? `last ${ago(state.lastAt, now)}` : 'no chat yet');
267
+ if (state.running.length) {
268
+ const [first] = state.running;
269
+ const more = state.running.length > 1 ? ` +${state.running.length - 1}` : '';
270
+ const count = state.running.length > 1 ? `${state.running.length} tasks:` : 'task';
271
+ parts.push(`${count} "${quotedText(first.title, 24)}"${first.at ? ` ${span(now - first.at)}` : ''}${more}`);
272
+ }
273
+ if (state.routines.length) {
274
+ const next = state.routines
275
+ .filter((routine) => routine.enabled !== false && epoch(routine.nextFireAt))
276
+ .sort((left, right) => epoch(left.nextFireAt) - epoch(right.nextFireAt))[0];
277
+ parts.push(
278
+ `${plural(state.routines.length, 'routine')}${next ? `, next ${quotedText(next.name, 20)} ${until(epoch(next.nextFireAt), now)}` : ''}`
279
+ );
280
+ }
281
+ const fixed = parts.join(' · ');
282
+ const preview = oneLine(state.home?.lastMessagePreview || state.home?.preview);
283
+ const room = BOT_LINE_LIMIT - fixed.length - 5;
284
+ return cut(preview && room >= MIN_PREVIEW ? `${fixed} · "${quotedText(preview, room)}"` : fixed, BOT_LINE_LIMIT);
285
+ }
286
+
287
+ const mixyBot = (ctx) => ({ id: MIXY_AGENT_ID, name: ctx.mixy, self: true });
288
+
289
+ /** The bots the caller sees: every bot then Mixy when she has something to
290
+ * show, or just the caller's own bot. */
291
+ function visibleStates(ctx) {
292
+ if (ctx.own) {
293
+ const bot = ctx.own === MIXY_AGENT_ID ? mixyBot(ctx) : ctx.bots[0];
294
+ return bot ? [botState(bot, ctx)] : [];
295
+ }
296
+ const states = ctx.bots
297
+ .map((bot) => botState(bot, ctx))
298
+ .sort(
299
+ (left, right) =>
300
+ Number(right.flags.length > 0) - Number(left.flags.length > 0) ||
301
+ Number(right.working) - Number(left.working) ||
302
+ right.lastAt - left.lastAt ||
303
+ (left.bot.id < right.bot.id ? -1 : 1)
304
+ );
305
+ const mixy = botState(mixyBot(ctx), ctx);
306
+ if (mixy.routines.length || mixy.running.length || mixy.approvals) states.push(mixy);
307
+ return states;
308
+ }
309
+
206
310
  export function createBotStatus({
207
311
  getSessionService,
208
312
  listBots = defaultListBots,
@@ -259,104 +363,6 @@ export function createBotStatus({
259
363
  };
260
364
  }
261
365
 
262
- /** Everything known about one bot, from the gathered state. */
263
- function botState(bot, ctx) {
264
- const homeId = agentHomeSessionId(bot.id);
265
- const owned = ctx.owned.get(bot.id) || [];
266
- const home = ctx.rows.get(homeId) || null;
267
- // Running task sessions: a turn whose report is still owed, or one working now.
268
- const tasks = new Map();
269
- const addTask = (id, title, at) => {
270
- const known = tasks.get(id);
271
- if (!known) tasks.set(id, { id, title, at });
272
- else if (at && (!known.at || at < known.at)) known.at = at;
273
- };
274
- for (const watch of ctx.watches) {
275
- if (watch.agentId !== bot.id || watch.target === 'session' || !watch.taskSessionId) continue;
276
- addTask(watch.taskSessionId, watch.title, Number(watch.at) || 0);
277
- }
278
- for (const row of owned) {
279
- if (row.id === homeId || roomMemberOfSession(row.id) || !isWorking(row)) continue;
280
- addTask(row.id, row.title, Number(row.createdAt) || 0);
281
- }
282
- const running = [...tasks.values()].sort((left, right) => left.at - right.at || (left.id < right.id ? -1 : 1));
283
- const held = ctx.held.filter((entry) => entry.agentId === bot.id);
284
- const approvals = held.length + [homeId, ...running.map((task) => task.id)].filter(ctx.awaitingApproval).length;
285
- const routines = ctx.routines.rows
286
- .filter((routine) => (routine.owner || MIXY_AGENT_ID) === bot.id)
287
- .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
288
- const flags = [];
289
- if (approvals) flags.push(`${plural(approvals, 'approval')} waiting`);
290
- for (const routine of routines) {
291
- const trouble = routineTrouble(routine);
292
- if (trouble.length) flags.push(`${quotedText(routine.name, 20)} ${trouble.join(', ')}`);
293
- }
294
- if (bot.disabled) flags.push('disabled');
295
- return {
296
- bot,
297
- homeId,
298
- home,
299
- owned,
300
- running,
301
- held,
302
- approvals,
303
- routines,
304
- flags,
305
- working: isWorking(home) || running.some((task) => isWorking(ctx.rows.get(task.id))),
306
- lastAt: activityOf(home),
307
- };
308
- }
309
-
310
- function botLine(state, now) {
311
- const { bot } = state;
312
- const parts = [`${quotedText(bot.name, 40)} (${bot.id})`, `chat ${state.homeId}`];
313
- if (bot.self) parts.push('you');
314
- parts.push(state.working ? 'working' : 'idle');
315
- if (state.flags.length) parts.push(`attention: ${state.flags.join('; ')}`);
316
- parts.push(state.lastAt ? `last ${ago(state.lastAt, now)}` : 'no chat yet');
317
- if (state.running.length) {
318
- const [first] = state.running;
319
- const more = state.running.length > 1 ? ` +${state.running.length - 1}` : '';
320
- const count = state.running.length > 1 ? `${state.running.length} tasks:` : 'task';
321
- parts.push(`${count} "${quotedText(first.title, 24)}"${first.at ? ` ${span(now - first.at)}` : ''}${more}`);
322
- }
323
- if (state.routines.length) {
324
- const next = state.routines
325
- .filter((routine) => routine.enabled !== false && epoch(routine.nextFireAt))
326
- .sort((left, right) => epoch(left.nextFireAt) - epoch(right.nextFireAt))[0];
327
- parts.push(
328
- `${plural(state.routines.length, 'routine')}${next ? `, next ${quotedText(next.name, 20)} ${until(epoch(next.nextFireAt), now)}` : ''}`
329
- );
330
- }
331
- const fixed = parts.join(' · ');
332
- const preview = oneLine(state.home?.lastMessagePreview || state.home?.preview);
333
- const room = BOT_LINE_LIMIT - fixed.length - 5;
334
- return cut(preview && room >= MIN_PREVIEW ? `${fixed} · "${quotedText(preview, room)}"` : fixed, BOT_LINE_LIMIT);
335
- }
336
-
337
- const mixyBot = (ctx) => ({ id: MIXY_AGENT_ID, name: ctx.mixy, self: true });
338
-
339
- /** The bots the caller sees: every bot then Mixy when she has something to
340
- * show, or just the caller's own bot. */
341
- function visibleStates(ctx) {
342
- if (ctx.own) {
343
- const bot = ctx.own === MIXY_AGENT_ID ? mixyBot(ctx) : ctx.bots[0];
344
- return bot ? [botState(bot, ctx)] : [];
345
- }
346
- const states = ctx.bots
347
- .map((bot) => botState(bot, ctx))
348
- .sort(
349
- (left, right) =>
350
- Number(right.flags.length > 0) - Number(left.flags.length > 0) ||
351
- Number(right.working) - Number(left.working) ||
352
- right.lastAt - left.lastAt ||
353
- (left.bot.id < right.bot.id ? -1 : 1)
354
- );
355
- const mixy = botState(mixyBot(ctx), ctx);
356
- if (mixy.routines.length || mixy.running.length || mixy.approvals) states.push(mixy);
357
- return states;
358
- }
359
-
360
366
  async function overview(own) {
361
367
  const ctx = await gather(own);
362
368
  const states = visibleStates(ctx);
@@ -0,0 +1,38 @@
1
+ // A bot id as the `session_id` of read, send and status: a bot's chat is a
2
+ // session of its own (`sess_home_<id>`), but the schema also lets a model name
3
+ // the bot (`bots` takes either), so the id resolves to that home chat — before
4
+ // any check of the target, so the bot-chain, hop and task-origin checks see
5
+ // the chat they would for `sess_home_<id>`. A minted session id always has an
6
+ // underscore, a normalized bot id never does (agent-home.mjs), so only ids
7
+ // shaped like a bot id are looked up.
8
+ import { MIXY_AGENT_ID, agentHomeSessionId } from '../runtime/agent/orchestrator/session/agent-home.mjs';
9
+ import { defaultListBots, quotedText } from './bot-status.mjs';
10
+
11
+ const MAX_NAMED_BOTS = 30;
12
+ /** The actions whose `session_id` may be a bot id. */
13
+ export const BOT_TARGET_ACTIONS = new Set(['read', 'send', 'status']);
14
+
15
+ /** The ids of the bots a send can reach: Mixy and every contact agent. */
16
+ async function botIds(listBots) {
17
+ return [MIXY_AGENT_ID, ...(await listBots()).map((bot) => bot.id)];
18
+ }
19
+
20
+ /** `target`'s home chat when it is a known bot id, else `target` unchanged. */
21
+ export async function resolveBotTarget(target, listBots = defaultListBots) {
22
+ const home = agentHomeSessionId(target);
23
+ return home && (await botIds(listBots)).includes(target) ? home : target;
24
+ }
25
+
26
+ /** Whether `target` is shaped like a bot id (so, with no session, a mistyped one). */
27
+ export const isBotShaped = (target) => agentHomeSessionId(target) !== '';
28
+
29
+ /** The error for a bot-shaped `target` that is neither a known bot nor a session. */
30
+ export async function unknownBotError(target, listBots = defaultListBots, cause) {
31
+ const ids = await botIds(listBots);
32
+ const named = ids.slice(0, MAX_NAMED_BOTS).join(', ');
33
+ const more = ids.length > MAX_NAMED_BOTS ? `, … (${ids.length - MAX_NAMED_BOTS} more)` : '';
34
+ return new Error(
35
+ `session: "${quotedText(target, 64)}" is neither a session nor a known bot id; bot ids: ${named}${more}; session action=list finds session ids`,
36
+ cause ? { cause } : undefined
37
+ );
38
+ }
@@ -12,7 +12,12 @@ import {
12
12
  testWebhook,
13
13
  withScheduleRenameReserved,
14
14
  } from './services/channel-admin.mjs';
15
- import { getSchedule, markScheduleFailure, markScheduleSkipped, markScheduleSuccess } from '../runtime/channels/lib/schedules-db.mjs';
15
+ import {
16
+ getSchedule,
17
+ markScheduleFailure,
18
+ markScheduleSkipped,
19
+ markScheduleSuccess,
20
+ } from '../runtime/channels/lib/schedules-db.mjs';
16
21
  import { scheduleRenameUncertainError } from '../runtime/channels/lib/schedule-errors.mjs';
17
22
  import { loadEndpointConfig, readEndpointLastPayload } from '../runtime/channels/lib/webhooks-db.mjs';
18
23
  import { webhookEventSummary, webhookRunPrompt } from '../runtime/channels/lib/webhook/session-dispatch.mjs';
@@ -1,6 +1,6 @@
1
- // After the multi-account connector merge (connector-catalog.mjs
2
- // mergeConnectorAccountServers) `gmail-2`, `google-calendar-2`… are accounts of
3
- // one server, no longer servers. Every store of ours that keys a setting by
1
+ // After the connector merge (connector-catalog.mjs mergeConnectorAccountServers)
2
+ // `gmail-2`, `notion-2`, `postgres-2`… are accounts of their connector's one
3
+ // server, no longer servers. Every store of ours that keys a setting by
4
4
  // MCP server name must name the surviving server instead:
5
5
  // agents/<id>/agent.json, bots/<id>/agent.json connectors.off / connectors.tools
6
6
  // (a legacy allow list too)
@@ -11,14 +11,15 @@
11
11
  // name models, not servers.) Project and plugin hook files are the user's or
12
12
  // the plugin's own and are never rewritten here.
13
13
  //
14
- // Rule: the merged connector is OFF for an agent/project only when EVERY
15
- // merged server was off (the same rule as the merged server's `enabled`: one
16
- // working account keeps the connector usable). Per-tool permissions move to
17
- // the surviving name; where two merged servers disagree on a tool the MORE
18
- // PERMISSIVE permission wins, as "on beats off" does at server level. Entries
19
- // of a server that was off are dormant and are dropped when the connector
20
- // stays on, so they never become live. A setting that names no merged-away
21
- // server is never touched, which makes every run after the first a no-op.
14
+ // Rule: differences are ignored and the topmost server decides. The merged
15
+ // connector is on or off for an agent/project as the surviving server was
16
+ // there when the setting names it, else as the lowest-numbered merged server
17
+ // it names (so a switched-off `-N` server never becomes reachable through the
18
+ // merge). Per-tool permissions move to the surviving name; where merged
19
+ // servers disagree on a tool the surviving server's own entry wins, else the
20
+ // first merged server's. Entries of a server that was off are dormant and
21
+ // dropped when the connector stays on. A setting that names no merged-away
22
+ // server is never touched, so every run after the first is a no-op.
22
23
  //
23
24
  // The merge is saved to the config once, so the rename mapping outlives it:
24
25
  // `<data>/connector-merge-pending.json` ({ merged: [{ name, from }] }) is
@@ -35,7 +36,6 @@ import { readdirSync, readFileSync, rmSync } from 'node:fs';
35
36
  import { join } from 'node:path';
36
37
  import { normalizeRules, standardConfigReport } from './services/hook-bus/config.mjs';
37
38
  import {
38
- PERMISSION_RANK,
39
39
  PROJECT_CONNECTORS_FILE,
40
40
  connectorEnabled,
41
41
  parseConnectorPolicy,
@@ -56,7 +56,8 @@ function mapMergedConnectorPolicy(policy, merged) {
56
56
  current.off.includes(server) || current.allow?.includes(server) || Object.hasOwn(current.tools, server);
57
57
  if (!gone.some(named)) continue;
58
58
  const live = from.filter((server) => connectorEnabled(current, server));
59
- const on = live.length > 0;
59
+ // `from` lists the surviving server first, then the others lowest-numbered first.
60
+ const on = connectorEnabled(current, from.find(named));
60
61
  const off = current.off.filter((server) => !from.includes(server));
61
62
  const allow = current.allow?.filter((server) => !from.includes(server));
62
63
  if (allow && on) allow.push(name);
@@ -64,9 +65,11 @@ function mapMergedConnectorPolicy(policy, merged) {
64
65
  const tools = { ...current.tools };
65
66
  for (const server of from) delete tools[server];
66
67
  const moved = {};
67
- for (const server of on ? live : from) {
68
+ const sources = on ? live : from;
69
+ for (const server of [name, ...sources.filter((id) => id !== name)]) {
70
+ if (!sources.includes(server)) continue;
68
71
  for (const [tool, permission] of Object.entries(current.tools[server] || {})) {
69
- if (!(tool in moved) || PERMISSION_RANK[permission] > PERMISSION_RANK[moved[tool]]) moved[tool] = permission;
72
+ if (!(tool in moved)) moved[tool] = permission;
70
73
  }
71
74
  }
72
75
  if (Object.keys(moved).length) tools[name] = moved;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The thread titles Codex itself stores, by thread id (read-only):
3
+ *
4
+ * state_<N>.sqlite `threads.title`, overridden by `threads.name` (a rename)
5
+ * session_index.jsonl append-only `{ id, thread_name }`; the latest
6
+ * non-empty name of an id wins and overrides the DB
7
+ *
8
+ * Anything unreadable is skipped: a missing or locked store simply leaves the
9
+ * conversation to the title derived from its messages.
10
+ */
11
+ import { DatabaseSync } from 'node:sqlite';
12
+ import { readFile, readdir } from 'node:fs/promises';
13
+ import { join } from 'node:path';
14
+ import { titleFromText } from '../../runtime/agent/orchestrator/session/conversation-import/turns.mjs';
15
+
16
+ const STATE_DB_RE = /^state_(\d+)\.sqlite$/i;
17
+
18
+ async function newestStateDb(home) {
19
+ let newest = null;
20
+ for (const name of await readdir(home).catch(() => [])) {
21
+ const version = STATE_DB_RE.exec(name)?.[1];
22
+ if (version !== undefined && (!newest || Number(version) > newest.version)) {
23
+ newest = { name, version: Number(version) };
24
+ }
25
+ }
26
+ return newest ? join(home, newest.name) : null;
27
+ }
28
+
29
+ function readStateRows(path) {
30
+ const db = new DatabaseSync(path, { readOnly: true });
31
+ try {
32
+ const columns = new Set(
33
+ db
34
+ .prepare('PRAGMA table_info(threads)')
35
+ .all()
36
+ .map((column) => column.name)
37
+ );
38
+ const wanted = ['title', 'name'].filter((column) => columns.has(column));
39
+ if (!wanted.length) return [];
40
+ return db.prepare(`SELECT id, ${wanted.join(', ')} FROM threads`).all();
41
+ } finally {
42
+ db.close();
43
+ }
44
+ }
45
+
46
+ async function readStateTitles(home, titles) {
47
+ try {
48
+ const path = await newestStateDb(home);
49
+ if (!path) return;
50
+ const rows = readStateRows(path);
51
+ for (const column of ['title', 'name']) {
52
+ for (const row of rows) {
53
+ const title = titleFromText(row[column]);
54
+ if (title && typeof row.id === 'string') titles.set(row.id, title);
55
+ }
56
+ }
57
+ } catch {
58
+ /* unreadable store: fall back to the session index and derived titles */
59
+ }
60
+ }
61
+
62
+ async function readIndexTitles(home, titles) {
63
+ let text;
64
+ try {
65
+ text = await readFile(join(home, 'session_index.jsonl'), 'utf8');
66
+ } catch {
67
+ return;
68
+ }
69
+ for (const line of text.split('\n')) {
70
+ if (!line.trim()) continue;
71
+ let entry;
72
+ try {
73
+ entry = JSON.parse(line);
74
+ } catch {
75
+ continue;
76
+ }
77
+ const title = titleFromText(entry?.thread_name);
78
+ if (title && typeof entry.id === 'string') titles.set(entry.id, title);
79
+ }
80
+ }
81
+
82
+ /** Map of Codex thread id → its stored title (whitespace-normalized, ≤100 chars). */
83
+ export async function loadCodexThreadTitles(home) {
84
+ const titles = new Map();
85
+ await readStateTitles(home, titles);
86
+ await readIndexTitles(home, titles);
87
+ return titles;
88
+ }