mixdog 1.3.5 → 1.4.1

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 (515) hide show
  1. package/NOTICE.md +2 -2
  2. package/README.md +2 -2
  3. package/package.json +2 -11
  4. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  5. package/scripts/daemon-stub.mjs +1 -1
  6. package/scripts/gate-local.mjs +16 -5
  7. package/scripts/latest-guard.mjs +21 -9
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +37 -37
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +123 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/native-release-status.mjs +2 -2
  14. package/scripts/post-release-check.mjs +1 -6
  15. package/scripts/pptx-kit-index.mjs +17 -4
  16. package/scripts/recall-history-cases.json +1 -1
  17. package/scripts/suite-health.mjs +20 -2
  18. package/scripts/test-data-dir.mjs +10 -7
  19. package/scripts/test.mjs +7 -11
  20. package/src/agents/reviewer/AGENT.md +7 -11
  21. package/src/agents/reviewer/agent.json +1 -1
  22. package/src/app.mjs +4 -0
  23. package/src/defaults/shipped-history.json +22 -1
  24. package/src/defaults/skills/browser-use/SKILL.md +62 -12
  25. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  26. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  27. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  28. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  29. package/src/defaults/skills/computer-use/SKILL.md +35 -9
  30. package/src/defaults/skills/setup/SKILL.md +22 -0
  31. package/src/defaults/skills/setup/references/actions.md +39 -5
  32. package/src/defaults/skills/setup/references/surfaces.md +11 -2
  33. package/src/defaults/skills/visualize/SKILL.md +2 -1
  34. package/src/lib/rules-builder.cjs +39 -20
  35. package/src/output-styles/common.md +2 -2
  36. package/src/output-styles/simple.md +1 -1
  37. package/src/rules/agent/AGENT.md +11 -10
  38. package/src/rules/lead/LEAD.md +23 -20
  39. package/src/rules/shared/05-tool-calls.md +5 -6
  40. package/src/rules/shared/10-tool-workflow.md +4 -0
  41. package/src/rules/shared/45-destructive.md +0 -2
  42. package/src/rules/shared/50-execution.md +2 -0
  43. package/src/rules/shared/60-verification.md +7 -5
  44. package/src/rules/shared/70-delivery.md +7 -9
  45. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
  46. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  47. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  48. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  49. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  50. package/src/runtime/agent/orchestrator/config.mjs +17 -1
  51. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  52. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
  53. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
  54. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  55. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
  56. package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
  57. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
  58. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
  59. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
  60. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
  62. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  63. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  66. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  67. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  70. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
  71. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  72. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
  73. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  74. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  75. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
  76. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  77. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  78. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  79. package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
  80. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  82. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
  83. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  84. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  85. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  87. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  88. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  89. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  90. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  91. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  92. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  93. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  105. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  106. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  107. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
  109. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  110. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  111. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  112. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  113. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
  117. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  118. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  119. package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
  120. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  121. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  122. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
  123. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  124. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  125. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  126. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
  127. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  129. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  130. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
  131. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  132. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  133. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
  134. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  136. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  137. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  138. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
  139. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  140. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  141. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  142. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
  143. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
  144. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  145. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  146. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
  147. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
  148. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
  149. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
  150. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  151. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
  152. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
  153. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
  154. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
  155. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  158. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
  159. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
  160. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  161. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
  162. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  163. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  164. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
  165. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  166. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
  167. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  168. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  170. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  171. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  172. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  173. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  174. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
  175. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  176. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  177. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
  178. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
  179. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  181. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
  182. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
  183. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
  185. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  187. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
  188. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
  189. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
  190. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  191. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
  192. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  193. package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
  194. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  195. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  196. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  197. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  198. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  199. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  200. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  201. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  203. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  204. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
  209. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  210. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  211. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  212. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  213. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
  214. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  215. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  217. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  218. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  221. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  222. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  224. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  225. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
  226. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
  227. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  228. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
  229. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  231. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  232. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  233. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  234. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  235. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  236. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  237. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  238. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  239. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  240. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  241. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
  243. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  244. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  245. package/src/runtime/browser-bridge/client.mjs +73 -8
  246. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  247. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  248. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  249. package/src/runtime/channels/lib/config.mjs +6 -61
  250. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  251. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  252. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  253. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  254. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  255. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  256. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  257. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  258. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  259. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  260. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  261. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  262. package/src/runtime/channels/lib/scheduler.mjs +33 -147
  263. package/src/runtime/channels/lib/schedules-db.mjs +34 -11
  264. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  265. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
  266. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  267. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  268. package/src/runtime/channels/lib/whisper-port.mjs +10 -1
  269. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  270. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  271. package/src/runtime/channels/lib/worker-main.mjs +10 -34
  272. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  273. package/src/runtime/computer-bridge/actions.mjs +9 -1
  274. package/src/runtime/computer-bridge/client.mjs +180 -8
  275. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  276. package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
  277. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  278. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  279. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  280. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  281. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  282. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  283. package/src/runtime/connectors/google-mcp.mjs +10 -12
  284. package/src/runtime/local-provider/server-process.mjs +2 -1
  285. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  286. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  287. package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
  288. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  289. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  290. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  291. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  292. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  293. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  294. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  295. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  296. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  297. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  298. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  299. package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
  300. package/src/runtime/office/quality/design-review.mjs +1 -5
  301. package/src/runtime/office/quality/document-brief.mjs +1 -5
  302. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  303. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  304. package/src/runtime/session-search/session-search-db.mjs +73 -9
  305. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  306. package/src/runtime/shared/abort-race.mjs +89 -0
  307. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  308. package/src/runtime/shared/agent-kind.mjs +4 -3
  309. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  310. package/src/runtime/shared/bounded-download.mjs +8 -3
  311. package/src/runtime/shared/config.mjs +2 -13
  312. package/src/runtime/shared/connector-accounts.mjs +20 -10
  313. package/src/runtime/shared/connector-catalog.d.mts +29 -0
  314. package/src/runtime/shared/connector-catalog.mjs +150 -0
  315. package/src/runtime/shared/connector-triggers.mjs +22 -19
  316. package/src/runtime/shared/defaults-separation.mjs +2 -17
  317. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  318. package/src/runtime/shared/err-text.mjs +24 -15
  319. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  320. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  321. package/src/runtime/shared/file-permissions.d.mts +0 -8
  322. package/src/runtime/shared/file-permissions.mjs +0 -11
  323. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  324. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  325. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  326. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  327. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  328. package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
  329. package/src/runtime/shared/llm/cost.mjs +5 -1
  330. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  331. package/src/runtime/shared/loopback-listener.mjs +25 -2
  332. package/src/runtime/shared/mixy-presence.mjs +22 -0
  333. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  334. package/src/runtime/shared/model-route-chain.mjs +22 -4
  335. package/src/runtime/shared/open-url.mjs +10 -0
  336. package/src/runtime/shared/orchestration.d.mts +2 -0
  337. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  338. package/src/runtime/shared/profile-config.cjs +1 -1
  339. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  340. package/src/runtime/shared/prompt-origin.mjs +21 -0
  341. package/src/runtime/shared/provider-accounts.mjs +7 -1
  342. package/src/runtime/shared/provider-display-name.mjs +29 -0
  343. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  344. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  345. package/src/runtime/shared/routine-trigger.mjs +10 -0
  346. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  347. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  348. package/src/runtime/shared/session-activity-signal.mjs +48 -1
  349. package/src/runtime/shared/session-scratch.mjs +37 -0
  350. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  351. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  352. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  353. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  354. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  355. package/src/runtime/shared/tool-result-summary.mjs +2 -15
  356. package/src/runtime/shared/tool-surface.mjs +3 -0
  357. package/src/runtime/shared/tool-work-units.mjs +2 -0
  358. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  359. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  360. package/src/runtime/shared/worktrees/git.mjs +15 -0
  361. package/src/runtime/shared/worktrees/manager.mjs +87 -38
  362. package/src/runtime/shared/worktrees/test-support.mjs +14 -13
  363. package/src/runtime/terminal-bridge/client.mjs +10 -1
  364. package/src/runtime/visualize-bridge/client.mjs +29 -8
  365. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  366. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  367. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  368. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  369. package/src/session-runtime/agent-home-delivery.mjs +489 -185
  370. package/src/session-runtime/agent-task-sessions.mjs +467 -229
  371. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  372. package/src/session-runtime/boot/apis.mjs +9 -0
  373. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  374. package/src/session-runtime/boot/providers.mjs +3 -0
  375. package/src/session-runtime/boot/tools.mjs +11 -2
  376. package/src/session-runtime/bot-status.mjs +12 -6
  377. package/src/session-runtime/bot-target.mjs +38 -0
  378. package/src/session-runtime/channel-config-api.mjs +6 -1
  379. package/src/session-runtime/config-lifecycle.mjs +6 -0
  380. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  381. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  382. package/src/session-runtime/conversation-import/discovery.mjs +271 -25
  383. package/src/session-runtime/conversation-import/service.mjs +26 -5
  384. package/src/session-runtime/handoff-attachments.mjs +82 -31
  385. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
  386. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
  387. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  388. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
  389. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  390. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  391. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  392. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  393. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  394. package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
  395. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  396. package/src/session-runtime/mixy-heartbeat.mjs +153 -33
  397. package/src/session-runtime/model-route/set-route.mjs +11 -2
  398. package/src/session-runtime/notification-bus.mjs +31 -117
  399. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  400. package/src/session-runtime/notification-listeners.mjs +76 -0
  401. package/src/session-runtime/owned-automation-run.mjs +2 -1
  402. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  403. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  404. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  405. package/src/session-runtime/provider-models.mjs +4 -2
  406. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  407. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  408. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  409. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  410. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  411. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  412. package/src/session-runtime/resource-recall-api.mjs +6 -1
  413. package/src/session-runtime/routine-owner.mjs +40 -9
  414. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  415. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  416. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  417. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  418. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  419. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  420. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
  421. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  422. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  423. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  424. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  425. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  426. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  427. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  428. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  429. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  430. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  431. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  432. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  433. package/src/session-runtime/services/channel-admin.mjs +7 -13
  434. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  435. package/src/session-runtime/services/provider-admin.mjs +2 -1
  436. package/src/session-runtime/services/seeds.mjs +0 -28
  437. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  438. package/src/session-runtime/session-create/session-options.mjs +1 -0
  439. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  440. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  441. package/src/session-runtime/settings-system-api.mjs +13 -1
  442. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  443. package/src/session-runtime/setup-tool/executor.mjs +145 -22
  444. package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
  445. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  446. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
  447. package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
  448. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  449. package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
  450. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  451. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  452. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
  453. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  454. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  455. package/src/session-runtime/workspace/transitions.mjs +25 -0
  456. package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
  457. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  458. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  459. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  460. package/src/standalone/channel-transport.mjs +1 -1
  461. package/src/standalone/daemon-channels-loader.mjs +10 -8
  462. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  463. package/src/standalone/daemon-session-control/request.mjs +51 -0
  464. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  465. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  466. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  467. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  468. package/src/standalone/daemon-session-control.mjs +142 -190
  469. package/src/standalone/daemon.mjs +26 -3
  470. package/src/standalone/session-client.mjs +7 -3
  471. package/src/standalone/session-protocol.mjs +5 -0
  472. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  473. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  474. package/src/standalone/session-service/quota-resume.mjs +3 -0
  475. package/src/standalone/session-service/retention/busy.mjs +65 -1
  476. package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
  477. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  478. package/src/standalone/session-tool-output.mjs +15 -7
  479. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  480. package/src/tui/app/app-view/floating-panel.jsx +7 -4
  481. package/src/tui/app/model-options.mjs +3 -28
  482. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  483. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  484. package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
  485. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  486. package/src/tui/app/provider-setup-picker.mjs +9 -5
  487. package/src/tui/components/QuestionPanel.jsx +13 -4
  488. package/src/tui/dist/index.mjs +133 -92
  489. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  490. package/src/tui/session/initial-state.mjs +3 -0
  491. package/src/tui/session/notice-surface.mjs +7 -1
  492. package/src/tui/session/queue-helpers.mjs +3 -42
  493. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  494. package/src/tui/session/session-api/routes-write.mjs +5 -1
  495. package/src/tui/session/session-api/routes.mjs +1 -0
  496. package/src/tui/session/session-api/settings.mjs +17 -1
  497. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  498. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  499. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  500. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  501. package/src/tui/session/session-flow/drain.mjs +118 -149
  502. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  503. package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
  504. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  505. package/src/tui/session/tool-approval-request.mjs +39 -0
  506. package/src/tui/session/tool-approval-settle.mjs +62 -0
  507. package/src/tui/session/tool-approval.mjs +69 -115
  508. package/src/tui/session/tui-steering-persist.mjs +8 -1
  509. package/src/tui/session/turn-stream.mjs +19 -2
  510. package/src/tui/session/turn.mjs +1 -0
  511. package/src/ui/statusline-agents.mjs +1 -3
  512. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  513. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  514. package/scripts/code-graph-description-contract.mjs +0 -188
  515. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -1,6 +1,7 @@
