mixdog 1.3.0 → 1.3.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 (423) hide show
  1. package/NOTICE.md +52 -9
  2. package/README.md +8 -4
  3. package/package.json +2 -2
  4. package/scripts/native-release-status.mjs +238 -0
  5. package/src/defaults/shipped-history.json +8 -1
  6. package/src/defaults/skills/pptx/scripts/qc-pages.mjs +3 -2
  7. package/src/defaults/skills/setup/SKILL.md +23 -1
  8. package/src/defaults/skills/setup/references/actions.md +54 -4
  9. package/src/defaults/skills/setup/references/surfaces.md +23 -3
  10. package/src/defaults/skills/setup-guide/SKILL.md +17 -10
  11. package/src/defaults/skills/visualize/SKILL.md +9 -6
  12. package/src/defaults/skills/visualize/references/craft.md +8 -1
  13. package/src/help.mjs +1 -1
  14. package/src/lib/keychain-cjs.cjs +4 -1
  15. package/src/lib/rules-builder.cjs +14 -7
  16. package/src/output-styles/common.md +13 -8
  17. package/src/rules/agent-mode/AGENT_MODE.md +9 -6
  18. package/src/rules/agent-mode/MIXY.md +11 -6
  19. package/src/rules/lead/LEAD.md +2 -2
  20. package/src/rules/shared/10-tool-workflow.md +4 -0
  21. package/src/rules/shared/20-research.md +2 -0
  22. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +5 -0
  23. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +8 -0
  24. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -1
  25. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +114 -26
  26. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +8 -0
  27. package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +5 -4
  28. package/src/runtime/agent/orchestrator/agent-trace.mjs +3 -0
  29. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +4 -0
  30. package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
  31. package/src/runtime/agent/orchestrator/config-storage.mjs +10 -3
  32. package/src/runtime/agent/orchestrator/config.mjs +11 -0
  33. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +81 -16
  34. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +97 -4
  35. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +6 -10
  36. package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
  37. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +80 -31
  38. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  40. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +67 -38
  41. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -0
  42. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
  43. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +6 -2
  44. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +34 -16
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +31 -4
  46. package/src/runtime/agent/orchestrator/providers/cursor.mjs +4 -1
  47. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +11 -8
  48. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -0
  49. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +19 -1
  50. package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +13 -0
  51. package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
  52. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -1
  53. package/src/runtime/agent/orchestrator/providers/mixdog-local.mjs +3 -1
  54. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +1 -0
  55. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +5 -5
  56. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +9 -5
  57. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +9 -1
  58. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
  59. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +10 -2
  60. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +30 -3
  61. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +1 -1
  62. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
  63. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +3 -1
  64. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +61 -8
  65. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
  66. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -0
  67. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
  68. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +90 -24
  69. package/src/runtime/agent/orchestrator/runtime-core/fs-utils.mjs +8 -1
  70. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +1 -1
  71. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +68 -22
  72. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +1 -1
  73. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +5 -5
  74. package/src/runtime/agent/orchestrator/runtime-core/route-context-state.mjs +81 -0
  75. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -1
  76. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +12 -1
  77. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +17 -6
  78. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +41 -10
  79. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +6 -4
  80. package/src/runtime/agent/orchestrator/runtime-core/workflow/packs.mjs +8 -4
  81. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +2 -0
  82. package/src/runtime/agent/orchestrator/session/agent-mode.mjs +0 -6
  83. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +1 -1
  84. package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +22 -4
  85. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +21 -2
  86. package/src/runtime/agent/orchestrator/session/agent-room.mjs +149 -45
  87. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +80 -0
  88. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  89. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +14 -11
  90. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +3 -0
  91. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +68 -18
  92. package/src/runtime/agent/orchestrator/session/compact/summary-mode.mjs +16 -0
  93. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +87 -0
  94. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +2 -0
  95. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +5 -1
  96. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +1 -1
  97. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/session/context-utils.mjs +41 -10
  99. package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +230 -0
  100. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +156 -25
  101. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +20 -0
  102. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +21 -9
  103. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +73 -0
  104. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +55 -27
  105. package/src/runtime/agent/orchestrator/session/human-gate/unattended-port.mjs +15 -0
  106. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +4 -1
  107. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +189 -105
  108. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
  109. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +6 -2
  110. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +111 -9
  111. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -14
  112. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -0
  113. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +38 -5
  114. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +21 -0
  115. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -1
  116. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +12 -0
  117. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +11 -5
  118. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +46 -4
  119. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +13 -2
  120. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
  121. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +4 -0
  122. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  123. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  124. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +44 -18
  125. package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +99 -0
  126. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +42 -0
  127. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +3 -9
  128. package/src/runtime/agent/orchestrator/session/manager/pending-spool-file.mjs +1 -1
  129. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +5 -3
  130. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
  131. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +40 -1
  132. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
  133. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +20 -0
  134. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +62 -47
  135. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +6 -8
  136. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +12 -1
  137. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +6 -15
  138. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +7 -1
  139. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +24 -8
  140. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +1 -1
  141. package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +94 -13
  142. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +5 -2
  143. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +42 -10
  144. package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +21 -3
  145. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +35 -4
  146. package/src/runtime/agent/orchestrator/session/routine-result.mjs +179 -16
  147. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -1
  148. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +3 -1
  149. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +41 -7
  150. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +10 -2
  151. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +14 -2
  152. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +15 -1
  153. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +8 -3
  154. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +36 -1
  155. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -1
  156. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +40 -5
  157. package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +47 -2
  158. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +125 -0
  159. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +4 -0
  160. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +78 -43
  161. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +49 -14
  162. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +134 -17
  163. package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +35 -13
  164. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +25 -5
  165. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -3
  166. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +13 -14
  167. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/transport-artifacts.mjs +9 -0
  168. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +19 -14
  169. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +7 -1
  170. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -14
  171. package/src/runtime/agent/orchestrator/tools/builtin/pdf-test-fixtures.mjs +5 -3
  172. package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -2
  173. package/src/runtime/agent/orchestrator/tools/builtin/read-single-media.mjs +47 -2
  174. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +264 -87
  175. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +10 -4
  176. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +34 -21
  177. package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +8 -4
  178. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +9 -30
  179. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +24 -12
  180. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +3 -2
  181. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -2
  182. package/src/runtime/agent/orchestrator/tools/patch/delete-quarantine.mjs +2 -1
  183. package/src/runtime/agent/orchestrator/tools/patch/replay-capture.mjs +4 -2
  184. package/src/runtime/agent/orchestrator/tools/patch/rollback-state.mjs +33 -2
  185. package/src/runtime/agent/orchestrator/tools/patch-manifest.json +13 -13
  186. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +5 -3
  187. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +3 -1
  188. package/src/runtime/attachments/attachment-reference.mjs +155 -0
  189. package/src/runtime/attachments/limits.mjs +5 -1
  190. package/src/runtime/attachments/office-extract.mjs +3 -6
  191. package/src/runtime/attachments/pdf-extract.mjs +84 -10
  192. package/src/runtime/attachments/store.mjs +55 -30
  193. package/src/runtime/browser-bridge/client.mjs +73 -20
  194. package/src/runtime/channels/lib/runtime-paths.mjs +1 -1
  195. package/src/runtime/channels/lib/scheduler.mjs +14 -7
  196. package/src/runtime/channels/lib/state-file.mjs +15 -15
  197. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +14 -13
  198. package/src/runtime/channels/lib/webhook/relay-tunnel.mjs +22 -18
  199. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +14 -36
  200. package/src/runtime/channels/lib/worker-main.mjs +3 -2
  201. package/src/runtime/effort-judge/compact-tokenizer.mjs +8 -2
  202. package/src/runtime/effort-judge/judge-client.mjs +6 -3
  203. package/src/runtime/effort-judge/model-install.mjs +16 -8
  204. package/src/runtime/effort-judge/model-manifest.json +7 -7
  205. package/src/runtime/local-provider/asset-installer.mjs +10 -4
  206. package/src/runtime/local-provider/catalog.mjs +5 -2
  207. package/src/runtime/local-provider/registered-models.mjs +64 -27
  208. package/src/runtime/local-provider/server.mjs +2 -3
  209. package/src/runtime/media/adapters/image-api.mjs +89 -0
  210. package/src/runtime/media/auth.mjs +64 -1
  211. package/src/runtime/media/catalog.mjs +66 -4
  212. package/src/runtime/media/jobs.mjs +4 -0
  213. package/src/runtime/media/lanes.mjs +46 -5
  214. package/src/runtime/media/media-usage.mjs +17 -0
  215. package/src/runtime/media/renditions.mjs +15 -15
  216. package/src/runtime/media/store.mjs +36 -35
  217. package/src/runtime/media/tool.mjs +8 -1
  218. package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +8 -2
  219. package/src/runtime/memory/lib/embedding-model-files.mjs +30 -7
  220. package/src/runtime/memory/lib/ingest/transcript-tail.mjs +16 -7
  221. package/src/runtime/memory/lib/pg/process.mjs +8 -4
  222. package/src/runtime/memory/lib/project-id-resolver.mjs +5 -1
  223. package/src/runtime/memory/lib/runtime-fetcher.mjs +6 -1
  224. package/src/runtime/office/core/journal.mjs +7 -14
  225. package/src/runtime/office/design/library/design-library-core.mjs +4 -16
  226. package/src/runtime/office/pdf/ocr-engine-worker.mjs +37 -0
  227. package/src/runtime/office/pdf/ocr-engine.mjs +146 -0
  228. package/src/runtime/office/pdf/pdf-ocr.mjs +51 -21
  229. package/src/runtime/office/pdf/pdf-render.mjs +30 -18
  230. package/src/runtime/office/portable/ooxml-validator.mjs +2 -2
  231. package/src/runtime/office/portable/portable-soffice.mjs +4 -0
  232. package/src/runtime/shared/agent-kind-migration.mjs +200 -0
  233. package/src/runtime/shared/agent-kind.mjs +152 -0
  234. package/src/runtime/shared/agent-message-envelope.d.mts +6 -0
  235. package/src/runtime/shared/agent-message-envelope.mjs +44 -0
  236. package/src/runtime/shared/agent-reap-state.d.mts +4 -0
  237. package/src/runtime/shared/agent-route-config.d.mts +1 -0
  238. package/src/runtime/shared/agent-route-config.mjs +22 -8
  239. package/src/runtime/shared/agent-store.mjs +149 -0
  240. package/src/runtime/shared/agent-task-starts.mjs +27 -0
  241. package/src/runtime/shared/atomic-file.d.mts +50 -0
  242. package/src/runtime/shared/atomic-file.mjs +394 -132
  243. package/src/runtime/shared/background-tasks.mjs +7 -4
  244. package/src/runtime/shared/bot-hops.mjs +30 -0
  245. package/src/runtime/shared/bot-split-migration.mjs +457 -0
  246. package/src/runtime/shared/bounded-download.mjs +4 -2
  247. package/src/runtime/shared/config-patch.mjs +20 -1
  248. package/src/runtime/shared/config.mjs +39 -9
  249. package/src/runtime/shared/connector-catalog.d.mts +1 -2
  250. package/src/runtime/shared/connector-catalog.mjs +2 -4
  251. package/src/runtime/shared/connector-triggers.mjs +2 -0
  252. package/src/runtime/shared/defaults-separation.mjs +6 -2
  253. package/src/runtime/shared/delegated-approval-host.mjs +74 -0
  254. package/src/runtime/shared/err-text.mjs +7 -1
  255. package/src/runtime/shared/error-presentation.mjs +113 -10
  256. package/src/runtime/shared/file-has-data.mjs +28 -0
  257. package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
  258. package/src/runtime/shared/handoff-artifacts.mjs +61 -0
  259. package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
  260. package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
  261. package/src/runtime/shared/llm/usage-ledger-import.mjs +37 -18
  262. package/src/runtime/shared/model-route-fallback.mjs +79 -7
  263. package/src/runtime/shared/pending-agent-work.mjs +54 -0
  264. package/src/runtime/shared/plain-preview.mjs +22 -17
  265. package/src/runtime/shared/process-lifecycle.mjs +8 -12
  266. package/src/runtime/shared/projects.mjs +50 -41
  267. package/src/runtime/shared/provider-accounts.mjs +17 -12
  268. package/src/runtime/shared/routine-trigger.d.mts +6 -1
  269. package/src/runtime/shared/routine-trigger.mjs +14 -6
  270. package/src/runtime/shared/run-child.d.mts +3 -0
  271. package/src/runtime/shared/run-child.mjs +24 -3
  272. package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
  273. package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
  274. package/src/runtime/shared/session-baseline-store.mjs +8 -2
  275. package/src/runtime/shared/singleton-owner.mjs +7 -6
  276. package/src/runtime/shared/skill-tool-dependencies.mjs +4 -10
  277. package/src/runtime/shared/staged-update.mjs +4 -2
  278. package/src/runtime/shared/statusline/statusline-segments.mjs +4 -15
  279. package/src/runtime/shared/tool-execution-contract.mjs +6 -0
  280. package/src/runtime/shared/transcript-metadata.mjs +28 -3
  281. package/src/runtime/shared/transcript-writer/session-record.mjs +7 -6
  282. package/src/runtime/shared/turn-snapshot-store.mjs +5 -4
  283. package/src/runtime/shared/turn-snapshot.mjs +44 -2
  284. package/src/runtime/shared/usage-readout-totals.mjs +15 -13
  285. package/src/runtime/shared/user-cwd.mjs +9 -4
  286. package/src/runtime/shared/user-data-guard.mjs +46 -44
  287. package/src/runtime/shared/utf8-cut.mjs +10 -0
  288. package/src/runtime/shared/worktrees/activity-gate.mjs +269 -61
  289. package/src/runtime/shared/worktrees/registry.mjs +26 -26
  290. package/src/runtime/tidy/core-install.mjs +26 -4
  291. package/src/runtime/tidy/install.mjs +91 -23
  292. package/src/runtime/web-search/lib/config.mjs +4 -16
  293. package/src/session-runtime/agent-home-delivery.mjs +859 -136
  294. package/src/session-runtime/agent-room-delivery.mjs +167 -19
  295. package/src/session-runtime/agent-task-sessions.mjs +831 -69
  296. package/src/session-runtime/agent-tool-routing.mjs +1 -0
  297. package/src/session-runtime/boot/apis.mjs +58 -24
  298. package/src/session-runtime/boot/config.mjs +1 -0
  299. package/src/session-runtime/boot/facade.mjs +11 -1
  300. package/src/session-runtime/boot/infrastructure.mjs +14 -2
  301. package/src/session-runtime/boot/providers.mjs +16 -6
  302. package/src/session-runtime/boot/shared.mjs +12 -6
  303. package/src/session-runtime/boot/tools.mjs +2 -2
  304. package/src/session-runtime/bot-status.mjs +432 -0
  305. package/src/session-runtime/config-lifecycle/lead-route-sync.mjs +29 -0
  306. package/src/session-runtime/config-lifecycle.mjs +78 -32
  307. package/src/session-runtime/cwd-plugins/core-memory-context.mjs +2 -4
  308. package/src/session-runtime/handoff-attachments.mjs +593 -0
  309. package/src/session-runtime/held-requests.mjs +36 -33
  310. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +10 -1
  311. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -2
  312. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +45 -6
  313. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  314. package/src/session-runtime/lifecycle/teardown.mjs +11 -3
  315. package/src/session-runtime/mcp-glue/connect.mjs +100 -186
  316. package/src/session-runtime/mcp-glue/initial-connect-gate.mjs +57 -0
  317. package/src/session-runtime/mcp-glue/server-connection.mjs +71 -0
  318. package/src/session-runtime/media-api.mjs +5 -2
  319. package/src/session-runtime/model-route/route-persist.mjs +2 -2
  320. package/src/session-runtime/model-route/route-tuning.mjs +11 -2
  321. package/src/session-runtime/model-route/set-route.mjs +82 -2
  322. package/src/session-runtime/native-web-search.mjs +2 -2
  323. package/src/session-runtime/new-session-config.mjs +6 -1
  324. package/src/session-runtime/owned-automation-run.mjs +8 -1
  325. package/src/session-runtime/room-member-gate.mjs +16 -3
  326. package/src/session-runtime/route-resolution.mjs +21 -19
  327. package/src/session-runtime/route-state.mjs +1 -59
  328. package/src/session-runtime/routine-home-turn.mjs +5 -3
  329. package/src/session-runtime/runtime-bootstrap.mjs +5 -3
  330. package/src/session-runtime/runtime-paths.mjs +11 -5
  331. package/src/session-runtime/runtime-tunables.mjs +6 -0
  332. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +11 -2
  333. package/src/session-runtime/services/agent-tool/close-flow.mjs +4 -2
  334. package/src/session-runtime/services/agent-tool/execute-send.mjs +1 -0
  335. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +1 -0
  336. package/src/session-runtime/services/agent-tool/helpers.mjs +24 -5
  337. package/src/session-runtime/services/agent-tool/restart-notify.mjs +10 -0
  338. package/src/session-runtime/services/agent-tool/send-flow.mjs +36 -24
  339. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -0
  340. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +6 -3
  341. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +12 -6
  342. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
  343. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  344. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +22 -2
  345. package/src/session-runtime/services/agent-tool/worker-index.mjs +4 -6
  346. package/src/session-runtime/services/agent-tool.mjs +6 -0
  347. package/src/session-runtime/services/daemon-crash-capture/daemon-exit-record.mjs +1 -1
  348. package/src/session-runtime/services/daemon-crash-capture/retention.mjs +4 -3
  349. package/src/session-runtime/services/hook-bus/config-loader.mjs +14 -5
  350. package/src/session-runtime/services/hook-bus/rule-file.mjs +49 -11
  351. package/src/session-runtime/services/plugin-admin.mjs +26 -26
  352. package/src/session-runtime/services/provider-admin.mjs +14 -4
  353. package/src/session-runtime/services/schedule-access.mjs +33 -4
  354. package/src/session-runtime/services/seeds.mjs +4 -3
  355. package/src/session-runtime/services/usage-dashboard.mjs +1 -1
  356. package/src/session-runtime/services/usage-stats-model.mjs +2 -1
  357. package/src/session-runtime/session-create/materialize.mjs +2 -3
  358. package/src/session-runtime/session-create/session-options.mjs +15 -2
  359. package/src/session-runtime/settings-builtin-tools-api.mjs +63 -1
  360. package/src/session-runtime/settings-compaction-api.mjs +86 -39
  361. package/src/session-runtime/setup-tool/executor.mjs +20 -3
  362. package/src/session-runtime/setup-tool/extended-actions.mjs +19 -7
  363. package/src/session-runtime/setup-tool/settings-contract.mjs +37 -1
  364. package/src/session-runtime/setup-tool/tool-defs.mjs +20 -3
  365. package/src/session-runtime/skills-api.mjs +12 -5
  366. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +265 -0
  367. package/src/session-runtime/tool-policy/mode-switch.mjs +54 -0
  368. package/src/session-runtime/tool-policy/pending-switches.mjs +59 -0
  369. package/src/session-runtime/tool-policy/policy-stage.mjs +165 -0
  370. package/src/session-runtime/tool-policy/session-switches.mjs +169 -0
  371. package/src/session-runtime/tool-policy/surface-helpers.mjs +114 -0
  372. package/src/session-runtime/tool-policy/workflow-overlay.mjs +145 -0
  373. package/src/session-runtime/tool-policy-refresh.mjs +47 -358
  374. package/src/session-runtime/tool-surface.mjs +5 -3
  375. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +99 -81
  376. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  377. package/src/session-runtime/turn/turn-run.mjs +2 -1
  378. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +54 -7
  379. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +578 -301
  380. package/src/session-runtime/workflow-agents-api/agent-route.mjs +113 -53
  381. package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
  382. package/src/session-runtime/workflow-agents-api/shared.mjs +5 -1
  383. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +14 -1
  384. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -3
  385. package/src/session-runtime/workspace/workspace-state.mjs +7 -6
  386. package/src/standalone/daemon-agent-control.mjs +4 -1
  387. package/src/standalone/daemon-session-control.mjs +60 -11
  388. package/src/standalone/daemon.mjs +34 -4
  389. package/src/standalone/local-session-runtime.mjs +22 -14
  390. package/src/standalone/session-client.mjs +7 -2
  391. package/src/standalone/session-protocol.mjs +7 -0
  392. package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
  393. package/src/standalone/session-service/agent-tree.mjs +4 -3
  394. package/src/standalone/session-service/session-calls/session-turns.mjs +19 -0
  395. package/src/standalone/session-service.mjs +11 -0
  396. package/src/standalone/session-state-projection.mjs +19 -9
  397. package/src/standalone/session-tool-output.mjs +35 -9
  398. package/src/tui/app/maintenance-pickers/auto-clear-picker.mjs +19 -13
  399. package/src/tui/app/settings-picker/settings-rows.mjs +2 -2
  400. package/src/tui/app/slash-commands.mjs +1 -1
  401. package/src/tui/app/usage-context-panels/context-model.mjs +8 -2
  402. package/src/tui/dist/index.mjs +599 -342
  403. package/src/tui/prompt-history-store.mjs +16 -21
  404. package/src/tui/session/context-state.mjs +4 -0
  405. package/src/tui/session/notice-surface.mjs +3 -4
  406. package/src/tui/session/session-api/intake/abort.mjs +19 -1
  407. package/src/tui/session/session-api/media.mjs +2 -1
  408. package/src/tui/session/session-api/routes-agent-definitions.mjs +75 -0
  409. package/src/tui/session/session-api/routes-write.mjs +203 -0
  410. package/src/tui/session/session-api/routes.mjs +23 -236
  411. package/src/tui/session/session-api/settings.mjs +14 -1
  412. package/src/tui/session/session-flow/drain.mjs +28 -3
  413. package/src/tui/session/session-flow/failed-turn-rewind.mjs +4 -2
  414. package/src/tui/session/session-flow/queue/take-entries.mjs +8 -0
  415. package/src/tui/session/session-flow/steering.mjs +8 -3
  416. package/src/tui/session/tool-approval.mjs +185 -20
  417. package/src/tui/session/transcript-intake.mjs +4 -0
  418. package/src/tui/session/turn-live-call.mjs +11 -3
  419. package/src/tui/session/turn.mjs +36 -17
  420. package/src/tui/transcript-tool-failures.mjs +8 -2
  421. package/src/vendor/statusline/src/gateway/route-meta.mjs +7 -8
  422. package/src/vendor/statusline/src/gateway/session-routes.mjs +6 -7
  423. package/src/rules/agent-mode/ROUTINE.md +0 -6
