mixdog 0.9.152 → 0.9.154

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 (300) hide show
  1. package/LICENSES/browser-import-NOTICE.txt +11 -0
  2. package/NOTICE.md +11 -0
  3. package/README.md +8 -10
  4. package/package.json +19 -3
  5. package/scripts/computer-task-cost-report.mjs +144 -0
  6. package/scripts/run-office-live-tests.mjs +32 -0
  7. package/src/agents/front-worker/AGENT.md +13 -0
  8. package/src/agents/front-worker/agent.json +6 -0
  9. package/src/agents/heavy-worker/AGENT.md +10 -11
  10. package/src/agents/heavy-worker/agent.json +1 -1
  11. package/src/agents/maintainer/AGENT.md +0 -2
  12. package/src/agents/reviewer/AGENT.md +9 -13
  13. package/src/agents/reviewer/agent.json +1 -1
  14. package/src/agents/security/AGENT.md +14 -0
  15. package/src/agents/security/agent.json +6 -0
  16. package/src/agents/worker/AGENT.md +8 -8
  17. package/src/agents/worker/agent.json +1 -1
  18. package/src/agents/writer/AGENT.md +14 -0
  19. package/src/agents/writer/agent.json +6 -0
  20. package/src/rules/agent/00-common.md +4 -7
  21. package/src/rules/lead/01-general.md +0 -3
  22. package/src/rules/shared/10-tool-workflow.md +10 -2
  23. package/src/rules/shared/60-verification.md +2 -0
  24. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +183 -26
  25. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +4 -0
  26. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +109 -0
  27. package/src/runtime/agent/orchestrator/config.mjs +7 -2
  28. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +16 -3
  29. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -1
  30. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +30 -9
  31. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +18 -26
  32. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +25 -2
  33. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +103 -10
  34. package/src/runtime/agent/orchestrator/providers/openai-turn-state.mjs +68 -0
  35. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +36 -11
  36. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +140 -86
  37. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +9 -13
  38. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +72 -4
  39. package/src/runtime/agent/orchestrator/session/browser-snapshot-supersession.mjs +61 -0
  40. package/src/runtime/agent/orchestrator/session/compact/handoff.mjs +0 -22
  41. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -2
  42. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +11 -23
  43. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +28 -269
  44. package/src/runtime/agent/orchestrator/session/compact.mjs +0 -6
  45. package/src/runtime/agent/orchestrator/session/context-utils.mjs +86 -11
  46. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +17 -1
  47. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +12 -8
  48. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +110 -2
  49. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +3 -16
  50. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +80 -18
  51. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +6 -0
  52. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +3 -0
  53. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +6 -0
  54. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +80 -21
  55. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +33 -72
  56. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +21 -2
  57. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +25 -51
  58. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +3 -0
  59. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -110
  60. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +39 -15
  61. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +14 -4
  62. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +41 -8
  63. package/src/runtime/agent/orchestrator/session/provider-prefix-guard.mjs +129 -12
  64. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +2 -2
  65. package/src/runtime/agent/orchestrator/session/store/listing.mjs +8 -1
  66. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +15 -1
  67. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +36 -2
  68. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +157 -30
  69. package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +57 -0
  70. package/src/runtime/agent/orchestrator/session/store.mjs +3 -1
  71. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +22 -0
  72. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +6 -6
  73. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +4 -0
  74. package/src/runtime/attachments/pdf-extract.mjs +3 -0
  75. package/src/runtime/attachments/pdfjs-runtime.mjs +13 -0
  76. package/src/runtime/browser-bridge/action-schema.mjs +251 -0
  77. package/src/runtime/browser-bridge/client.mjs +75 -26
  78. package/src/runtime/browser-bridge/tool-defs.mjs +132 -15
  79. package/src/runtime/computer-bridge/action-schema.mjs +653 -0
  80. package/src/runtime/computer-bridge/client.mjs +211 -28
  81. package/src/runtime/computer-bridge/tool-defs.mjs +25 -45
  82. package/src/runtime/office/assurance-benchmark.mjs +358 -0
  83. package/src/runtime/office/assurance.mjs +833 -0
  84. package/src/runtime/office/benchmark.mjs +496 -0
  85. package/src/runtime/office/capabilities.mjs +551 -0
  86. package/src/runtime/office/com-adapter.mjs +283 -0
  87. package/src/runtime/office/content-model.mjs +183 -0
  88. package/src/runtime/office/contract-benchmark.mjs +105 -0
  89. package/src/runtime/office/design-library.mjs +1562 -0
  90. package/src/runtime/office/design-system.mjs +1966 -0
  91. package/src/runtime/office/index.mjs +2413 -0
  92. package/src/runtime/office/journal.mjs +82 -0
  93. package/src/runtime/office/office-com-host.ps1 +3781 -0
  94. package/src/runtime/office/office-com-session-host.ps1 +855 -0
  95. package/src/runtime/office/ooxml-validator.mjs +271 -0
  96. package/src/runtime/office/pagination.mjs +132 -0
  97. package/src/runtime/office/pdf-adapter.mjs +591 -0
  98. package/src/runtime/office/pdf-analysis.mjs +372 -0
  99. package/src/runtime/office/pdf-render.mjs +167 -0
  100. package/src/runtime/office/pdf-security.mjs +63 -0
  101. package/src/runtime/office/polish-benchmark.mjs +190 -0
  102. package/src/runtime/office/portable-ooxml.mjs +1867 -0
  103. package/src/runtime/office/quality-live-benchmark.mjs +486 -0
  104. package/src/runtime/office/quality-pipeline.mjs +136 -0
  105. package/src/runtime/office/tabular.mjs +302 -0
  106. package/src/runtime/office/templates/mixdog-executive.pptx +0 -0
  107. package/src/runtime/office/templates/mixdog-executive.pptx.mixdog.json +190 -0
  108. package/src/runtime/office/tool-defs.mjs +113 -0
  109. package/src/runtime/office/visual-diff.mjs +89 -0
  110. package/src/runtime/office/xlsx-assertions.mjs +172 -0
  111. package/src/runtime/office/xlsx-contract.mjs +147 -0
  112. package/src/runtime/shared/agent-route-config.mjs +9 -0
  113. package/src/runtime/shared/tool-execution-contract.mjs +16 -0
  114. package/src/runtime/shared/tool-surface.mjs +9 -0
  115. package/src/session-runtime/context-status.mjs +9 -3
  116. package/src/session-runtime/deferred-tool-delta.mjs +104 -0
  117. package/src/session-runtime/goal-runtime.mjs +617 -197
  118. package/src/session-runtime/lifecycle-api.mjs +50 -8
  119. package/src/session-runtime/provider-request-snapshot.mjs +33 -9
  120. package/src/session-runtime/resource-api.mjs +31 -94
  121. package/src/session-runtime/runtime-core.mjs +78 -26
  122. package/src/session-runtime/session-lifecycle.mjs +34 -12
  123. package/src/session-runtime/session-title.mjs +2 -2
  124. package/src/session-runtime/session-turn-api.mjs +15 -14
  125. package/src/session-runtime/tool-catalog-data.mjs +1 -1
  126. package/src/session-runtime/tool-catalog.mjs +38 -99
  127. package/src/session-runtime/tool-defs.mjs +6 -1
  128. package/src/session-runtime/tool-surface.mjs +18 -8
  129. package/src/session-runtime/workflow-agents-api.mjs +8 -25
  130. package/src/session-runtime/workflow.mjs +8 -6
  131. package/src/standalone/agent-tool/helpers.mjs +2 -2
  132. package/src/standalone/agent-tool/job-views.mjs +3 -1
  133. package/src/standalone/agent-tool/notify.mjs +5 -1
  134. package/src/standalone/agent-tool/render.mjs +3 -0
  135. package/src/standalone/agent-tool/spawn-flow.mjs +61 -16
  136. package/src/standalone/agent-tool/tool-def.mjs +1 -1
  137. package/src/standalone/agent-tool/worker-index.mjs +123 -0
  138. package/src/standalone/agent-tool/worker-rows.mjs +2 -1
  139. package/src/standalone/agent-tool.mjs +57 -10
  140. package/src/standalone/daemon.mjs +105 -6
  141. package/src/standalone/session-runtime-host.mjs +61 -48
  142. package/src/standalone/session-runtime-inline-host.mjs +34 -127
  143. package/src/standalone/session-runtime-worker.mjs +20 -198
  144. package/src/standalone/session-service.mjs +632 -7
  145. package/src/tui/dist/index.mjs +24 -1
  146. package/src/tui/lib/voice-setup.mjs +4 -1
  147. package/src/tui/session/context-state.mjs +2 -13
  148. package/src/tui/session/goal-continuation.mjs +38 -7
  149. package/src/tui/session/session-api-ext.mjs +9 -0
  150. package/src/tui/session/session-api.mjs +15 -1
  151. package/src/tui/session/session-flow.mjs +25 -1
  152. package/src/tui/session/turn.mjs +88 -16
  153. package/src/tui/session-local.mjs +25 -3
  154. package/src/vendor/statusline/src/gateway/route-meta.mjs +31 -0
  155. package/scripts/generate-voice-runtime-manifest.test.mjs +0 -135
  156. package/scripts/native-binary-arch.test.mjs +0 -111
  157. package/scripts/patch-replay.test.mjs +0 -94
  158. package/src/headless-exec.test.mjs +0 -539
  159. package/src/runtime/agent/orchestrator/agent-trace-timing.test.mjs +0 -57
  160. package/src/runtime/agent/orchestrator/context/collect-skills.test.mjs +0 -153
  161. package/src/runtime/agent/orchestrator/mcp/cancellation.test.mjs +0 -139
  162. package/src/runtime/agent/orchestrator/mcp/features.test.mjs +0 -66
  163. package/src/runtime/agent/orchestrator/mcp/security.test.mjs +0 -80
  164. package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.test.mjs +0 -90
  165. package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.test.mjs +0 -215
  166. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.test.mjs +0 -165
  167. package/src/runtime/agent/orchestrator/providers/media-parity.test.mjs +0 -142
  168. package/src/runtime/agent/orchestrator/providers/openai-codex-identity.test.mjs +0 -153
  169. package/src/runtime/agent/orchestrator/providers/openai-codex-model.test.mjs +0 -24
  170. package/src/runtime/agent/orchestrator/providers/openai-ws-delta-parity.test.mjs +0 -190
  171. package/src/runtime/agent/orchestrator/providers/provider-replay.test.mjs +0 -235
  172. package/src/runtime/agent/orchestrator/providers/sse-framing.test.mjs +0 -719
  173. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.test.mjs +0 -40
  174. package/src/runtime/agent/orchestrator/session/compact-policy.test.mjs +0 -176
  175. package/src/runtime/agent/orchestrator/session/compaction-read-reset.test.mjs +0 -161
  176. package/src/runtime/agent/orchestrator/session/eager-dispatch.test.mjs +0 -115
  177. package/src/runtime/agent/orchestrator/session/evidence-union.test.mjs +0 -228
  178. package/src/runtime/agent/orchestrator/session/image-strip-recovery.test.mjs +0 -245
  179. package/src/runtime/agent/orchestrator/session/lossless-tool-output.test.mjs +0 -125
  180. package/src/runtime/agent/orchestrator/session/manager/pending-messages-persistence.test.mjs +0 -325
  181. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.test.mjs +0 -70
  182. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.test.mjs +0 -457
  183. package/src/runtime/agent/orchestrator/session/provider-prefix-guard.test.mjs +0 -117
  184. package/src/runtime/agent/orchestrator/session/reduction-metrics.test.mjs +0 -87
  185. package/src/runtime/agent/orchestrator/session/store/serialize.test.mjs +0 -60
  186. package/src/runtime/agent/orchestrator/session/store-summary-reader.test.mjs +0 -583
  187. package/src/runtime/agent/orchestrator/session/task-wait-control.test.mjs +0 -78
  188. package/src/runtime/agent/orchestrator/tools/builtin/absence-absorption.test.mjs +0 -43
  189. package/src/runtime/agent/orchestrator/tools/builtin/absolute-glob-expand.test.mjs +0 -63
  190. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool-cwd-env.test.mjs +0 -14
  191. package/src/runtime/agent/orchestrator/tools/builtin/edit-encoding-eol.test.mjs +0 -224
  192. package/src/runtime/agent/orchestrator/tools/builtin/edit-sequential-occupation.test.mjs +0 -224
  193. package/src/runtime/agent/orchestrator/tools/builtin/enoent-outside-project.test.mjs +0 -56
  194. package/src/runtime/agent/orchestrator/tools/builtin/find-search-budget.test.mjs +0 -103
  195. package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.test.mjs +0 -30
  196. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.test.mjs +0 -390
  197. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.test.mjs +0 -83
  198. package/src/runtime/agent/orchestrator/tools/builtin/grep-output-budget.test.mjs +0 -31
  199. package/src/runtime/agent/orchestrator/tools/builtin/grep-single-file-rescue.test.mjs +0 -106
  200. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.test.mjs +0 -102
  201. package/src/runtime/agent/orchestrator/tools/builtin/list-tool-integrity.test.mjs +0 -152
  202. package/src/runtime/agent/orchestrator/tools/builtin/native-search-health.test.mjs +0 -24
  203. package/src/runtime/agent/orchestrator/tools/builtin/native-search-transport.test.mjs +0 -24
  204. package/src/runtime/agent/orchestrator/tools/builtin/noise-dir-visibility.test.mjs +0 -69
  205. package/src/runtime/agent/orchestrator/tools/builtin/read-glob-survey.test.mjs +0 -71
  206. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.test.mjs +0 -56
  207. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.test.mjs +0 -16
  208. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-top-k.test.mjs +0 -39
  209. package/src/runtime/agent/orchestrator/tools/builtin/write-symlink.test.mjs +0 -153
  210. package/src/runtime/agent/orchestrator/tools/code-graph/aggregate-anchor-relocation.test.mjs +0 -55
  211. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.test.mjs +0 -88
  212. package/src/runtime/agent/orchestrator/tools/code-graph/loose-file-target.test.mjs +0 -72
  213. package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.test.mjs +0 -54
  214. package/src/runtime/agent/orchestrator/tools/code-graph/search-references.test.mjs +0 -20
  215. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-search-scope.test.mjs +0 -55
  216. package/src/runtime/agent/orchestrator/tools/code-graph/text-span-mask.test.mjs +0 -268
  217. package/src/runtime/agent/orchestrator/tools/env-scrub.test.mjs +0 -57
  218. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.test.mjs +0 -19
  219. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.test.mjs +0 -104
  220. package/src/runtime/agent/orchestrator/tools/patch/engine-contract-gate.test.mjs +0 -661
  221. package/src/runtime/agent/orchestrator/tools/patch/patch-codec-eol.test.mjs +0 -552
  222. package/src/runtime/agent/orchestrator/tools/patch/patch-symlink.test.mjs +0 -141
  223. package/src/runtime/agent/orchestrator/tools/patch/v4a-pure-move.test.mjs +0 -57
  224. package/src/runtime/agent/orchestrator/tools/patch/v4a-section-coalesce.test.mjs +0 -81
  225. package/src/runtime/agent/orchestrator/tools/spawn-binary-fetcher.test.mjs +0 -52
  226. package/src/runtime/attachments/store.test.mjs +0 -209
  227. package/src/runtime/channels/lib/voice-runtime-fetcher.test.mjs +0 -17
  228. package/src/runtime/channels/lib/webhook/deliveries.test.mjs +0 -18
  229. package/src/runtime/channels/lib/webhook/relay-tunnel.test.mjs +0 -68
  230. package/src/runtime/media/adapters/codex-image.test.mjs +0 -22
  231. package/src/runtime/media/download.test.mjs +0 -52
  232. package/src/runtime/media/renditions.test.mjs +0 -99
  233. package/src/runtime/media/store.test.mjs +0 -159
  234. package/src/runtime/memory/lib/archive-security.test.mjs +0 -128
  235. package/src/runtime/memory/lib/embedding-model-config.test.mjs +0 -33
  236. package/src/runtime/memory/lib/http-wire.test.mjs +0 -15
  237. package/src/runtime/memory/lib/memory-cycle-packets.test.mjs +0 -49
  238. package/src/runtime/memory/lib/memory-cycle2-shared.test.mjs +0 -78
  239. package/src/runtime/memory/lib/memory-embedding-migration.test.mjs +0 -50
  240. package/src/runtime/memory/lib/pg/process.test.mjs +0 -36
  241. package/src/runtime/memory/lib/trace-store.test.mjs +0 -57
  242. package/src/runtime/memory/lib/transcript-ingest.test.mjs +0 -52
  243. package/src/runtime/shared/background-tasks.test.mjs +0 -78
  244. package/src/runtime/shared/bounded-download.test.mjs +0 -41
  245. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -25
  246. package/src/runtime/shared/child-spawn-remote.test.mjs +0 -124
  247. package/src/runtime/shared/remote-intent.test.mjs +0 -40
  248. package/src/runtime/shared/resource-admission.test.mjs +0 -43
  249. package/src/runtime/shared/runtime-root.test.mjs +0 -34
  250. package/src/runtime/shared/schedule-time.test.mjs +0 -29
  251. package/src/runtime/shared/session-runtime-health.test.mjs +0 -83
  252. package/src/runtime/shared/skill-document.test.mjs +0 -81
  253. package/src/runtime/shared/tool-surface.test.mjs +0 -87
  254. package/src/runtime/shared/update-checker.test.mjs +0 -33
  255. package/src/runtime/shared/user-cwd.test.mjs +0 -43
  256. package/src/runtime/shared/webhook-session-run.test.mjs +0 -14
  257. package/src/session-runtime/agent-disable.test.mjs +0 -123
  258. package/src/session-runtime/cwd-plugins.test.mjs +0 -75
  259. package/src/session-runtime/cwd-tool-routing.test.mjs +0 -61
  260. package/src/session-runtime/global-extensions.test.mjs +0 -28
  261. package/src/session-runtime/goal-runtime.test.mjs +0 -108
  262. package/src/session-runtime/lifecycle-api.test.mjs +0 -21
  263. package/src/session-runtime/model-settings-persist.test.mjs +0 -105
  264. package/src/session-runtime/notification-bus.test.mjs +0 -148
  265. package/src/session-runtime/plugin-mcp-standard.test.mjs +0 -177
  266. package/src/session-runtime/prewarm.test.mjs +0 -52
  267. package/src/session-runtime/provider-request-snapshot.test.mjs +0 -37
  268. package/src/session-runtime/resource-api-global.test.mjs +0 -69
  269. package/src/session-runtime/session-lifecycle.test.mjs +0 -125
  270. package/src/session-runtime/session-title.test.mjs +0 -36
  271. package/src/session-runtime/skills-api.test.mjs +0 -99
  272. package/src/session-runtime/tool-policy-surface.test.mjs +0 -331
  273. package/src/standalone/agent-tool/helpers.test.mjs +0 -62
  274. package/src/standalone/agent-tool/notify.test.mjs +0 -37
  275. package/src/standalone/agent-tool/spawn-flow.test.mjs +0 -63
  276. package/src/standalone/channel-restart.test.mjs +0 -145
  277. package/src/standalone/channel-session-router.test.mjs +0 -37
  278. package/src/standalone/channel-worker-heartbeat.test.mjs +0 -30
  279. package/src/standalone/hook-bus/handlers.test.mjs +0 -88
  280. package/src/standalone/plugin-admin.test.mjs +0 -173
  281. package/src/standalone/session-runtime-agent-control-client.test.mjs +0 -71
  282. package/src/standalone/session-runtime-dispatch-cancel.test.mjs +0 -139
  283. package/src/standalone/session-runtime-host-factory.test.mjs +0 -31
  284. package/src/standalone/session-runtime-host-health.test.mjs +0 -160
  285. package/src/standalone/session-runtime-inline-host.test.mjs +0 -83
  286. package/src/standalone/session-runtime-provider-cooldown.test.mjs +0 -80
  287. package/src/standalone/session-runtime-shard-host.test.mjs +0 -569
  288. package/src/standalone/session-runtime-shard-router.test.mjs +0 -101
  289. package/src/tui/app/live-spinner-visibility.test.mjs +0 -44
  290. package/src/tui/app/panel-epoch.test.mjs +0 -1009
  291. package/src/tui/app/panel-handoff.test.mjs +0 -311
  292. package/src/tui/app/prompt-submit.test.mjs +0 -206
  293. package/src/tui/session/completion-card-restore.test.mjs +0 -111
  294. package/src/tui/session/goal-continuation.test.mjs +0 -84
  295. package/src/tui/session/oauth-flows.test.mjs +0 -134
  296. package/src/tui/session/queue-helpers.test.mjs +0 -46
  297. package/src/tui/session/session-action-surface.test.mjs +0 -108
  298. package/src/tui/session/task-wait-submit.test.mjs +0 -80
  299. package/src/tui/session/tool-result-status.test.mjs +0 -131
  300. package/src/tui/session/tui-steering-persist.test.mjs +0 -104