1
1
  // Rule-based Compact preserves conversation verbatim by default. A bounded
2
2
  // cumulative handoff replaces only the conversation part when requested by
3
3
  // its independent threshold policy.
4
+ import { createHash } from 'node:crypto';
4
5
  import { estimateMessagesTokens, reconcileDedupStubs, sanitizeToolPairs } from '../context-utils.mjs';
5
6
  import { HANDOFF_TIMEOUT_MAX_MS, SUMMARY_OUTPUT_TOKENS, compactDebugLog } from './constants.mjs';
6
7
  import {
@@ -11,6 +12,7 @@ import {
11
12
  textByteLength,
12
13
  } from './text-utils.mjs';
13
14
  import {
15
+ callArguments,
14
16
  contextAckMessage,
15
17
  isCompactConversationRow,
16
18
  isProtectedContextAckMessage,
@@ -22,8 +24,9 @@ import {
22
24
  } from './messages.mjs';
23
25
  import { activeTurnContinuationMessage } from './continuation.mjs';
24
26
  import { EXECUTION_RECOVERY_SOURCE, buildExecutionTail } from './execution-tail.mjs';
25
- import { latestSkillBodies } from '../../context/skill-state.mjs';
27
+ import { latestSkillBodies, skillMessageText } from '../../context/skill-state.mjs';
26
28
  import { effectiveBudget } from './budget.mjs';
29
+ import { parseMcpToolName } from '../../../../shared/tool-primitives.mjs';
27
30
  import { stripRuntimeUserContext, withRuntimeUserContext } from '../runtime-user-context.mjs';
28
31
  import { carryMessageId, messageIdOf } from '../message-ids.mjs';
29
32
  import { normalizeIngestRole, shouldExcludeIngestMessage } from '../../../../memory/lib/session-ingest.mjs';
@@ -69,12 +72,23 @@ function splitFreshSource(messages) {
69
72
  break;
70
73
  }
71
74
  }
75
+ // Where the previous Compact's skill-use window opens: `live` index after
76
+ // the history it kept (see SKILL_WINDOW_SOURCE). Without a marker the whole
77
+ // transcript is the window.
78
+ const isKept = (message) => !isSummaryMessage(message) && message?.meta?.source !== SKILL_WINDOW_SOURCE;
79
+ const markerAt = conversation.findLastIndex((message) => message?.meta?.source === SKILL_WINDOW_SOURCE);
80
+ const span = conversation[markerAt]?.meta?.span;
81
+ const skillWindowStart =
82
+ markerAt >= 0 && Number.isInteger(span) && span >= 0
83
+ ? conversation.slice(0, markerAt).filter(isKept).length + span
84
+ : 0;
72
85
  const latestUserIndex = latestActualUserInstructionIndex(conversation);
73
86
  return {
74
87
  protectedPrefix,
75
88
  previousSummary: previousSummaryMessage?.content || null,
76
89
  previousSummaryMessage,
77
90
  previousAck,
91
+ skillWindowStart,
78
92
  // Budgeting, AI input and rule-only retention use this same projection.
79
93
  // Keep current-turn reminders; remove only proven runtime additions from
80
94
  // older requests. Unmarked legacy text remains part of the summary budget.
@@ -85,7 +99,7 @@ function splitFreshSource(messages) {
85
99
  .map((message, index) =>
86
100
  index === latestUserIndex ? message : referenceMessageMedia(stripRuntimeUserContext(message))
87
101
  )
88
- .filter((message) => !isSummaryMessage(message)),
102
+ .filter(isKept),
89
103
  sanitized,
90
104
  };
91
105
  }
@@ -134,9 +148,11 @@ function toolCallSummaryLine(call, result) {
134
148
  // Arguments arrive redacted (splitFreshSource); the outcome is redacted
135
149
  // here, before any cut can split a secret from its key.
136
150
  const outcome = redactRawSecretString(contentText(result?.content)).trim();
137
- // An ask_user result is the user's own answer: never cut.
151
+ // An ask_user or handoff_user result is the user's own answer: never cut.
138
152
  const shown =
139
- call.name === 'ask_user' ? outcome : boundedSummaryText(outcome.replace(/\s+/g, ' '), SUMMARY_TOOL_OUTCOME_CHARS);
153
+ call.name === 'ask_user' || call.name === 'handoff_user'
154
+ ? outcome
155
+ : boundedSummaryText(outcome.replace(/\s+/g, ' '), SUMMARY_TOOL_OUTCOME_CHARS);
140
156
  return `[tool call] ${call.name}(${args}) → ${result ? shown || '(empty result)' : '(no result)'}`;
141
157
  }
142
158
 
@@ -413,6 +429,47 @@ function prependLatestUserContext(message, prefix) {
413
429
  });