@@ -9,7 +9,20 @@ import { readAgentFrontmatterPermission } from '../services/agent-tool/helpers.m
9
9
  import { LEAD_DISALLOWED_TOOLS } from '../../runtime/agent/orchestrator/runtime-core/tool-defs.mjs';
10
10
  import { HEADLESS_TOOL_PROFILE } from '../../runtime/agent/orchestrator/runtime-core/tool-profile.mjs';
11
11
  import { AGENT_MODE, resolveSessionMode } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
12
- import { MIXY_AGENT_ID } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
12
+ import { MIXY_AGENT_ID, agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
13
+ import { roomMemberOfSession } from '../../runtime/agent/orchestrator/session/agent-room.mjs';
14
+ import { unattendedApprovalPort } from '../../runtime/agent/orchestrator/session/human-gate/gate.mjs';
15
+
16
+ /** Where a bot created its task session, recorded after its id in the
17
+ * session's `sourceName` (`agent:<id>@home|room|run`): the desktop lets the
18
+ * task act as the bot (its standing allows, "always allow") only when it came
19
+ * from the bot's own attended chat. None when the origin is anything else. */
20
+ function taskOriginSuffix(taskOrigin) {
21
+ const from = clean(taskOrigin?.sessionId);
22
+ if (roomMemberOfSession(from)) return '@room';
23
+ if (unattendedApprovalPort()?.runOf?.(from)) return '@run';
24
+ return agentIdOfHomeSession(from) === clean(taskOrigin?.agentId) ? '@home' : '';
25
+ }
13
26
 
14
27
  // Ownership and permission fields an agent-owned session inherits from its profile.
15
28
  function agentOwnedSessionFields(sessionProfile) {
@@ -83,7 +96,7 @@ export function sessionOptions(deps, coreMemoryContext) {
83
96
  sourceName: agentOwned
84
97
  ? sessionProfile?.sourceName || sessionProfile?.agent || 'agent'
85
98
  : taskOrigin
86
- ? `agent:${taskOrigin.agentId}`
99
+ ? `agent:${taskOrigin.agentId}${taskOriginSuffix(taskOrigin)}`
87
100
  : 'main',
88
101
  ...(taskOrigin ? { taskOrigin } : {}),
89
102
  ...(rt.approvalMode ? { approvalMode: rt.approvalMode } : {}),
@@ -8,8 +8,10 @@ import {
8
8
  setBuiltinInstalledInConfig,
9
9
  } from '../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
10
10
  import { featureEnvOverride, moduleEnabled } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
11
+ import { normalizeAgentAvatar } from '../runtime/shared/agent-avatar.mjs';
11
12
  import { LOCAL_PROVIDER_ID } from '../runtime/local-provider/managed-runtime.mjs';
12
13
  import { INSTRUCTION_FILES_MODES, normalizeInstructionFilesMode } from '../runtime/shared/instruction-files-mode.mjs';
14
+ import { AUTO_EFFORT_BASES, autoEffortBase } from '../runtime/agent/orchestrator/providers/auto-effort.mjs';
13
15
  import { getEmbeddingInfo } from '../runtime/memory/lib/embedding-provider.mjs';
14
16
  import { onnxRuntimeSupported } from '../runtime/shared/onnx-runtime-support.mjs';
15
17
  import {
@@ -21,6 +23,14 @@ import {
21
23
  shutdownEffortJudge,
22
24
  } from '../runtime/effort-judge/judge-client.mjs';
23
25
 
26
+ const MAX_BOT_ORDER_IDS = 500;
27
+ const isBotOrderId = (id) => typeof id === 'string' && id.trim().length > 0 && id.trim().length <= 128;
28
+ /** A stored bot order as trimmed, de-duplicated ids; anything else is no order (null). */
29
+ function normalizeBotOrder(value) {
30
+ if (!Array.isArray(value)) return null;
31
+ return [...new Set(value.filter(isBotOrderId).map((id) => id.trim()))].slice(0, MAX_BOT_ORDER_IDS);
32
+ }
33
+
24
34
  const TOGGLEABLE_BUILTINS = ['git', 'office', 'tidy', 'localProvider', 'autoEffort', 'visualize', 'media'];
25
35
 
26
36
  function setLocalProviderEnabledInConfig(configLike, enabled) {
@@ -85,12 +95,50 @@ export function createBuiltinToolSettings(
85
95
  saveConfigAndAdopt({ ...getConfig(), aiSessionTitles: enabled !== false });
86
96
  return this.getSessionTitleSettings();
87
97
  },
98
+ // The one pixel face every Lead row on the bot page wears, shared by every
99
+ // device that follows this host. Only a mascot look counts; null (the
100
+ // default grey pup) is stored as no key.
101
+ getLeadAppearance() {
102
+ const avatar = normalizeAgentAvatar(getConfig()?.leadAvatar);
103
+ return { avatar: avatar?.kind === 'mascot' ? avatar : null };
104
+ },
105
+ setLeadAppearance(avatar) {
106
+ const config = { ...getConfig() };
107
+ if (avatar == null) {
108
+ delete config.leadAvatar;
109
+ } else {
110
+ const normalized = normalizeAgentAvatar(avatar);
111
+ if (normalized?.kind !== 'mascot') throw new Error('usage: setLeadAppearance(a mascot appearance or null)');
112
+ config.leadAvatar = normalized;
113
+ }
114
+ saveConfigAndAdopt(config);
115
+ return this.getLeadAppearance();
116
+ },
117
+ // The one bot order every device that follows this host shows (Bots page
118
+ // and the Sessions bot section): agent ids only. Mixy is pinned first by
119
+ // the UI and is not part of it; ids of unknown or deleted bots are ignored
120
+ // where the order is applied. No key = the UI's current order.
121
+ getBotOrder() {
122
+ return { order: normalizeBotOrder(getConfig()?.botOrder) ?? [] };
123
+ },
124
+ setBotOrder(order) {
125
+ if (!Array.isArray(order) || order.length > MAX_BOT_ORDER_IDS || order.some((id) => !isBotOrderId(id))) {
126
+ throw new Error('usage: setBotOrder(an array of agent ids)');
127
+ }
128
+ const config = { ...getConfig() };
129
+ const ids = normalizeBotOrder(order);
130
+ if (!ids.length) delete config.botOrder;
131
+ else config.botOrder = ids;
132
+ saveConfigAndAdopt(config);
133
+ return this.getBotOrder();
134
+ },
88
135
  getToolModuleSettings() {
89
136
  const config = getConfig();
90
137
  const localProvider = getLocalProviderStatus?.() || {};
91
138
  const localProviderRuntimeInstalled = localProvider?.runtime?.installed === true;
92
139
  return {
93
140
  instructionFiles: normalizeInstructionFilesMode(config?.instructionFiles),
141
+ autoEffortBase: autoEffortBase(config?.autoEffortBase),
94
142
  webSearch: { enabled: webSearchEnabled() },
95
143
  memory: {
96
144
  enabled: memoryToolsEnabledFn(),
@@ -152,6 +200,14 @@ export function createBuiltinToolSettings(
152
200
  await refreshEmptySessionToolPolicy?.();
153
201
  return this.getToolModuleSettings();
154
202
  },
203
+ /** The global "Auto reasoning base": the effort Auto works around. */
204
+ setAutoEffortBase(level) {
205
+ if (!AUTO_EFFORT_BASES.includes(level)) {
206
+ throw new TypeError(`Auto reasoning base must be one of ${AUTO_EFFORT_BASES.join(', ')}.`);
207
+ }
208
+ saveConfigAndAdopt({ ...getConfig(), autoEffortBase: level });
209
+ return this.getToolModuleSettings();
210
+ },
155
211
  async setMemoryToolsEnabled(enabled) {
156
212
  const config = getConfig();
157
213
  const memoryEnabled = enabled !== false;
@@ -202,11 +258,17 @@ export function createBuiltinToolSettings(
202
258
  /** Extensions → Built-in Install: run the feature's preparation adapter
203
259
  * (model pre-download, component verification), then mark it installed
204
260
  * and enabled in one step. New sessions pick up the tool surface. */
205
- async installBuiltinFeature(name) {
261
+ async installBuiltinFeature(name, options = null) {
206
262
  if (!INSTALLABLE_BUILTIN_IDS.includes(name)) {
207
263
  throw new TypeError('Built-in feature must be git, memory, office, tidy, localProvider, or autoEffort.');
208
264
  }
209
265
  if (name === 'autoEffort' && !onnxRuntimeSupported()) throw new Error(EFFORT_JUDGE_UNSUPPORTED);
266
+ // Code Tidy retry for named engines: fetch just those and leave the
267
+ // feature's installed/enabled state exactly as the user set it.
268
+ if (name === 'tidy' && Array.isArray(options?.engines)) {
269
+ await prepareBuiltinFeature?.(name, { engines: options.engines });
270
+ return this.getToolModuleSettings();
271
+ }
210
272
  await prepareBuiltinFeature?.(name);
211
273
  const config = getConfig();
212
274
  let nextConfig = setBuiltinInstalledInConfig({ ...config }, name, true);
@@ -3,6 +3,8 @@ import {
3
3
  refreshLiveSessionsProviderCacheOpts,
4
4
  refreshSessionProviderCacheOpts,
5
5
  } from '../runtime/agent/orchestrator/session/manager/session-lifecycle.mjs';
6
+ import { isAutoClearUnlimited } from '../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
7
+ import { COMPACTION_SUMMARY_MODES } from '../runtime/agent/orchestrator/session/compact/summary-mode.mjs';
6
8
 
7
9
  // Every spelling of the main-context buffer budget; a new representation
8
10
  // replaces the previous one.
@@ -32,9 +34,60 @@ const SESSION_COMPACTION_KEYS = [
32
34
  'recallWindowSize',
33
35
  'recallConcurrency',
34
36
  'recallCycle1DeadlineMs',
37
+ // Replaced by summaryMode.
38
+ 'useMaintainer',
35
39
  ...MAIN_BUFFER_KEYS,
36
40
  ];
37
41
 
42
+ // Unlimited (never auto-clear) typed as a duration.
43
+ const UNLIMITED_DURATION = /^(?:unlimited|never)$/i;
44
+
45
+ /** Fold the recognised compaction input fields into `next` (mutated and returned). */
46
+ function applyCompactionInput(next, input, hasOwn) {
47
+ if (hasOwn(input, 'auto')) next.auto = input.auto !== false;
48
+ if (hasOwn(input, 'enabled')) next.auto = input.enabled !== false;
49
+ if (hasOwn(input, 'onModelChange')) next.onModelChange = input.onModelChange !== false;
50
+ if (hasOwn(input, 'summaryMode')) {
51
+ if (!COMPACTION_SUMMARY_MODES.includes(input.summaryMode)) {
52
+ throw new Error(`usage: summaryMode ${COMPACTION_SUMMARY_MODES.join(' | ')}`);
53
+ }
54
+ next.summaryMode = input.summaryMode;
55
+ }
56
+ // Legacy Compact type fields are intentionally ignored. There is one
57
+ // fresh-context Compact contract for every session.
58
+ // A new budget representation replaces the previous one. Otherwise a
59
+ // saved token override silently outranks a later percentage edit.
60
+ if (MAIN_BUFFER_KEYS.some((key) => hasOwn(input, key))) {
61
+ for (const old of MAIN_BUFFER_KEYS) delete next[old];
62
+ }
63
+ for (const key of MAIN_BUFFER_KEYS) {
64
+ if (hasOwn(input, key)) next[key] = input[key];
65
+ }
66
+ return next;
67
+ }
68
+
69
+ /** Replace the live session's compaction fields with the saved config's. */
70
+ function adoptSessionCompaction(session, saved) {
71
+ if (!session) return;
72
+ const currentSessionCompaction = { ...(session.compaction || {}) };
73
+ for (const key of SESSION_COMPACTION_KEYS) delete currentSessionCompaction[key];
74
+ session.compaction = { ...currentSessionCompaction, ...saved };
75
+ }
76
+
77
+ // Advanced picker shows only providers the user actually has enabled
78
+ // (config.providers[*].enabled), plus the active route provider, any
79
+ // provider with a custom override, and the 'default' fallback row —
80
+ // not the full built-in table.
81
+ function enabledProviderKeys(config, provider) {
82
+ const enabledProviders = new Set(
83
+ Object.entries(config?.providers || {})
84
+ .filter(([, v]) => v && typeof v === 'object' && v.enabled !== false)
85
+ .map(([k]) => String(k).toLowerCase())
86
+ );
87
+ if (provider) enabledProviders.add(String(provider).toLowerCase());
88
+ return enabledProviders;
89
+ }
90
+
38
91
  export function createCompactionSettings({
39
92
  getConfig,
40
93
  getRoute,
@@ -63,9 +116,21 @@ export function createCompactionSettings({
63
116
  if (input.resetProvider === true || (hasOwn(input, 'idleMs') && input.idleMs == null)) {
64
117
  delete providerIdleMs[providerKey];
65
118
  } else {
66
- const idleMs = hasOwn(input, 'duration') ? parseDurationMs(input.duration) : Number(input.idleMs);
67
- if (!idleMs || !Number.isFinite(idleMs) || idleMs <= 0) throw new Error('usage: duration like 10m, 1h, or 24h');
68
- providerIdleMs[providerKey] = Math.max(60_000, Math.round(idleMs));
119
+ // Unlimited (never auto-clear) is stored as 0: `unlimited: true`, a
120
+ // duration of 'unlimited'/'never', or idleMs 0.
121
+ const unlimited =
122
+ input.unlimited === true ||
123
+ (hasOwn(input, 'duration') && UNLIMITED_DURATION.test(String(input.duration ?? '').trim())) ||
124
+ (!hasOwn(input, 'duration') && hasOwn(input, 'idleMs') && input.idleMs === 0);
125
+ if (unlimited) {
126
+ providerIdleMs[providerKey] = 0;
127
+ } else {
128
+ const idleMs = hasOwn(input, 'duration') ? parseDurationMs(input.duration) : Number(input.idleMs);
129
+ if (!idleMs || !Number.isFinite(idleMs) || idleMs <= 0) {
130
+ throw new Error('usage: duration like 10m, 1h, 24h, or unlimited');
131
+ }
132
+ providerIdleMs[providerKey] = Math.max(60_000, Math.round(idleMs));
133
+ }
69
134
  }
70
135
  saveConfigAndAdopt({ ...config, autoClear: { ...next, providerIdleMs } });
71
136
  refreshLeadCacheOpts();
@@ -79,28 +144,10 @@ export function createCompactionSettings({
79
144
  setCompactionSettings(input = {}) {
80
145
  const config = getConfig();
81
146
  const current = normalizeCompactionConfig(config.compaction);
82
- const next = { ...current };
83
- if (hasOwn(input, 'auto')) next.auto = input.auto !== false;
84
- if (hasOwn(input, 'enabled')) next.auto = input.enabled !== false;
85
- if (hasOwn(input, 'onModelChange')) next.onModelChange = input.onModelChange !== false;
86
- // Legacy Compact type fields are intentionally ignored. There is one
87
- // fresh-context Compact contract for every session.
88
- // A new budget representation replaces the previous one. Otherwise a
89
- // saved token override silently outranks a later percentage edit.
90
- if (MAIN_BUFFER_KEYS.some((key) => hasOwn(input, key))) {
91
- for (const old of MAIN_BUFFER_KEYS) delete next[old];
92
- }
93
- for (const key of MAIN_BUFFER_KEYS) {
94
- if (hasOwn(input, key)) next[key] = input[key];
95
- }
147
+ const next = applyCompactionInput({ ...current }, input, hasOwn);
96
148
  saveConfigAndAdopt({ ...config, compaction: normalizeCompactionConfig(next) });
97
149
  const saved = normalizeCompactionConfig(getConfig().compaction);
98
- const session = getSession();
99
- if (session) {
100
- const currentSessionCompaction = { ...(session.compaction || {}) };
101
- for (const key of SESSION_COMPACTION_KEYS) delete currentSessionCompaction[key];
102
- session.compaction = { ...currentSessionCompaction, ...saved };
103
- }
150
+ adoptSessionCompaction(getSession(), saved);
104
151
  invalidateContextStatusCache();
105
152
  return saved;
106
153
  },
@@ -113,22 +160,17 @@ export function createCompactionSettings({
113
160
  const idleMs = resolveAutoClearIdleMs(config, provider);
114
161
  const key = String(provider || '').toLowerCase();
115
162
  const providerCustom = Boolean(key && key !== 'default' && normalized.providerIdleMs?.[key]);
116
- // Advanced picker shows only providers the user actually has enabled
117
- // (config.providers[*].enabled), plus the active route provider, any
118
- // provider with a custom override, and the 'default' fallback row —
119
- // not the full built-in table.
120
- const enabledProviders = new Set(
121
- Object.entries(config?.providers || {})
122
- .filter(([, v]) => v && typeof v === 'object' && v.enabled !== false)
123
- .map(([k]) => String(k).toLowerCase())
124
- );
125
- if (provider) enabledProviders.add(String(provider).toLowerCase());
126
- const providerDefaults = autoClearProviderDefaults(normalized.providerIdleMs).filter(
163
+ const enabledProviders = enabledProviderKeys(config, provider);
164
+ // Every enabled provider gets its row, including ones without a
165
+ // built-in window (they resolve through the 'default' row).
166
+ const providerDefaults = autoClearProviderDefaults(normalized.providerIdleMs, [...enabledProviders]).filter(
127
167
  (entry) => entry.provider === 'default' || entry.custom === true || enabledProviders.has(entry.provider)
128
168
  );
129
169
  return {
130
170
  enabled: normalized.enabled,
131
171
  idleMs,
172
+ unlimited: isAutoClearUnlimited(idleMs),
173
+ label: isAutoClearUnlimited(idleMs) ? 'unlimited' : formatDurationMs(idleMs),
132
174
  custom: normalized.custom,
133
175
  providerCustom,
134
176
  providerDefault,
@@ -148,11 +190,17 @@ export function createCompactionSettings({
148
190
  throw new Error('autoclear minContextPercent must be a number between 0 and 100');
149
191
  next.minContextPercent = Math.min(100, Math.max(0, Math.round(rawMinPct)));
150
192
  }
151
- const providerKey = String(input.provider || '')
193
+ // `/autoclear unlimited` names no provider: it means the current route's.
194
+ const wantsUnlimited = hasOwn(input, 'duration') && UNLIMITED_DURATION.test(String(input.duration ?? '').trim());
195
+ const providerKey = String(input.provider || (wantsUnlimited ? getRoute()?.provider : '') || '')
152
196
  .trim()
153
197
  .toLowerCase();
154
198
  const editsProviderDefault =
155
- providerKey && (input.resetProvider === true || hasOwn(input, 'duration') || hasOwn(input, 'idleMs'));
199
+ providerKey &&
200
+ (input.resetProvider === true ||
201
+ input.unlimited === true ||
202
+ hasOwn(input, 'duration') ||
203
+ hasOwn(input, 'idleMs'));
156
204
  if (editsProviderDefault) {
157
205
  saveProviderIdle(config, next, providerKey, input);
158
206
  } else {
@@ -165,15 +213,14 @@ export function createCompactionSettings({
165
213
  }
166
214
  if (hasOwn(input, 'duration')) {
167
215
  const idleMs = parseDurationMs(input.duration);
168
- if (!idleMs) throw new Error('usage: /autoclear [on|off|status|<minutes|1h|90m>]');
216
+ if (!idleMs) throw new Error('usage: /autoclear [on|off|status|<minutes|1h|90m>|unlimited]');
169
217
  next.idleMs = idleMs;
170
218
  if (!hasOwn(input, 'enabled')) next.enabled = true;
171
219
  }
172
220
  saveConfigAndAdopt({ ...config, autoClear: next });
173
221
  refreshLeadCacheOpts();
174
222
  }
175
- const resolved = this.getAutoClear();
176
- return { ...resolved, label: formatDurationMs(resolved.idleMs) };
223
+ return this.getAutoClear();
177
224
  },
178
225
  };
179
226
  }
@@ -5,6 +5,7 @@
5
5
  * registers the tool executor before it finishes assembling the API object. */
6
6
  import { builtinFeatureActive } from '../../runtime/agent/orchestrator/runtime-core/builtin-features.mjs';
7
7
  import { ORCHESTRATION_MODES } from '../../runtime/shared/orchestration.mjs';
8
+ import { AUTO_EFFORT_BASES } from '../../runtime/agent/orchestrator/providers/auto-effort.mjs';
8
9
  import { INSTRUCTION_FILES_MODES } from '../../runtime/shared/instruction-files-mode.mjs';
9
10
  import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
10
11
  import { SETUP_DESKTOP_DOMAINS, SETUP_HANDOFFS } from './settings-contract.mjs';
@@ -377,6 +378,17 @@ const SETUP_STATUS_READERS = {
377
378
  // schema, the per-action field list and the route/object-argument minimums.
378
379
  function validateSetupInput(args) {
379
380
  const action = requireEnum(args?.action, SETUP_ACTIONS, 'action');
381
+ // Old callers still ask to connect GitHub: it is the signed-in GitHub CLI, not a catalog connector.
382
+ if (
383
+ action === 'connect_connector' &&
384
+ String(args.connector ?? '')
385
+ .trim()
386
+ .toLowerCase() === 'github'
387
+ ) {
388
+ throw new Error(
389
+ 'GitHub uses the signed-in GitHub CLI; no connector needed. Use the github tool or Settings → Git.'
390
+ );
391
+ }
380
392
  const validationError = schemaValueError({ ...args, action }, SETUP_TOOL_DEFS[0].inputSchema, 'setup');
381
393
  if (validationError) throw new Error(`[tool-input-validation] ${validationError}`);
382
394
  const fields = SETUP_ACTION_FIELDS[action].split(' ').filter(Boolean);
@@ -392,8 +404,11 @@ function validateSetupInput(args) {
392
404
  if (action !== 'set_agent_route' && Object.hasOwn(args.route, 'disabled')) {
393
405
  throw new Error('route.disabled is only accepted by set_agent_route');
394
406
  }
395
- if (Object.hasOwn(args.route, 'fallbacks') && !['set_agent_route', 'set_web_search_route'].includes(action)) {
396
- throw new Error('route.fallbacks is only accepted by set_agent_route and set_web_search_route');
407
+ if (
408
+ Object.hasOwn(args.route, 'fallbacks') &&
409
+ !['set_route', 'set_agent_route', 'set_web_search_route'].includes(action)
410
+ ) {
411
+ throw new Error('route.fallbacks is only accepted by set_route, set_agent_route and set_web_search_route');
397
412
  }
398
413
  for (const field of ['contextPercent', 'contextTokens', 'autoEffort']) {
399
414
  if (action !== 'set_route' && action !== 'set_agent_route' && Object.hasOwn(args.route, field)) {
@@ -522,6 +537,8 @@ const SETUP_ACTION_HANDLERS = {
522
537
  set_web_search_enabled: (rt, args) => rt.setWebSearchEnabled(requireBoolean(args.enabled)),
523
538
  set_instruction_files: (rt, args) =>
524
539
  rt.setInstructionFiles(requireEnum(args.instructionFiles, INSTRUCTION_FILES_MODES, 'instructionFiles')),
540
+ set_auto_effort_base: (rt, args) =>
541
+ rt.setAutoEffortBase(requireEnum(args.autoEffortBase, AUTO_EFFORT_BASES, 'autoEffortBase')),
525
542
  set_builtin_enabled: (rt, args, { requestDesktop }) => {
526
543
  const name = requireEnum(args.name, SETUP_BUILTIN_TOGGLE_FEATURES, 'name');
527
544
  if (DESKTOP_HOSTED_FEATURES.includes(name)) return requestDesktop(args);
@@ -647,7 +664,7 @@ const SETUP_ACTION_HANDLERS = {
647
664
  const entry = connectorById(requireText(args.connector, 'connector'));
648
665
  if (!entry || entry.ownKey) throw new Error(`connector must be one of ${CONNECTOR_IDS.join(', ')}`);
649
666
  const server = (rt.mcpStatus?.()?.servers || []).find((row) => row.connector === entry.id) || null;
650
- const connected = entry.backend.kind === 'builtin' ? null : server?.connected === true;
667
+ const connected = server?.connected === true;
651
668
  return {
652
669
  connector: entry.id,
653
670
  name: entry.name,
@@ -1,7 +1,9 @@
1
1
  import { SETUP_EXTENDED_PROPERTIES, SETUP_DESKTOP_ACTIONS } from './settings-contract.mjs';
2
2
  import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
3
3
  import { OPENAI_COMPAT_PRESETS } from '../../runtime/agent/orchestrator/providers/openai-compat-presets.mjs';
4
- import { agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
4
+ import { MIXY_AGENT_ID, agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
5
+ import { AGENT_MODE, resolveSessionMode } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
6
+ import { BOT_AGENT_KIND, WORKFLOW_AGENT_KIND } from '../../runtime/shared/agent-route-config.mjs';
5
7
  import { assertAutomationAccess, scheduleCallerScope } from '../services/schedule-access.mjs';
6
8
 
7
9
  const own = (value, key) => Object.hasOwn(value || {}, key);
@@ -164,13 +166,20 @@ async function readDefinition(rt, kind, name) {
164
166
  };
165
167
  }
166
168
 
167
- async function saveDefinition(rt, args) {
169
+ // A created agent's explicit marker: the one given, else a bot when Mixy's
170
+ // agent-mode chat creates it (Mixy creates bots), else a workflow agent.
171
+ function createdAgentKind(input, caller) {
172
+ if (own(input, 'kind')) return input.kind;
173
+ const { mode, agentId } = resolveSessionMode({ session: caller });
174
+ return mode === AGENT_MODE && agentId === MIXY_AGENT_ID ? BOT_AGENT_KIND : WORKFLOW_AGENT_KIND;
175
+ }
176
+
177
+ async function saveDefinition(rt, args, context = {}) {
168
178
  const kind = args.definitionKind;
169
179
  const input = args.definition;
170
- const allowed =
171
- kind === 'skill'
172
- ? ['originalName', 'name', 'description', 'body', 'whenToUse', 'toolDependencies']
173
- : ['id', 'name', 'description', 'body'];
180
+ let allowed = ['id', 'name', 'description', 'body'];
181
+ if (kind === 'skill') allowed = ['originalName', 'name', 'description', 'body', 'whenToUse', 'toolDependencies'];
182
+ else if (kind === 'agent') allowed = [...allowed, 'kind'];
174
183
  const unexpected = Object.keys(input).find((key) => !allowed.includes(key));
175
184
  if (unexpected) throw new Error(`${unexpected} is not a ${kind} definition field`);
176
185
  const creating = args.action === 'create_definition';
@@ -200,7 +209,10 @@ async function saveDefinition(rt, args) {
200
209
  const agents = await rt.listAgents();
201
210
  if (agents.some((agent) => agent.id === input.id)) throw new Error(`agent "${input.id}" already exists`);
202
211
  }
203
- return rt.saveAgentDefinition(creating ? next : { ...next, id: current.id });
212
+ if (creating) return rt.saveAgentDefinition({ ...next, kind: createdAgentKind(input, context.caller) });
213
+ // The stored kind is kept as it is; an edit naming one is refused by the editor.
214
+ const { kind: _storedKind, ...edit } = { ...pick(current, definitionKeys), ...input };
215
+ return rt.saveAgentDefinition({ ...edit, ...(own(input, 'kind') ? { kind: input.kind } : {}), id: current.id });
204
216
  }
205
217
  return creating ? rt.addSkill(next) : rt.saveSkill({ ...next, originalName: current.originalName });
206
218
  }
@@ -157,7 +157,17 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
157
157
  name: text,
158
158
  description: text,
159
159
  body: text,
160
- whenToUse: text,
160
+ kind: {
161
+ type: 'string',
162
+ enum: ['bot', 'agent'],
163
+ description:
164
+ 'Agent create only: "bot" (a contact the user chats with) or "agent" (a workflow sub-agent). Omitted: a bot when created from the representative bot\'s chat, else a workflow agent. Fixed after creation.',
165
+ },
166
+ whenToUse: {
167
+ ...text,
168
+ description:
169
+ 'Skill only: the SKILL.md when_to_use trigger line shown in the model\'s skill listing; "" clears it.',
170
+ },
161
171
  toolDependencies: {
162
172
  type: ['array', 'null'],
163
173
  items: object({ type: { type: 'string', enum: ['tool', 'mcp'] }, value: text }, ['type', 'value']),
@@ -232,6 +242,32 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
232
242
  markdownDefaultView: { type: 'string', enum: ['preview', 'rich', 'source'] },
233
243
  linkPreview: boolean,
234
244
  toolActivityExpansion: { type: 'string', enum: ['collapsed', 'commands', 'all'] },
245
+ uiFont: { ...text, description: 'Installed font family for the UI; "" restores the built-in font.' },
246
+ codeFont: { ...text, description: 'Installed font family for code; "" restores the built-in font.' },
247
+ skinTransparency: {
248
+ type: 'integer',
249
+ minimum: 0,
250
+ maximum: 100,
251
+ description: 'Sets both skin transparency sliders at once, 0-100 (defaults: outer 20, main 40).',
252
+ },
253
+ skinOuterTransparency: {
254
+ type: 'integer',
255
+ minimum: 0,
256
+ maximum: 100,
257
+ description:
258
+ 'How much of the skin picture shows through the outer panels (window frame, titlebar, rail, sidebar, side dock), 0-100 (default 20).',
259
+ },
260
+ skinMainTransparency: {
261
+ type: 'integer',
262
+ minimum: 0,
263
+ maximum: 100,
264
+ description:
265
+ 'How much of the skin picture shows through the main panel (conversation area, composer card, status island), 0-100 (default 40).',
266
+ },
267
+ colorTheme: {
268
+ ...text,
269
+ description: 'Imported JSON color theme id from status appearance colorThemes; "builtin" turns themes off.',
270
+ },
235
271
  }),
236
272
  hookRule: object(
237
273
  {
@@ -6,6 +6,7 @@ import {
6
6
  } from './settings-contract.mjs';
7
7
  import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
8
8
  import { INSTRUCTION_FILES_MODES } from '../../runtime/shared/instruction-files-mode.mjs';
9
+ import { AUTO_EFFORT_BASES } from '../../runtime/agent/orchestrator/providers/auto-effort.mjs';
9
10
  import { WORKTREE_NEW_TASK_DEFAULTS } from '../../runtime/shared/worktrees/settings.mjs';
10
11
  import { CONNECTOR_IDS } from '../../runtime/shared/connector-catalog.mjs';
11
12
 
@@ -83,6 +84,7 @@ export const SETUP_ACTION_FIELDS = Object.freeze({
83
84
  set_recap_enabled: 'enabled',
84
85
  set_web_search_enabled: 'enabled',
85
86
  set_instruction_files: 'instructionFiles',
87
+ set_auto_effort_base: 'autoEffortBase',
86
88
  set_builtin_enabled: 'name enabled',
87
89
  install_builtin: 'name',
88
90
  install_local_model: 'modelId',
@@ -160,7 +162,8 @@ const ROUTE_SCHEMA = {
160
162
 
161
163
  ROUTE_SCHEMA.properties.fallbacks = {
162
164
  type: 'array',
163
- description: 'Agent and Web Search routes only: ordered fallback models; [] clears the list.',
165
+ description:
166
+ 'Lead (set_route), agent (bots included) and Web Search routes only: ordered fallback models tried when the model hits its usage limit or is unavailable; [] clears the list.',
164
167
  items: {
165
168
  type: 'object',
166
169
  additionalProperties: false,
@@ -224,8 +227,16 @@ export const SETUP_TOOL_DEFS = Object.freeze([
224
227
  additionalProperties: false,
225
228
  properties: {
226
229
  enabled: { type: 'boolean' },
227
- duration: { type: 'string', description: 'Idle window such as "45m" or "2h"; minimum 1m.' },
228
- provider: { type: 'string', description: 'Scope the duration to one provider.' },
230
+ duration: {
231
+ type: 'string',
232
+ description:
233
+ 'Idle window such as "45m" or "2h" (minimum 1m), or "unlimited"/"never" to stop idle clearing. Without provider, "unlimited" applies to the current route provider.',
234
+ },
235
+ provider: {
236
+ type: 'string',
237
+ description:
238
+ 'Scope the duration to one provider; "default" is the fallback for providers without a built-in window.',
239
+ },
229
240
  reset: { type: 'boolean', description: 'Restore the global idle duration default.' },
230
241
  resetProvider: { type: 'boolean', description: 'Restore the given provider idle duration default.' },
231
242
  minContextPercent: { type: 'number', minimum: 0, maximum: 100 },
@@ -251,6 +262,12 @@ export const SETUP_TOOL_DEFS = Object.freeze([
251
262
  description:
252
263
  "set_instruction_files: which user instruction files new sessions load (global ~/.codex/AGENTS.md, ~/.claude/CLAUDE.md, then the Project root's AGENTS.md/CLAUDE.md).",
253
264
  },
265
+ autoEffortBase: {
266
+ type: 'string',
267
+ enum: [...AUTO_EFFORT_BASES],
268
+ description:
269
+ "set_auto_effort_base: the reasoning effort Auto works around (global; default medium). Auto moves one step down to two steps up from it, within the model's supported efforts.",
270
+ },
254
271
  name: {
255
272
  type: 'string',
256
273
  description: `set_builtin_enabled: ${SETUP_BUILTIN_TOGGLE_FEATURES.join('|')}; install_builtin also accepts memory. Memory toggles use set_memory_enabled. revoke_linked_device: client id from status connection, not its display name; set_developer_option: option id from status developer; read_definition/delete_definition: the definition id; reconnect_mcp: optional MCP server name (omit for all); else MCP/plugin/provider id.`,
@@ -1,8 +1,9 @@
1
1
  // Skill surface (status listing, resource load, tool envelope, global skill
2
2
  // creation/editing). The runtime facade only wires the mutable cwd and the
3
3
  // context module into it.
4
- import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
4
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync } from 'node:fs';
5
5
  import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
6
+ import { holdsNoData, writeFileAtomicSync } from '../runtime/shared/atomic-file.mjs';
6
7
  import { resolvePluginData } from '../runtime/shared/plugin-paths.mjs';
7
8
  import {
8
9
  createSkillDocument,
@@ -21,6 +22,10 @@ import { loadSkillToolDependencies } from '../runtime/agent/orchestrator/runtime
21
22
 
22
23
  const DEFAULT_SKILL_BODY = '# Instructions\n\nDescribe how to use this skill.';
23
24
 
25
+ // SKILL.md is user-authored: written atomically (a crash never leaves it torn
26
+ // or NUL-filled), the replaced copy kept as SKILL.md.bak.
27
+ const writeSkillFile = (filePath, text) => writeFileAtomicSync(filePath, text, { backup: true, mode: 0o644 });
28
+
24
29
  export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
25
30
  const globalSkillsRoot = () => resolve(resolvePluginData(), 'skills');
26
31
 
@@ -114,9 +119,11 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
114
119
  : normalizeSkillToolDependencies(input.toolDependencies, { strict: true });
115
120
  const dir = join(globalSkillsRoot(), name);
116
121
  const filePath = join(dir, 'SKILL.md');
117
- if (existsSync(filePath)) throw new Error(`skill already exists: ${name}`);
122
+ // A SKILL.md holding no data (empty, NUL-filled by a crash) is no skill:
123
+ // creating over it is allowed.
124
+ if (existsSync(filePath) && !holdsNoData(readFileSync(filePath))) throw new Error(`skill already exists: ${name}`);
118
125
  mkdirSync(dir, { recursive: true });
119
- writeFileSync(filePath, createSkillDocument({ name, description, whenToUse, body }), 'utf8');
126
+ writeSkillFile(filePath, createSkillDocument({ name, description, whenToUse, body }));
120
127
  if (dependencies !== undefined) saveSkillToolDependencies(filePath, dependencies);
121
128
  invalidateSkills();
122
129
  return { name, filePath };
@@ -177,13 +184,13 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
177
184
  renameSync(currentDir, nextDir);
178
185
  filePath = join(nextDir, 'SKILL.md');
179
186
  try {
180
- writeFileSync(filePath, updated, 'utf8');
187
+ writeSkillFile(filePath, updated);
181
188
  } catch (error) {
182
189
  renameSync(nextDir, currentDir);
183
190
  throw error;
184
191
  }
185
192
  } else {
186
- writeFileSync(filePath, updated, 'utf8');
193
+ writeSkillFile(filePath, updated);
187
194
  }
188
195
  if (dependencies !== undefined) saveSkillToolDependencies(filePath, dependencies);
189
196
  else if (filePath !== resource.filePath && resource.dependencySource === 'override') {