@@ -1,539 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
- import test from 'node:test';
6
-
7
- import { classifyCliInvocation } from './headless-command.mjs';
8
- import { prewarmHeadlessSearch, runHeadlessExec } from './headless-exec.mjs';
9
- import { resolveCursorOAuthAccessToken } from './runtime/agent/orchestrator/providers/cursor-auth.mjs';
10
- import { createPristineExecutionBoundary } from './runtime/shared/pristine-execution.mjs';
11
-
12
- test('headless search prewarm starts only the canonical native server', async () => {
13
- const calls = [];
14
- await prewarmHeadlessSearch('/app/project', {
15
- loadNativeSearch: async () => ({
16
- async warmNativeSearchServer() {
17
- calls.push('server');
18
- return true;
19
- },
20
- }),
21
- });
22
- assert.deepEqual(calls, ['server']);
23
- });
24
-
25
- test('pristine headless execution binds Cursor OAuth credentials in process', async () => {
26
- const root = mkdtempSync(join(tmpdir(), 'mixdog-headless-cursor-auth-test-'));
27
- const dataDir = join(root, 'data');
28
- mkdirSync(dataDir, { recursive: true });
29
- writeFileSync(join(dataDir, 'cursor-oauth.json'), JSON.stringify({
30
- access_token: 'cursor-test-token',
31
- }));
32
- const env = { MIXDOG_HOME: root };
33
- const boundary = createPristineExecutionBoundary({
34
- provider: 'cursor-oauth',
35
- model: 'gemini-3.7-flash',
36
- env,
37
- });
38
- try {
39
- assert.equal(boundary.audit.authMode, 'in-process-host-oauth-binding');
40
- assert.equal(await resolveCursorOAuthAccessToken(), 'cursor-test-token');
41
- assert.deepEqual(boundary.loadConfig().providers, {
42
- 'cursor-oauth': { enabled: true },
43
- });
44
- } finally {
45
- boundary.cleanup();
46
- rmSync(root, { recursive: true, force: true });
47
- }
48
- });
49
-
50
- test('headless exec runs one implicit-approval session and waits for tracked tasks', async () => {
51
- const root = mkdtempSync(join(tmpdir(), 'mixdog-headless-exec-test-'));
52
- const usageLogPath = join(root, 'usage.json');
53
- const output = [];
54
- const errors = [];
55
- const runtimeOptions = [];
56
- const activeScopes = [];
57
- let activeChecks = 0;
58
- let boundaryCleaned = false;
59
- let runtimeClosed = false;
60
- const daemonCleanupCalls = [];
61
- const cleanupOrder = [];
62
- try {
63
- const code = await runHeadlessExec({
64
- message: 'fix it',
65
- provider: 'openai-oauth',
66
- model: 'gpt-test',
67
- effort: 'high',
68
- fast: true,
69
- usageLogPath,
70
- idlePollMs: 1,
71
- write: (text) => output.push(text),
72
- writeErr: (text) => errors.push(text),
73
- boundaryFactory: () => ({
74
- runtimeRoot: join(root, 'runtime-root'),
75
- loadConfig: () => ({ providers: { 'openai-oauth': { enabled: true } } }),
76
- cleanup: () => {
77
- boundaryCleaned = true;
78
- cleanupOrder.push('boundary');
79
- },
80
- }),
81
- runtimeFactory: async (options) => {
82
- runtimeOptions.push(options);
83
- return {
84
- id: 'sess_exec_test',
85
- model: 'gpt-test',
86
- clientHostPid: 123,
87
- ask: async (_prompt, optionsForAsk) => {
88
- optionsForAsk.onUsageDelta({
89
- model: 'gpt-fallback',
90
- deltaInput: 11,
91
- deltaCachedRead: 7,
92
- deltaCacheWrite: 3,
93
- deltaOutput: 5,
94
- });
95
- return { result: { content: 'done' } };
96
- },
97
- close: async () => {
98
- runtimeClosed = true;
99
- cleanupOrder.push('runtime');
100
- },
101
- };
102
- },
103
- memoryRuntimeCleanup: async () => {
104
- cleanupOrder.push('memory');
105
- },
106
- daemonRuntimeCleanup: async (runtimeRoot, options) => {
107
- daemonCleanupCalls.push({ runtimeRoot, options });
108
- cleanupOrder.push('daemon');
109
- },
110
- hasActiveTasks: (scope) => {
111
- activeScopes.push(scope);
112
- activeChecks += 1;
113
- return false;
114
- },
115
- installSignalCleanupFn: () => ({ uninstall() {} }),
116
- });
117
-
118
- assert.equal(code, 0);
119
- assert.deepEqual(output, ['done\n']);
120
- assert.deepEqual(errors, []);
121
- assert.equal(runtimeOptions[0].approvalMode, 'implicit');
122
- assert.equal(runtimeOptions[0].disallowDelegation, true);
123
- assert.deepEqual(runtimeOptions[0].initialConfig.workflow, { active: 'headless' });
124
- assert.equal(runtimeOptions[0].autoWakeCompletions, false);
125
- assert.equal(runtimeOptions[0].toolMode, 'full');
126
- assert.deepEqual(activeScopes[0], {
127
- callerSessionId: 'sess_exec_test',
128
- clientHostPid: 123,
129
- });
130
- assert.equal(boundaryCleaned, true);
131
- assert.equal(runtimeClosed, true);
132
- assert.deepEqual(cleanupOrder, ['runtime', 'daemon', 'memory', 'boundary']);
133
- assert.deepEqual(daemonCleanupCalls, [{
134
- runtimeRoot: join(root, 'runtime-root'),
135
- options: { waitForExit: true, timeoutMs: 8_000 },
136
- }]);
137
- const usage = JSON.parse(readFileSync(usageLogPath, 'utf8'));
138
- assert.deepEqual(usage.sessions[0].models, ['gpt-test', 'gpt-fallback']);
139
- assert.deepEqual(usage.totals, {
140
- inputTokens: 11,
141
- cacheTokens: 7,
142
- cacheWriteTokens: 3,
143
- outputTokens: 5,
144
- toolCallCountApprox: 0,
145
- });
146
- } finally {
147
- rmSync(root, { recursive: true, force: true });
148
- }
149
- });
150
-
151
- test('headless exec preserves the pristine root when isolated daemon shutdown fails', async () => {
152
- const errors = [];
153
- let cleanupOptions = null;
154
- const code = await runHeadlessExec({
155
- message: 'done',
156
- provider: 'openai-oauth',
157
- model: 'gpt-test',
158
- usageLogPath: '',
159
- write() {},
160
- writeErr: (text) => errors.push(text),
161
- boundaryFactory: () => ({
162
- runtimeRoot: '/isolated/runtime',
163
- loadConfig: () => ({ providers: { 'openai-oauth': { enabled: true } } }),
164
- cleanup: (options) => { cleanupOptions = options; },
165
- }),
166
- runtimeFactory: async () => ({
167
- id: 'sess_cleanup_failure',
168
- model: 'gpt-test',
169
- clientHostPid: 123,
170
- async ask() { return { result: { content: 'done' } }; },
171
- async close() {},
172
- }),
173
- daemonRuntimeCleanup: async () => { throw new Error('daemon stuck'); },
174
- memoryRuntimeCleanup: async () => {},
175
- hasActiveTasks: () => false,
176
- installSignalCleanupFn: () => ({ uninstall() {} }),
177
- });
178
-
179
- assert.equal(code, 1);
180
- assert.deepEqual(cleanupOptions, { preserveRoot: true });
181
- assert.ok(errors.some((line) => line.includes('shutdown failed: daemon stuck')));
182
- });
183
-
184
- test('headless exec flushes the usage snapshot mid-session, before any exit path', async () => {
185
- const root = mkdtempSync(join(tmpdir(), 'mixdog-headless-usage-flush-test-'));
186
- const usageLogPath = join(root, 'usage.json');
187
- // What a killed run would have left behind: read the file while `ask` is
188
- // still running. Before the per-response flush this was always absent, so
189
- // an agent-timeout trial reported no token spend at all.
190
- let midSession = null;
191
- try {
192
- const code = await runHeadlessExec({
193
- message: 'fix it',
194
- provider: 'openai-oauth',
195
- model: 'gpt-test',
196
- effort: 'high',
197
- fast: true,
198
- usageLogPath,
199
- idlePollMs: 1,
200
- write: () => {},
201
- writeErr: () => {},
202
- boundaryFactory: () => ({
203
- loadConfig: () => ({ providers: { 'openai-oauth': { enabled: true } } }),
204
- cleanup: () => {},
205
- }),
206
- runtimeFactory: async () => ({
207
- id: 'sess_flush_test',
208
- model: 'gpt-test',
209
- clientHostPid: 123,
210
- ask: async (_prompt, options) => {
211
- options.onUsageDelta({
212
- deltaInput: 9,
213
- deltaCachedRead: 4,
214
- deltaCacheWrite: 2,
215
- deltaOutput: 6,
216
- });
217
- try {
218
- midSession = JSON.parse(readFileSync(usageLogPath, 'utf8'));
219
- } catch (error) {
220
- midSession = { error: error?.message ?? String(error) };
221
- }
222
- return { result: { content: 'done' } };
223
- },
224
- close: async () => {},
225
- }),
226
- hasActiveTasks: () => false,
227
- installSignalCleanupFn: () => ({ uninstall() {} }),
228
- });
229
-
230
- assert.equal(code, 0);
231
- assert.deepEqual(midSession?.totals, {
232
- inputTokens: 9,
233
- cacheTokens: 4,
234
- cacheWriteTokens: 2,
235
- outputTokens: 6,
236
- toolCallCountApprox: 0,
237
- });
238
- } finally {
239
- rmSync(root, { recursive: true, force: true });
240
- }
241
- });
242
-
243
- test('headless exec answers an arrived completion and exits without waiting on live work', async () => {
244
- const output = [];
245
- const errors = [];
246
- const prompts = [];
247
- let closeOptions = null;
248
- let notificationListener = null;
249
- const code = await runHeadlessExec({
250
- message: 'start the long task',
251
- provider: 'openai-oauth',
252
- model: 'gpt-test',
253
- usageLogPath: '',
254
- write: (text) => output.push(text),
255
- writeErr: (text) => errors.push(text),
256
- boundaryFactory: () => ({
257
- loadConfig: () => ({ providers: { 'openai-oauth': { enabled: true } } }),
258
- cleanup() {},
259
- }),
260
- runtimeFactory: async () => ({
261
- id: 'sess_headless_drain',
262
- model: 'gpt-test',
263
- clientHostPid: 123,
264
- onNotification(listener) {
265
- notificationListener = listener;
266
- return () => { notificationListener = null; };
267
- },
268
- async ask(prompt) {
269
- prompts.push(prompt);
270
- if (prompts.length === 1) {
271
- notificationListener?.({
272
- content: 'background task completed',
273
- meta: { status: 'completed', execution_id: 'job_drain' },
274
- });
275
- return { result: { content: 'task started' } };
276
- }
277
- return { result: { content: 'final result' } };
278
- },
279
- async close(reason, options) { closeOptions = options ?? null; },
280
- }),
281
- // The job the model left running never ends — a server it was asked to
282
- // keep up. Exit must not wait for it, and must not reap it either: this
283
- // test hangs on a regression instead of failing slowly.
284
- hasActiveTasks: () => true,
285
- installSignalCleanupFn: () => ({ uninstall() {} }),
286
- });
287
-
288
- assert.equal(code, 0);
289
- assert.deepEqual(errors, []);
290
- assert.deepEqual(prompts, ['start the long task', '']);
291
- assert.deepEqual(output, ['final result\n']);
292
- assert.deepEqual(closeOptions, { keepBackgroundWork: true });
293
- });
294
-
295
- test('headless exec emits a timestamped JSONL lifecycle and exact tool count', async () => {
296
- const root = mkdtempSync(join(tmpdir(), 'mixdog-headless-json-test-'));
297
- const usageLogPath = join(root, 'usage.json');
298
- const output = [];
299
- const errors = [];
300
- let notificationListener = null;
301
- try {
302
- const code = await runHeadlessExec({
303
- message: 'fix it',
304
- provider: 'openai-oauth',
305
- model: 'gpt-test',
306
- effort: 'high',
307
- fast: true,
308
- json: true,
309
- usageLogPath,
310
- write: (text) => output.push(text),
311
- writeErr: (text) => errors.push(text),
312
- boundaryFactory: () => ({
313
- loadConfig: () => ({ providers: { 'openai-oauth': { enabled: true } } }),
314
- cleanup() {},
315
- }),
316
- runtimeFactory: async () => ({
317
- id: 'sess_json_test',
318
- provider: 'openai-oauth',
319
- model: 'gpt-test',
320
- effort: 'high',
321
- fast: true,
322
- cwd: '/app',
323
- clientHostPid: 123,
324
- onNotification(listener) {
325
- notificationListener = listener;
326
- return () => { notificationListener = null; };
327
- },
328
- async ask(_prompt, options) {
329
- options.onProviderSendStarted();
330
- options.onReasoningDelta('inspect first');
331
- options.onUsageDelta({
332
- deltaInput: 11,
333
- deltaCachedRead: 7,
334
- deltaCacheWrite: 3,
335
- deltaOutput: 5,
336
- });
337
- const call = {
338
- id: 'call_1',
339
- name: 'shell',
340
- arguments: { command: 'echo ok' },
341
- };
342
- options.onAssistantToolCallObserved(call);
343
- await options.onToolCall(1, [call]);
344
- options.onToolPhaseStarted();
345
- const toolClock = Date.now();
346
- options.onToolResult({
347
- role: 'tool',
348
- toolCallId: 'call_1',
349
- content: 'ok\n',
350
- __earlyNotify: true,
351
- toolTiming: {
352
- dispatchStartedAt: toolClock,
353
- executionStartedAt: toolClock + 2,
354
- executionCompletedAt: toolClock + 5,
355
- },
356
- });
357
- options.onToolResult({
358
- role: 'tool',
359
- toolCallId: 'call_1',
360
- content: 'ok\n',
361
- toolKind: 'normal',
362
- toolTiming: {
363
- dispatchStartedAt: toolClock,
364
- executionStartedAt: toolClock + 2,
365
- executionCompletedAt: toolClock + 5,
366
- postprocessStartedAt: toolClock + 6,
367
- resultCompletedAt: toolClock + 8,
368
- },
369
- });
370
- options.onToolPhaseCompleted({ iteration: 1, calls: 1, elapsedMs: 2 });
371
- notificationListener?.({
372
- content: 'background task completed',
373
- meta: { status: 'progress' },
374
- });
375
- options.onProviderSendStarted();
376
- options.onAssistantText('done');
377
- options.onUsageDelta({
378
- deltaInput: 5,
379
- deltaCachedRead: 0,
380
- deltaCacheWrite: 0,
381
- deltaOutput: 2,
382
- });
383
- return { result: { content: 'done', stopReason: 'end_turn' } };
384
- },
385
- async close() {},
386
- }),
387
- hasActiveTasks: () => false,
388
- installSignalCleanupFn: () => ({ uninstall() {} }),
389
- });
390
-
391
- assert.equal(code, 0);
392
- assert.deepEqual(errors, []);
393
- const events = output.join('').trim().split('\n').map((line) => JSON.parse(line));
394
- assert.equal(events[0].type, 'thread.started');
395
- assert.equal(events[1].type, 'turn.started');
396
- assert.ok(events.every((event) => event.schema_version === 1 && event.timestamp));
397
- const toolStarted = events.find(
398
- (event) => event.type === 'item.started' && event.item?.type === 'tool_call',
399
- );
400
- const toolCompleted = events.find(
401
- (event) => event.type === 'item.completed' && event.item?.id === 'call_1',
402
- );
403
- assert.equal(toolStarted.item.name, 'shell');
404
- assert.equal(toolCompleted.item.output, 'ok\n');
405
- assert.equal(toolCompleted.item.status, 'completed');
406
- assert.ok(toolCompleted.item.duration_ms >= 0);
407
- assert.equal(toolCompleted.item.timing.dispatch_ms, 2);
408
- assert.equal(toolCompleted.item.timing.execution_ms, 3);
409
- assert.equal(toolCompleted.item.timing.batch_wait_ms, 1);
410
- assert.equal(toolCompleted.item.timing.postprocess_ms, 2);
411
- assert.equal(events.filter(
412
- (event) => event.type === 'item.completed' && event.item?.id === 'call_1',
413
- ).length, 1);
414
- assert.ok(events.some((event) => event.type === 'notification'));
415
- assert.equal(events.filter((event) => event.type === 'model.request.completed').length, 2);
416
- const terminal = events.at(-1);
417
- assert.equal(terminal.type, 'result');
418
- assert.equal(terminal.subtype, 'success');
419
- assert.equal(terminal.session_id, 'sess_json_test');
420
- assert.equal(terminal.provider_requests, 2);
421
- assert.equal(terminal.tool_calls, 1);
422
- assert.deepEqual(terminal.usage, {
423
- input_tokens: 16,
424
- cached_input_tokens: 7,
425
- cache_write_input_tokens: 3,
426
- output_tokens: 7,
427
- tool_calls: 1,
428
- });
429
- const usage = JSON.parse(readFileSync(usageLogPath, 'utf8'));
430
- assert.equal(usage.totals.toolCallCountApprox, 1);
431
- } finally {
432
- rmSync(root, { recursive: true, force: true });
433
- }
434
- });
435
-
436
- test('headless exec emits structured JSONL failure before returning exit 1', async () => {
437
- const output = [];
438
- const errors = [];
439
- const code = await runHeadlessExec({
440
- message: 'fail',
441
- provider: 'openai-oauth',
442
- model: 'gpt-test',
443
- json: true,
444
- usageLogPath: '',
445
- write: (text) => output.push(text),
446
- writeErr: (text) => errors.push(text),
447
- boundaryFactory: () => ({
448
- loadConfig: () => ({ providers: { 'openai-oauth': { enabled: true } } }),
449
- cleanup() {},
450
- }),
451
- runtimeFactory: async () => ({
452
- id: 'sess_json_failure',
453
- model: 'gpt-test',
454
- clientHostPid: 123,
455
- async ask() {
456
- throw new Error('boom');
457
- },
458
- async close() {},
459
- }),
460
- installSignalCleanupFn: () => ({ uninstall() {} }),
461
- });
462
-
463
- const events = output.join('').trim().split('\n').map((line) => JSON.parse(line));
464
- assert.equal(code, 1);
465
- assert.ok(events.some((event) => event.type === 'turn.failed'));
466
- assert.equal(events.at(-1).type, 'result');
467
- assert.equal(events.at(-1).subtype, 'error_during_execution');
468
- assert.deepEqual(events.at(-1).errors, ['boom']);
469
- assert.deepEqual(errors, ['mixdog: boom\n']);
470
- });
471
-
472
- test('headless exec exposes typed refusal as an API error result', async () => {
473
- const output = [];
474
- const code = await runHeadlessExec({
475
- message: 'request',
476
- provider: 'anthropic-oauth',
477
- model: 'claude-test',
478
- json: true,
479
- usageLogPath: '',
480
- write: (text) => output.push(text),
481
- writeErr() {},
482
- boundaryFactory: () => ({
483
- loadConfig: () => ({ providers: { 'anthropic-oauth': { enabled: true } } }),
484
- cleanup() {},
485
- }),
486
- runtimeFactory: async () => ({
487
- id: 'sess_json_refusal',
488
- model: 'claude-test',
489
- clientHostPid: 123,
490
- async ask() {
491
- return {
492
- result: {
493
- content: 'Unable to respond.',
494
- stopReason: 'refusal',
495
- terminationReason: 'refusal',
496
- },
497
- };
498
- },
499
- async close() {},
500
- }),
501
- hasActiveTasks: () => false,
502
- installSignalCleanupFn: () => ({ uninstall() {} }),
503
- });
504
-
505
- const terminal = output.join('').trim().split('\n').map((line) => JSON.parse(line)).at(-1);
506
- assert.equal(code, 0);
507
- assert.equal(terminal.subtype, 'success');
508
- assert.equal(terminal.is_error, true);
509
- assert.equal(terminal.stop_reason, 'refusal');
510
- assert.equal(terminal.termination_reason, 'refusal');
511
- });
512
-
513
- test('--json is accepted for exec and rejected for the interactive command', () => {
514
- const exec = classifyCliInvocation([
515
- 'exec',
516
- '--provider', 'openai-oauth',
517
- '--model', 'gpt-test',
518
- '--json',
519
- 'fix it',
520
- ]);
521
- assert.equal(exec.kind, 'exec');
522
- assert.equal(exec.options.json, true);
523
-
524
- const interactive = classifyCliInvocation(['--json']);
525
- assert.equal(interactive.kind, 'error');
526
- assert.equal(interactive.error, 'option --json is only supported for mixdog exec');
527
- });
528
-
529
- test('headless exec rejects workflow selection', () => {
530
- const invocation = classifyCliInvocation([
531
- 'exec',
532
- '--provider', 'openai-oauth',
533
- '--model', 'gpt-test',
534
- '--workflow', 'solo',
535
- 'fix it',
536
- ]);
537
- assert.equal(invocation.kind, 'error');
538
- assert.equal(invocation.error, 'option --workflow is not supported for mixdog exec');
539
- });
@@ -1,57 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
4
- import { tmpdir } from 'node:os';
5
- import { join } from 'node:path';
6
- import { spawnSync } from 'node:child_process';
7
-
8
- test('tool traces expose dispatch, execution, collection, and postprocess timing', () => {
9
- const dir = mkdtempSync(join(tmpdir(), 'mixdog-tool-timing-'));
10
- try {
11
- const tracePath = join(dir, 'agent-trace.jsonl');
12
- const child = spawnSync(process.execPath, ['--input-type=module', '-e', `
13
- import { readFileSync } from 'node:fs';
14
- import { traceAgentTool } from './src/runtime/agent/orchestrator/agent-trace-format.mjs';
15
- import { drainAgentTrace } from './src/runtime/agent/orchestrator/agent-trace-io.mjs';
16
- traceAgentTool({
17
- sessionId: 'timing-test',
18
- iteration: 1,
19
- toolName: 'grep',
20
- toolKind: 'builtin',
21
- toolMs: 50,
22
- resultKind: 'normal',
23
- resultText: 'ok',
24
- toolTiming: {
25
- dispatchStartedAt: 100,
26
- executionStartedAt: 110,
27
- executionCompletedAt: 160,
28
- postprocessStartedAt: 175,
29
- resultCompletedAt: 190,
30
- },
31
- });
32
- await drainAgentTrace();
33
- const row = JSON.parse(readFileSync(process.env.MIXDOG_AGENT_TRACE_PATH, 'utf8').trim());
34
- process.stdout.write(JSON.stringify(row.payload.timing));
35
- `], {
36
- cwd: process.cwd(),
37
- encoding: 'utf8',
38
- env: {
39
- ...process.env,
40
- MIXDOG_AGENT_TRACE_PATH: tracePath,
41
- MIXDOG_AGENT_TRACE_DISABLE: '',
42
- MIXDOG_AGENT_TRACE_LOCAL_DISABLE: '',
43
- MIXDOG_RUNTIME_ROOT: join(dir, 'no-service'),
44
- },
45
- });
46
- assert.equal(child.status, 0, child.stderr);
47
- assert.deepEqual(JSON.parse(child.stdout), {
48
- dispatch_wait_ms: 10,
49
- execution_ms: 50,
50
- result_collection_wait_ms: 15,
51
- postprocess_ms: 15,
52
- total_ms: 90,
53
- });
54
- } finally {
55
- rmSync(dir, { recursive: true, force: true });
56
- }
57
- });