414
430
  }
415
431
 
432
+ const LOADED_SKILL_RESULT_RE = /^Loaded (?:built-in )?skill: /;
433
+
434
+ // A Skill load the retained execution tail keeps states what the skill
435
+ // delivered then: its tool list (the native payload or the summary text). It
436
+ // is brought to what the skill delivers now, in place, so its call stays
437
+ // paired: a skill that no longer loads keeps a result saying so, with no tool
438
+ // payload; a skill whose dependencies changed carries its current payload.
439
+ // Failed loads (errors) are left as they are. `currentSkill` absent, or a
440
+ // skill's `native` undefined (a preview), keeps the result.
441
+ function reconcileRetainedSkillLoads(messages, currentSkill) {
442
+ if (!currentSkill) return messages;
443
+ const calls = new Map(
444
+ messages.flatMap((message) =>
445
+ message?.role === 'assistant' ? (message.toolCalls || []).map((call) => [call.id, call]) : []
446
+ )
447
+ );
448
+ const withoutPayload = ({ nativeToolSearch: _native, ...message }, content) => ({ ...message, content });
449
+ return messages.map((message) => {
450
+ if (message?.role !== 'tool') return message;
451
+ const call = calls.get(message.toolCallId);
452
+ const name = call?.name === 'Skill' ? String(call.arguments?.name || '').trim() : '';
453
+ if (!name) return message;
454
+ const text = contentText(message.content);
455
+ if (!message.nativeToolSearch && !LOADED_SKILL_RESULT_RE.test(text)) return message;
456
+ const skill = currentSkill(name);
457
+ if (skill === null) {
458
+ return withoutPayload(
459
+ message,
460
+ `Skill "${name}" is no longer available in this session (switched off, removed, or outside this project's scope); its instructions and tools are not active.`
461
+ );
462
+ }
463
+ if (skill?.native === undefined) return message;
464
+ if (skill.native) {
465
+ return nativeToolsKey(message.nativeToolSearch) === nativeToolsKey(skill.native)
466
+ ? message
467
+ : { ...message, content: skill.native.summary, nativeToolSearch: skill.native };
468
+ }
469
+ return !message.nativeToolSearch && text === skill.summary ? message : withoutPayload(message, skill.summary);
470
+ });
471
+ }
472
+
416
473
  // The retained execution tail plus the current-turn messages that must
417
474
  // survive every compaction verbatim.
418
475
  function freshContextTail(source, budgetTokens, preserveConversation, opts) {
@@ -423,10 +480,11 @@ function freshContextTail(source, budgetTokens, preserveConversation, opts) {
423
480
  preview: opts.preview === true,
424
481
  });
425
482
  const latestUser = latestActualUserInstructionMessage(source.live);
426
- const latestIndex = execution.messages.findLastIndex(
483
+ const executed = reconcileRetainedSkillLoads(execution.messages, opts.currentSkill);
484
+ const latestIndex = executed.findLastIndex(
427
485
  (message) => message.role === 'user' && message.content === latestUser?.content
428
486
  );
429
- const retainedTail = execution.messages.map((message, index) =>
487
+ const retainedTail = executed.map((message, index) =>
430
488
  index === latestIndex ? prependLatestUserContext(message, opts.latestUserPrefix) : message
431
489
  );
432
490
  // The turn's input: the latest real request or an unanswered notification
@@ -459,11 +517,9 @@ function freshContextTail(source, budgetTokens, preserveConversation, opts) {
459
517
  };
460
518
  }
461
519
 
462
- // Native tool search exposes a skill's linked tools only through the executed
463
- // Skill result that referenced them. A restored body keeps that pair, unless
464
- // the retained tail already carries it, so its instructions never return
465
- // without the tools they require.
466
- function skillLoaderPair(live, bodyIndex, name, retainedCallIds) {
520
+ // The executed Skill call (its owner message, the call and its result) that
521
+ // delivered the body at `bodyIndex`, or null.
522
+ function skillLoader(live, bodyIndex, name) {
467
523
  for (let index = bodyIndex - 1; index >= 0; index -= 1) {
468
524
  const result = live[index];
469
525
  if (result?.role !== 'tool') continue;
@@ -473,65 +529,211 @@ function skillLoaderPair(live, bodyIndex, name, retainedCallIds) {
473
529
  (message) => message?.role === 'assistant' && message.toolCalls?.some((c) => c.id === result.toolCallId)
474
530
  );
475
531
  const call = owner?.toolCalls.find((entry) => entry.id === result.toolCallId);
476
- if (call?.name !== 'Skill' || call.arguments?.name !== name) continue;
477
- if (!result.nativeToolSearch || retainedCallIds.has(result.toolCallId)) return [];
478
- // The re-attached call is part of its owner message: it keeps that id.
479
- return [carryMessageId({ role: 'assistant', content: '', toolCalls: [call] }, owner), result];
532
+ if (call?.name === 'Skill' && call.arguments?.name === name) return { owner, call, result };
480
533
  }
481
- return [];
534
+ return null;
535
+ }
536
+
537
+ const nativeToolsKey = (native) =>
538
+ JSON.stringify([native?.provider || '', native?.toolReferences || [], native?.openaiTools || []]);
539
+
540
+ const SKILL_RESTORE_SOURCE = 'compact-skill-restore';
541
+
542
+ // Native tool search exposes a skill's linked tools only through the executed
543
+ // Skill result that referenced them. A restored body keeps that pair, unless
544
+ // the retained tail already carries it, so its instructions never return
545
+ // without the tools they require. `current.native` is the payload the skill's
546
+ // current dependencies produce (null: none to expose); the transcript pair is
547
+ // kept while it matches, otherwise rebuilt from it. `current` absent, or its
548
+ // `native` undefined, keeps the transcript pair as it is.
549
+ function skillLoaderPair(live, bodyIndex, name, retainedCallIds, current) {
550
+ const loader = skillLoader(live, bodyIndex, name);
551
+ if (loader && retainedCallIds.has(loader.result.toolCallId)) return [];
552
+ const native = current?.native === undefined ? loader?.result.nativeToolSearch : current.native;
553
+ if (!native) return [];
554
+ // The re-attached call is part of its owner message: it keeps that id.
555
+ const callMessage = (call) =>
556
+ loader
557
+ ? carryMessageId({ role: 'assistant', content: '', toolCalls: [call] }, loader.owner)
558
+ : { role: 'assistant', content: '', toolCalls: [call], meta: { source: SKILL_RESTORE_SOURCE, synthetic: true } };
559
+ if (loader?.result.nativeToolSearch && nativeToolsKey(loader.result.nativeToolSearch) === nativeToolsKey(native)) {
560
+ return [callMessage(loader.call), loader.result];
561
+ }
562
+ // A body that arrived without a native pair still needs one now: a
563
+ // per-skill call id, stable across later Compacts that keep it.
564
+ const call = loader?.call || {
565
+ id: `skill-restore-${createHash('sha256').update(name).digest('hex').slice(0, 24)}`,
566
+ name: 'Skill',
567
+ arguments: { name },
568
+ };
569
+ const result = { role: 'tool', toolCallId: call.id, content: native.summary, nativeToolSearch: native };
570
+ return [callMessage(call), loader ? carryMessageId(result, loader.result) : result];
571
+ }
572
+
573
+ // The body to restore: the transcript copy while it is what the Skill tool
574
+ // delivers now, else the current body.
575
+ function currentSkillBodyMessage(message, current) {
576
+ if (!current || skillMessageText(message.content).trimStart() === current.body) return message;
577
+ return { role: 'user', content: current.body, meta: 'skill' };
482
578
  }
483
579
 
484
580
  const SKILL_RELOAD_SOURCE = 'compact-skill-reload';
485
581
 
486
- function skillReloadReminder(name) {
582
+ // How many Compacts in a row a skill may go unused before even its reload
583
+ // line is dropped: a skill untouched that long belongs to finished work, and
584
+ // the model can still load it by name from the skill manifest.
585
+ export const SKILL_RELOAD_MAX_IDLE = 3;
586
+
587
+ const SKILL_TOOL_NAMES = new Set(['Skill', 'skill_view']);
588
+
589
+ function skillReloadReminder(name, idle = 0) {
487
590
  return {
488
591
  role: 'user',
489
- content: `[mixdog-runtime] Skill "${name}" was active, but its instructions did not fit after Compact. Reload it with the Skill tool before relying on them.`,
490
- meta: { source: SKILL_RELOAD_SOURCE, synthetic: true, skill: name },
592
+ content: `[mixdog-runtime] Skill "${name}" was active earlier, but Compact did not keep its instructions. Reload it with the Skill tool before relying on them.`,
593
+ meta: { source: SKILL_RELOAD_SOURCE, synthetic: true, skill: name, idle },
491
594
  };
492
595
  }
493
596
 
494
- // Preserve complete, most-recent skill bodies from the durable transcript.
597
+ // Every Compact leaves this marker just ahead of the skills it restores, with
598
+ // `span`: how many messages follow it (restored skills and retained tail).
599
+ // All of them happened before that Compact, so the next one reads the skill
600
+ // use window from after them, whether or not a summary exists. The marker is
601
+ // not conversation: the next Compact removes it and writes a new one.
602
+ const SKILL_WINDOW_SOURCE = 'compact-skill-window';
603
+
604
+ function skillWindowMarker(span = 0) {
605
+ return {
606
+ role: 'user',
607
+ content: '[mixdog-runtime] Compact boundary.',
608
+ meta: { source: SKILL_WINDOW_SOURCE, synthetic: true, span },
609
+ };
610
+ }
611
+
612
+ // Restore the skills the session used since the previous Compact, each as the
613
+ // Skill tool would deliver it now. A skill is used when it was loaded or one of
614
+ // its linked tools ran in that window (`windowStart` onward); its linked
615
+ // tools are the native tool references of its loader pair and, when the
616
+ // resolver gives them, `tools`. `currentSkill(name)` (the caller's resolver)
617
+ // answers `{ body, native, summary, tools? }` for a skill that still loads in
618
+ // the session, or null for one switched off, outside its scope or removed:
619
+ // such a skill is restored neither as a body nor as a reload line, since its
620
+ // instructions are no longer in force. Without a resolver the transcript
621
+ // copies are kept.
495
622
  // Never summarize/truncate operating instructions or displace the handoff
496
- // and current task. An omitted body leaves a one-line reload reminder, which
497
- // stands through later Compacts until the skill is loaded again. Reminders
498
- // are charged to the same budget: every skill's reminder is reserved before
499
- // any body is restored, and restoring a body releases its own reminder.
500
- function restoreSkillBodies(live, skillBudget, retainedTail) {
623
+ // and current task. Every other active skill, and a used one whose body does
624
+ // not fit, is left as a one-line reload line. The line counts the Compacts
625
+ // the skill went unused (`meta.idle`) and is dropped past SKILL_RELOAD_MAX_IDLE.
626
+ // Reload lines are charged to the same budget: every possible line is
627
+ // reserved before any body is restored, and restoring a body releases its own.
628
+ function restoreSkillBodies(live, skillBudget, retainedTail, currentSkill = null, windowStart = 0) {
501
629
  const retainedCallIds = new Set(retainedTail.filter((m) => m?.role === 'tool').map((m) => m.toolCallId));
502
- const bodies = latestSkillBodies(live);
503
- const loaded = new Set(bodies.map((body) => body.name));
504
- const reload = live
505
- .filter((m) => m?.meta?.source === SKILL_RELOAD_SOURCE && !loaded.has(m.meta.skill))
506
- .map((m) => m.meta.skill);
507
- const reminderCost = (name) => estimateMessagesTokens([skillReloadReminder(name)]);
508
- let reserved = [...new Set([...reload, ...loaded])].reduce((sum, name) => sum + reminderCost(name), 0);
509
- const dropped = [];
630
+ const current = (name) => (currentSkill ? currentSkill(name) : undefined);
631
+ const loads = (name) => current(name) !== null;
632
+ const transcriptBodies = latestSkillBodies(live);
633
+ const loaded = new Set(transcriptBodies.map((body) => body.name));
634
+ const bodies = transcriptBodies.filter((body) => loads(body.name));
635
+ // Reload lines from earlier Compacts: skill -> Compacts it went unused.
636
+ const earlier = new Map();
637
+ for (const m of live) {
638
+ if (m?.meta?.source !== SKILL_RELOAD_SOURCE || loaded.has(m.meta.skill) || !loads(m.meta.skill)) continue;
639
+ earlier.delete(m.meta.skill);
640
+ earlier.set(m.meta.skill, Number.isFinite(m.meta.idle) ? m.meta.idle : 0);
641
+ }
642
+
643
+ // A loader pair can sit anywhere in the transcript (a restored body stays
644
+ // ahead of the retained tail's pair), so read them all.
645
+ const results = new Map(live.filter((m) => m?.role === 'tool').map((m) => [m.toolCallId, m]));
646
+ const loaderTools = new Map();
647
+ for (const message of live) {
648
+ for (const call of message?.role === 'assistant' ? message.toolCalls || [] : []) {
649
+ const references = results.get(call.id)?.nativeToolSearch?.toolReferences;
650
+ if (call.name !== 'Skill' || !references) continue;
651
+ const name = String(callArguments(call).name || '').trim();
652
+ loaderTools.set(name, [...(loaderTools.get(name) || []), ...references]);
653
+ }
654
+ }
655
+ const skillsOfTool = new Map();
656
+ for (const name of new Set([...earlier.keys(), ...bodies.map((body) => body.name)])) {
657
+ const skill = current(name);
658
+ const tools = [...(skill?.native?.toolReferences || []), ...(skill?.tools || []), ...(loaderTools.get(name) || [])];
659
+ for (const tool of tools) skillsOfTool.set(tool, (skillsOfTool.get(tool) || new Set()).add(name));
660
+ }
661
+ // Use since the previous Compact (from `windowStart`): the newest transcript
662
+ // position of a load or of a linked tool's call.
663
+ const lastUse = new Map();
664
+ const noteUse = (name, index) => lastUse.set(name, Math.max(lastUse.get(name) ?? -1, index));
665
+ live.forEach((message, index) => {
666
+ if (index < windowStart || message?.role !== 'assistant') return;
667
+ for (const call of message.toolCalls || []) {
668
+ const args = callArguments(call);
669
+ if (SKILL_TOOL_NAMES.has(call.name)) noteUse(String(args.name || '').trim(), index);
670
+ else {
671
+ const tool = call.name === 'call_tool' ? args.name : call.name;
672
+ const mcpServer = `mcp:${parseMcpToolName(tool)?.server}`;
673
+ for (const name of [...(skillsOfTool.get(tool) || []), ...(skillsOfTool.get(mcpServer) || [])]) {
674
+ noteUse(name, index);
675
+ }
676
+ }
677
+ }
678
+ });
679
+ for (const { name, message } of bodies) {
680
+ const index = live.lastIndexOf(message);
681
+ if (index >= windowStart) noteUse(name, index);
682
+ }
683
+
684
+ // Every active skill without a body ends as a reload line: an unused one
685
+ // ages by a Compact and goes once past the bound; one used (or whose body
686
+ // did not fit) starts over.
687
+ const reminders = new Map();
688
+ for (const [name, idle] of earlier) {
689
+ if (lastUse.has(name)) reminders.set(name, 0);
690
+ else if (idle < SKILL_RELOAD_MAX_IDLE) reminders.set(name, idle + 1);
691
+ }
692
+ const used = bodies.filter(({ name }) => lastUse.has(name)).sort((a, b) => lastUse.get(b.name) - lastUse.get(a.name));
693
+ const unused = bodies.filter(({ name }) => !lastUse.has(name));
694
+
695
+ const reminderCost = (name, idle = 0) => estimateMessagesTokens([skillReloadReminder(name, idle)]);
696
+ let reserved =
697
+ [...reminders].reduce((sum, [name, idle]) => sum + reminderCost(name, idle), 0) +
698
+ unused.reduce((sum, { name }) => sum + reminderCost(name, 1), 0) +
699
+ used.reduce((sum, { name }) => sum + reminderCost(name), 0);
700
+ const dropped = new Set();
510
701
  const restoredSkills = [];
511
702
  let skillTokens = 0;
512
- for (const { name, message } of bodies.reverse()) {
513
- const restored = [...skillLoaderPair(live, live.lastIndexOf(message), name, retainedCallIds), message];
703
+ for (const { name, message } of used) {
704
+ const skill = current(name);
705
+ const restored = [
706
+ ...skillLoaderPair(live, live.lastIndexOf(message), name, retainedCallIds, skill),
707
+ currentSkillBodyMessage(message, skill),
708
+ ];
514
709
  const cost = estimateMessagesTokens(restored);
515
710
  const own = reminderCost(name);
516
711
  if (skillTokens + cost + reserved - own > skillBudget) {
517
- dropped.unshift(name);
712
+ dropped.add(name);
518
713
  continue;
519
714
  }
520
715
  restoredSkills.unshift(...restored);
521
716
  skillTokens += cost;
522
717
  reserved -= own;
523
718
  }
524
- // Newest skill first; only a budget too small for the reminders themselves
719
+ // In transcript order, after the lines of earlier Compacts.
720
+ for (const { name } of bodies) {
721
+ if (!lastUse.has(name)) reminders.set(name, 1);
722
+ else if (dropped.has(name)) reminders.set(name, 0);
723
+ }
724
+ // Newest skill first; only a budget too small for the lines themselves
525
725
  // leaves one out.
526
- const pending = [...new Set([...reload, ...dropped])];
726
+ const pending = [...reminders];
527
727
  const reminded = new Set();
528
- for (const name of pending.toReversed()) {
529
- const cost = reminderCost(name);
728
+ for (const [name, idle] of pending.toReversed()) {
729
+ const cost = reminderCost(name, idle);
530
730
  if (skillTokens + cost > skillBudget) continue;
531
731
  reminded.add(name);
532
732
  skillTokens += cost;
533
733
  }
534
- restoredSkills.push(...pending.filter((name) => reminded.has(name)).map(skillReloadReminder));
734
+ restoredSkills.push(
735
+ ...pending.filter(([name]) => reminded.has(name)).map(([name, idle]) => skillReloadReminder(name, idle))
736
+ );
535
737
  return { restoredSkills, skillTokens };
536
738
  }
537
739
 
@@ -716,7 +918,19 @@ function assertHandoffFits(summaryMessage, room) {
716
918
  }
717
919
  }
718
920
 
719
- export function freshContextCompactMessages(messages, budgetTokens, opts = {}) {
921
+ // One resolution per skill per Compact: the retained tail and the restored
922
+ // bodies read the same answer (the real pass re-arms dependencies once).
923
+ function memoizedSkillResolver(resolve) {
924
+ if (!resolve) return null;
925
+ const known = new Map();
926
+ return (name) => {
927
+ if (!known.has(name)) known.set(name, resolve(name));
928
+ return known.get(name);
929
+ };
930
+ }
931
+
932
+ export function freshContextCompactMessages(messages, budgetTokens, options = {}) {
933
+ const opts = { ...options, currentSkill: memoizedSkillResolver(options.currentSkill) };
720
934
  const startedAt = Date.now();
721
935
  const targetBudget = effectiveBudget(budgetTokens, opts);
722
936
  const baseSanitized = reconcileDedupStubs(sanitizeToolPairs(messages));
@@ -756,12 +970,33 @@ export function freshContextCompactMessages(messages, budgetTokens, opts = {}) {
756
970
  const summaryContent = String(summaryMessage?.content || '');
757
971
  assertHandoffFits(summaryMessage, handoff.room);
758
972
  const skillBudget = freshSkillBudget(targetBudget, budget, [...stableHead, ...tail.volatileTail]);
759
- const skills = { ...restoreSkillBodies(source.live, skillBudget, tail.volatileTail), skillBudget };
760
- const stablePrefixMessages = [...stableHead, ...skills.restoredSkills];
761
- const result = rebaseCompactedEffortConfiguration(
973
+ // Restored skills carry the window marker, which is charged to their budget.
974
+ const markerCost = estimateMessagesTokens([skillWindowMarker()]);
975
+ const skills = {
976
+ ...restoreSkillBodies(
977
+ source.live,
978
+ Math.max(0, skillBudget - markerCost),
979
+ tail.volatileTail,
980
+ opts.currentSkill,
981
+ source.skillWindowStart
982
+ ),
983
+ skillBudget,
984
+ };
985
+ // A session with no skill state has no use to window: no marker.
986
+ const marker = skills.restoredSkills.length ? [skillWindowMarker()] : [];
987
+ const stablePrefixMessages = [...stableHead, ...marker, ...skills.restoredSkills];
988
+ const compacted = rebaseCompactedEffortConfiguration(
762
989
  baseSanitized,
763
990
  reconcileDedupStubs(sanitizeToolPairs([...stablePrefixMessages, ...tail.volatileTail]))
764
991
  );
992
+ // The next Compact reads everything after the marker as history, not as use.
993
+ const markerAt = compacted.findLastIndex((message) => message?.meta?.source === SKILL_WINDOW_SOURCE);
994
+ const result =
995
+ markerAt < 0
996
+ ? compacted
997
+ : compacted.map((message, index) =>
998
+ index === markerAt ? skillWindowMarker(compacted.length - markerAt - 1) : message
999
+ );
765
1000
  const finalTokens = estimateMessagesTokens(result);
766
1001
  if (finalTokens > budget) {
767
1002
  throw new Error(`freshContextCompactMessages: compacted result exceeds budget=${budget} (result=${finalTokens})`);