mixdog 1.2.3 → 1.2.5

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 (469) hide show
  1. package/package.json +1 -1
  2. package/scripts/gate-local.mjs +6 -4
  3. package/scripts/lib/gate-scheduler.mjs +29 -11
  4. package/scripts/mobile-release.mjs +5 -4
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +128 -38
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/maintainer/AGENT.md +1 -1
  9. package/src/agents/maintainer/agent.json +1 -1
  10. package/src/agents/reviewer/AGENT.md +2 -4
  11. package/src/agents/security/AGENT.md +1 -2
  12. package/src/agents/writer/AGENT.md +2 -3
  13. package/src/defaults/shipped-history.json +7 -1
  14. package/src/defaults/skills/image/SKILL.md +21 -23
  15. package/src/lib/keychain-cjs.cjs +13 -11
  16. package/src/output-styles/common.md +2 -1
  17. package/src/rules/agent/AGENT.md +7 -5
  18. package/src/rules/lead/LEAD.md +13 -13
  19. package/src/rules/shared/45-destructive.md +4 -0
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  21. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  22. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  23. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  24. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  25. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  26. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
  28. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  29. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  30. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
  31. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
  32. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  33. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  34. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
  35. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
  36. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
  37. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
  38. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
  39. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
  40. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  41. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  42. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  43. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  44. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
  46. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
  47. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
  48. package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
  49. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
  50. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
  51. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
  52. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
  53. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
  54. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
  55. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  56. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  57. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
  58. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
  59. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
  60. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
  61. package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
  62. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
  64. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
  65. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  66. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
  67. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
  68. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  69. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
  70. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
  72. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
  78. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
  79. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  80. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
  81. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  82. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
  83. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
  84. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
  86. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
  87. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
  88. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
  89. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
  90. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
  92. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
  93. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
  95. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
  96. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
  97. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
  98. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  99. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
  100. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  101. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  102. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  103. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
  104. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
  106. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
  107. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
  108. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  109. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  110. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  111. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  112. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  113. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
  114. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  115. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  117. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
  118. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  119. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  120. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  121. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
  122. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  123. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  124. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
  125. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
  126. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
  127. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  128. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  129. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  130. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
  131. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
  132. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
  133. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  134. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
  135. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
  136. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  137. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
  138. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
  139. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
  140. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  141. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
  146. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
  147. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  148. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  149. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  150. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  151. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
  152. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  153. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  154. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
  155. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
  157. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  158. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
  159. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  160. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
  161. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  162. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
  163. package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
  164. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
  165. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  167. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  169. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
  172. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  173. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  174. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  175. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
  176. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  177. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  178. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  179. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  181. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +160 -212
  182. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
  183. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  184. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  185. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
  186. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  187. package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
  188. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
  189. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
  190. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  191. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
  192. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  193. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  194. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  195. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  196. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  197. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
  198. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  199. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  200. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  201. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  202. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  203. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  205. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
  206. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  207. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  208. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  209. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  210. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  211. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  212. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  213. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  214. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  215. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  216. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  217. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  218. package/src/runtime/attachments/store.d.mts +9 -0
  219. package/src/runtime/attachments/store.mjs +80 -9
  220. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  221. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  222. package/src/runtime/computer-bridge/action-schema.mjs +178 -178
  223. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  224. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  225. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  226. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  227. package/src/runtime/github/tool.mjs +118 -17
  228. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  229. package/src/runtime/media/catalog.mjs +4 -4
  230. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  231. package/src/runtime/media/defaults.mjs +37 -0
  232. package/src/runtime/media/jobs.mjs +12 -2
  233. package/src/runtime/media/lanes.mjs +12 -0
  234. package/src/runtime/media/tool-defs.mjs +15 -4
  235. package/src/runtime/media/tool.mjs +41 -12
  236. package/src/runtime/media/upstream-error.mjs +72 -6
  237. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  238. package/src/runtime/memory/lib/pg/process.mjs +5 -7
  239. package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
  240. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  241. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  242. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  243. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  244. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  245. package/src/runtime/office/core/office-write-ledger.mjs +1 -5
  246. package/src/runtime/office/index.mjs +2 -3
  247. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  248. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  249. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  250. package/src/runtime/shared/atomic-file.d.mts +1 -1
  251. package/src/runtime/shared/background-tasks.mjs +6 -1
  252. package/src/runtime/shared/bounded-line-diff.mjs +11 -2
  253. package/src/runtime/shared/browser-launch.mjs +15 -0
  254. package/src/runtime/shared/err-text.mjs +42 -4
  255. package/src/runtime/shared/file-lock.mjs +6 -5
  256. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  257. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  258. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  259. package/src/runtime/shared/model-route-chain.mjs +48 -0
  260. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  261. package/src/runtime/shared/pid-liveness.mjs +12 -0
  262. package/src/runtime/shared/provider-api-key.mjs +6 -0
  263. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  264. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  265. package/src/runtime/shared/quiet-progress.mjs +101 -0
  266. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  267. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  268. package/src/runtime/shared/remote-intent.mjs +2 -42
  269. package/src/runtime/shared/slow-span.mjs +8 -1
  270. package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
  271. package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
  272. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  273. package/src/runtime/shared/tool-result-summary.mjs +16 -2
  274. package/src/runtime/shared/tool-status.mjs +3 -2
  275. package/src/runtime/shared/tool-surface.mjs +2 -3
  276. package/src/runtime/shared/tool-work-units.mjs +22 -15
  277. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  278. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  279. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  280. package/src/runtime/shared/transcript-writer.mjs +14 -4
  281. package/src/runtime/shared/turn-changes.mjs +2 -1
  282. package/src/runtime/shared/turn-snapshot.mjs +11 -3
  283. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  284. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  285. package/src/runtime/shared/worktrees/carry.mjs +6 -4
  286. package/src/runtime/shared/worktrees/contract.mjs +27 -1
  287. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  288. package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
  289. package/src/runtime/shared/worktrees/git-head.mjs +22 -13
  290. package/src/runtime/shared/worktrees/include.mjs +125 -7
  291. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  292. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  293. package/src/runtime/shared/worktrees/manager.mjs +378 -32
  294. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  295. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  296. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  297. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  298. package/src/runtime/terminal-bridge/client.mjs +14 -10
  299. package/src/session-runtime/boot/apis.mjs +7 -1
  300. package/src/session-runtime/boot/config.mjs +2 -0
  301. package/src/session-runtime/boot/facade.mjs +3 -0
  302. package/src/session-runtime/boot/session.mjs +3 -2
  303. package/src/session-runtime/boot/tools.mjs +3 -0
  304. package/src/session-runtime/conversation-import/service.mjs +1 -1
  305. package/src/session-runtime/goal-facade-api.mjs +2 -2
  306. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
  307. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
  308. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
  309. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  310. package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
  311. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
  312. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
  313. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  314. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  315. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  316. package/src/session-runtime/lifecycle/teardown.mjs +7 -16
  317. package/src/session-runtime/media-api.mjs +8 -0
  318. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  319. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  320. package/src/session-runtime/model-route/set-route.mjs +114 -34
  321. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  322. package/src/session-runtime/model-route-api.mjs +4 -2
  323. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  324. package/src/session-runtime/native-web-search.mjs +9 -8
  325. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  326. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  327. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  328. package/src/session-runtime/provider-models.mjs +1 -0
  329. package/src/session-runtime/provider-usage.mjs +4 -0
  330. package/src/session-runtime/route-resolution.mjs +3 -1
  331. package/src/session-runtime/runtime-core.mjs +4 -0
  332. package/src/session-runtime/runtime-facade.mjs +6 -0
  333. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  334. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  335. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  336. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  337. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  338. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  339. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  340. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  341. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  342. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  343. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  344. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  345. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
  346. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  347. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  348. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  349. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  350. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  351. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  352. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  353. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  354. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  355. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
  356. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  357. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  358. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  359. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  360. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  361. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  362. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  363. package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
  364. package/src/session-runtime/services/agent-tool.mjs +4 -0
  365. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  366. package/src/session-runtime/services/provider-admin.mjs +77 -0
  367. package/src/session-runtime/session-create/session-options.mjs +7 -5
  368. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  369. package/src/session-runtime/session-transcript.mjs +4 -5
  370. package/src/session-runtime/session-turn-api.mjs +3 -9
  371. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
  372. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  373. package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
  374. package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
  375. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
  376. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  377. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  378. package/src/session-runtime/turn/side-question-ops.mjs +1 -4
  379. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
  380. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
  381. package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
  382. package/src/session-runtime/turn/turn-run.mjs +1 -36
  383. package/src/session-runtime/usage-stats-api.mjs +4 -1
  384. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  385. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  386. package/src/session-runtime/workspace/project-branches.mjs +28 -36
  387. package/src/session-runtime/workspace/transition-steps.mjs +96 -95
  388. package/src/session-runtime/workspace/transitions.mjs +248 -68
  389. package/src/standalone/channel-transport.mjs +3 -4
  390. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  391. package/src/standalone/daemon-pg-stop.mjs +1 -3
  392. package/src/standalone/daemon-session-control.mjs +88 -0
  393. package/src/standalone/daemon-stored-session-views.mjs +23 -3
  394. package/src/standalone/daemon.mjs +2 -0
  395. package/src/standalone/desktop-service-registry.mjs +32 -5
  396. package/src/standalone/local-session-runtime.mjs +11 -12
  397. package/src/standalone/session-protocol.mjs +7 -0
  398. package/src/standalone/session-runtime-inline-host.mjs +2 -0
  399. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  400. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  401. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  402. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  403. package/src/standalone/session-service/agent-tree.mjs +28 -2
  404. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  405. package/src/standalone/session-service/entries.mjs +1 -0
  406. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  407. package/src/standalone/session-service/quota-resume.mjs +28 -13
  408. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  409. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  410. package/src/standalone/session-tool-output.mjs +82 -0
  411. package/src/tui/app/app-view.jsx +2 -1
  412. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  413. package/src/tui/app/provider-setup-picker.mjs +15 -3
  414. package/src/tui/app/slash-commands.mjs +6 -0
  415. package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
  416. package/src/tui/components/Spinner.jsx +4 -0
  417. package/src/tui/components/SpinnerByline.jsx +21 -2
  418. package/src/tui/components/status-line/local-line.mjs +10 -2
  419. package/src/tui/dist/index.mjs +529 -270
  420. package/src/tui/session/active-tool-summary.mjs +1 -1
  421. package/src/tui/session/context-state.mjs +0 -3
  422. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  423. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  424. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  425. package/src/tui/session/quota-resume.mjs +140 -61
  426. package/src/tui/session/session-api/commands.mjs +4 -10
  427. package/src/tui/session/session-api/controls.mjs +12 -0
  428. package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
  429. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  430. package/src/tui/session/session-api/lifecycle.mjs +13 -11
  431. package/src/tui/session/session-api/media.mjs +2 -0
  432. package/src/tui/session/session-api/routes.mjs +81 -57
  433. package/src/tui/session/session-api/settings.mjs +3 -3
  434. package/src/tui/session/session-api/worktree.mjs +3 -2
  435. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  436. package/src/tui/session/session-flow/drain.mjs +6 -4
  437. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  438. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  439. package/src/tui/session/session-flow/queue.mjs +1 -1
  440. package/src/tui/session/tool-approval.mjs +17 -8
  441. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  442. package/src/tui/session/tui-steering-persist.mjs +3 -5
  443. package/src/tui/session/turn-quiet.mjs +53 -0
  444. package/src/tui/session/turn-stream.mjs +5 -1
  445. package/src/tui/session/turn.mjs +38 -31
  446. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  447. package/src/tui/spinner-meta.mjs +10 -0
  448. package/src/tui/spinner-verbs.mjs +3 -0
  449. package/src/ui/statusline.mjs +13 -3
  450. package/src/ui/streaming-markdown-heal.mjs +70 -18
  451. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  452. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  453. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  454. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
  455. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  456. package/src/session-runtime/turn/share-ops.mjs +0 -77
  457. package/src/tui/session/cross-surface-share.mjs +0 -406
  458. package/src/tui/session/live-share/delta.mjs +0 -153
  459. package/src/tui/session/live-share/mirror.mjs +0 -106
  460. package/src/tui/session/live-share/owner.mjs +0 -254
  461. package/src/tui/session/live-share/retry.mjs +0 -54
  462. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  463. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  464. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  465. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  466. package/src/tui/session/live-share/viewer.mjs +0 -99
  467. package/src/tui/session/live-share/wire.mjs +0 -44
  468. package/src/tui/session/live-share.mjs +0 -154
  469. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -0,0 +1,38 @@
1
+ /**
2
+ * src/tui/session/worktree-setup-notice.mjs - the one-line transcript notice
3
+ * shown while a new worktree's dependencies install (runtime.onWorktreeSetup).
4
+ * Only runs that install anything reach it; one notice per run, patched in
5
+ * place, so every surface showing the transcript (TUI, desktop, remote) sees
6
+ * the same line. The details (output, failures, skips) go to the agent only.
7
+ */
8
+ const ENDINGS = {
9
+ completed: 'Worktree dependencies installed.',
10
+ cancelled: 'Installing worktree dependencies was cancelled.',
11
+ };
12
+ const INCOMPLETE = 'Some worktree dependencies were not installed; the agent has the details.';
13
+
14
+ /** Notice text and tone for one install progress event. */
15
+ export function worktreeSetupNotice(event) {
16
+ if (event.final) {
17
+ const text = ENDINGS[event.status] ?? INCOMPLETE;
18
+ return { text, tone: event.status === 'completed' ? 'info' : 'warn' };
19
+ }
20
+ const what = event.label || event.command;
21
+ return { text: `Installing worktree dependencies [${event.index + 1}/${event.total}]: ${what}`, tone: 'info' };
22
+ }
23
+
24
+ export function createWorktreeSetupNotices({ pushItem, patchItem, nextId }) {
25
+ const items = new Map();
26
+ return (event) => {
27
+ const notice = worktreeSetupNotice(event);
28
+ const itemId = items.get(event.id);
29
+ if (itemId === undefined) {
30
+ const id = nextId();
31
+ items.set(event.id, id);
32
+ pushItem({ kind: 'notice', id, ...notice });
33
+ } else {
34
+ patchItem(itemId, notice);
35
+ }
36
+ if (event.final) items.delete(event.id);
37
+ };
38
+ }
@@ -9,6 +9,8 @@
9
9
  * for 30s. One builder, one answer.
10
10
  */
11
11
 
12
+ import { quietProgressLabel, quietProgressParts } from '../runtime/shared/quiet-progress.mjs';
13
+
12
14
  const compactNumberFormatter = new Intl.NumberFormat('en-US', {
13
15
  notation: 'compact',
14
16
  maximumFractionDigits: 1,
@@ -67,9 +69,13 @@ export function buildSpinnerMeta({
67
69
  thinkingSince = 0,
68
70
  thinkingMs = 0,
69
71
  effort = '',
72
+ // The turn's published quiet state (`spinner.quiet`) and the clock it is read at.
73
+ quiet = null,
74
+ now = Date.now(),
70
75
  verbose: _verbose = false,
71
76
  } = {}) {
72
77
  const tokens = Math.max(0, Number(outputTokens) || 0);
78
+ const quietParts = quietProgressParts(quiet, now, quiet?.warnMs);
73
79
  const thinkingParts = spinnerThinkingParts({ thinking, thinkingSince, thinkingMs, effort });
74
80
  const thinkingText = spinnerThinkingLabel({ thinking, thinkingSince, thinkingMs, effort });
75
81
  return {
@@ -83,6 +89,10 @@ export function buildSpinnerMeta({
83
89
  showTokens: tokens > 0,
84
90
  thinkingText,
85
91
  thinkingActive: Boolean(thinking || Number(thinkingSince) > 0),
92
+ // Quiet-time cue: structured for the desktop's i18n, English for the TUI;
93
+ // `escalated` once the silence reaches the stall watchdog's warn point.
94
+ quietParts,
95
+ quietText: quietProgressLabel(quietParts),
86
96
  };
87
97
  }
88
98
 
@@ -247,6 +247,9 @@ export const SPINNER_MODE_OVERRIDE_VERBS = {
247
247
  'auto-clear': 'Auto-clearing conversation',
248
248
  resuming: 'Resuming conversation',
249
249
  'task-wait': '작업 대기 중',
250
+ // The request is sent and its response headers are pending: the model is
251
+ // queued or thinking server-side.
252
+ 'model-thinking': 'Model thinking',
250
253
  };
251
254
 
252
255
  /**
@@ -31,7 +31,11 @@ import {
31
31
  num,
32
32
  formatElapsed,
33
33
  } from '../runtime/shared/statusline/statusline-format.mjs';
34
- import { shellJobsStatus, memoryCycleStatus } from '../runtime/shared/statusline/statusline-segments.mjs';
34
+ import {
35
+ shellJobsStatus,
36
+ memoryCycleStatus,
37
+ unconfirmedShellCount,
38
+ } from '../runtime/shared/statusline/statusline-segments.mjs';
35
39
  import {
36
40
  agentStatuslinePayload,
37
41
  classifyAgentWorkers,
@@ -397,10 +401,16 @@ function activitySegments({ sessionId, clientHostPid, agentWorkers, agentJobs, a
397
401
  const n = runningWorkers.length;
398
402
  segment(`Running ${n} Agent${n === 1 ? '' : 's'}`, agentsElapsed(runningWorkers));
399
403
  }
400
- if (shellStatus.count > 0) {
401
- const n = shellStatus.count;
404
+ const unconfirmed = unconfirmedShellCount(shellStatus);
405
+ if (shellStatus.count - unconfirmed > 0) {
406
+ const n = shellStatus.count - unconfirmed;
402
407
  segment(`Running ${n} Shell${n === 1 ? '' : 's'}`, shellStatus.elapsedLabel);
403
408
  }
409
+ if (unconfirmed > 0) {
410
+ parts.push(
411
+ `${YLW}⚠ ${unconfirmed} Shell${unconfirmed === 1 ? '' : 's'} termination unconfirmed${R} ${D}·${R} /shells`
412
+ );
413
+ }
404
414
  const webSearch = webSearchActivity(activeTools, { sessionId, clientHostPid });
405
415
  if (webSearch.count > 0) segment('Web Searching', webSearch.elapsed);
406
416
  // Memory cycle segment — single unified "Memory" wording for all states:
@@ -8,19 +8,47 @@ const HEALABLE_MARKDOWN_SYNTAX = /[`*_~[]/;
8
8
  function openFence(text) {
9
9
  let marker = '';
10
10
  let length = 0;
11
+ let start = 0;
12
+ let lineStart = 0;
11
13
  for (const rawLine of String(text ?? '').split('\n')) {
12
14
  const fence = FENCE_LINE.exec(rawLine.replace(/\r$/, ''));
13
- if (!fence) continue;
14
- const marks = fence[1];
15
- if (!marker) {
16
- marker = marks[0];
17
- length = marks.length;
18
- } else if (marks[0] === marker && marks.length >= length && !fence[2].trim()) {
19
- marker = '';
20
- length = 0;
15
+ if (fence) {
16
+ const marks = fence[1];
17
+ if (!marker) {
18
+ marker = marks[0];
19
+ length = marks.length;
20
+ start = lineStart;
21
+ } else if (marks[0] === marker && marks.length >= length && !fence[2].trim()) {
22
+ marker = '';
23
+ length = 0;
24
+ }
21
25
  }
26
+ lineStart += rawLine.length + 1;
22
27
  }
23
- return marker ? { marker, length } : null;
28
+ return marker ? { marker, length, start } : null;
29
+ }
30
+
31
+ // The opening fence line arrives a token at a time: ``` → ```py → ```python.
32
+ // Rendered at once, the card opened unlabelled and then relabelled (and
33
+ // re-highlighted) per token. The card appears with its first code character:
34
+ // an opening line alone would paint an empty box before any code.
35
+ function trimPartialOpeningFence(text, fence) {
36
+ const lineEnd = text.indexOf('\n', fence.start);
37
+ return lineEnd >= 0 && /\S/.test(text.slice(lineEnd + 1)) ? text : text.slice(0, fence.start);
38
+ }
39
+
40
+ // A line holding only a block marker so far has no content to show, and the
41
+ // marker alone parses as something else: `-` or `=` under a paragraph is a
42
+ // setext underline (the paragraph flashed into a heading until the item text
43
+ // arrived), `2` is a lazy paragraph continuation until its `.` arrives, `#`
44
+ // grows into `##`, and a lone backtick run is literal text until it becomes a
45
+ // fence. Hold the line back until its first content character.
46
+ const PENDING_BLOCK_MARKER_LINE = /(?:^|\n)[ \t]*(?:[-+*=_#>~`]+|\d{1,9}[.)]?)[ \t]*$/;
47
+
48
+ function trimPendingBlockMarker(text) {
49
+ const pending = PENDING_BLOCK_MARKER_LINE.exec(text);
50
+ if (!pending) return text;
51
+ return text.slice(0, pending.index + (pending[0].startsWith('\n') ? 1 : 0));
24
52
  }
25
53
 
26
54
  // A closing fence arrives a token at a time. Until its run is long enough to
@@ -57,7 +85,9 @@ function closeInlineCode(text, isPendingLocalPath) {
57
85
  } else if (run === open) open = 0;
58
86
  index = end;
59
87
  }
60
- if (open && isPendingLocalPath?.(text.slice(openIndex + open))) {
88
+ // An opener with nothing after it yet closes into an empty span, which
89
+ // parses as a literal backtick run that then vanishes into code.
90
+ if (open && (!text.slice(openIndex + open) || isPendingLocalPath?.(text.slice(openIndex + open)))) {
61
91
  return text.slice(0, openIndex);
62
92
  }
63
93
  return open > 0 ? `${text}${'`'.repeat(open)}` : text;
@@ -93,6 +123,7 @@ function scanEmphasisRuns(masked) {
93
123
  let end = index + 1;
94
124
  while (masked[end] === marker) end += 1;
95
125
  const length = end - index;
126
+ const at = index;
96
127
  const before = index > 0 ? masked[index - 1] : '';
97
128
  const after = end < masked.length ? masked[end] : '';
98
129
  const beforeSpace = isMarkdownSpace(before);
@@ -102,16 +133,26 @@ function scanEmphasisRuns(masked) {
102
133
  const left = !afterSpace && (!afterPunctuation || beforeSpace || beforePunctuation);
103
134
  const right = !beforeSpace && (!beforePunctuation || afterSpace || afterPunctuation);
104
135
  if (marker === '~') {
105
- if (length >= 2) runs.push({ marker, length: 2, canOpen: left, canClose: right });
136
+ // A single tilde is inert, but at the end it may be half of `~~`.
137
+ runs.push({
138
+ marker,
139
+ length: Math.min(length, 2),
140
+ canOpen: left && length >= 2,
141
+ canClose: right && length >= 2,
142
+ at,
143
+ end,
144
+ });
106
145
  } else if (marker === '_') {
107
146
  runs.push({
108
147
  marker,
109
148
  length,
110
149
  canOpen: left && (!right || beforePunctuation),
111
150
  canClose: right && (!left || afterPunctuation),
151
+ at,
152
+ end,
112
153
  });
113
154
  } else {
114
- runs.push({ marker, length, canOpen: left, canClose: right });
155
+ runs.push({ marker, length, canOpen: left, canClose: right, at, end });
115
156
  }
116
157
  index = end;
117
158
  }
@@ -120,7 +161,9 @@ function scanEmphasisRuns(masked) {
120
161
 
121
162
  function closeEmphasis(text) {
122
163
  const open = [];
123
- for (const run of scanEmphasisRuns(maskCode(text))) {
164
+ const runs = scanEmphasisRuns(maskCode(text));
165
+ const last = runs[runs.length - 1];
166
+ for (const run of runs) {
124
167
  let length = run.length;
125
168
  while (run.canClose && length > 0) {
126
169
  let match = -1;
@@ -137,13 +180,21 @@ function closeEmphasis(text) {
137
180
  length -= used;
138
181
  open.length = opener.length > 0 ? match + 1 : match;
139
182
  }
183
+ // A run ending the text that closed nothing has no content after it yet:
184
+ // it painted as literal `**` until the next token turned it into style.
185
+ if (run === last && run.end === text.length && length === run.length) {
186
+ return closeEmphasis(text.slice(0, run.at));
187
+ }
140
188
  if (length > 0 && run.canOpen) open.push({ marker: run.marker, length });
141
189
  }
142
- let healed = text;
190
+ // Closers go before trailing whitespace: `**word ` closed after the space
191
+ // could not close (a closing run must follow non-space) and stayed literal.
192
+ const body = text.trimEnd();
193
+ let closers = '';
143
194
  for (let index = open.length - 1; index >= 0; index -= 1) {
144
- healed += open[index].marker.repeat(Math.min(open[index].length, 3));
195
+ closers += open[index].marker.repeat(Math.min(open[index].length, 3));
145
196
  }
146
- return healed;
197
+ return closers ? `${body}${closers}${text.slice(body.length)}` : text;
147
198
  }
148
199
 
149
200
  function linkDestinationEnd(text, start) {
@@ -246,8 +297,9 @@ function trimPendingTableHead(text) {
246
297
  export function healStreamingMarkdownTail(text, isPendingLocalPath) {
247
298
  const source = String(text ?? '');
248
299
  const fence = source.includes('`') || source.includes('~') ? openFence(source) : null;
249
- if (fence) return trimPartialClosingFence(source, fence);
250
- const value = source.includes('|') ? trimPendingTableHead(source) : source;
300
+ if (fence) return trimPartialOpeningFence(trimPartialClosingFence(source, fence), fence);
301
+ const unmarked = trimPendingBlockMarker(source);
302
+ const value = unmarked.includes('|') ? trimPendingTableHead(unmarked) : unmarked;
251
303
  const hasSyntax = HEALABLE_MARKDOWN_SYNTAX.test(value);
252
304
  if (!value || (!hasSyntax && !isPendingLocalPath)) return value;
253
305
  const healed = hasSyntax
@@ -1 +0,0 @@
1
- export * from '../../../shared/llm/model-pricing-rates.mjs';
@@ -1,346 +0,0 @@
1
- import { stat } from 'node:fs/promises';
2
- import { isProcessAlive } from '../store/paths-heartbeat.mjs';
3
- import {
4
- isCompletionNotificationEntry,
5
- isStaleUserInjection,
6
- lateDeliveryText,
7
- normalizePendingMessageEntry,
8
- pendingMessageId,
9
- pendingMessageText,
10
- } from './pending-message-entry.mjs';
11
- import { isInternalRuntimeNotificationText } from './prompt-utils.mjs';
12
- import { lifecycleTokenClosed } from './pending-lifecycle-epoch.mjs';
13
-
14
- const HANDOFF_RETRY_MS = 1000;
15
- const HANDOFF_RELEASE_SLACK_MS = 50;
16
-
17
- /**
18
- * One session's spool queue, split into what this process takes and what stays
19
- * on disk. A foreign user message is taken (and parked with a handoff stamp
20
- * until the consumer owns a copy); an entry already handed off stays until its
21
- * release window expires or its owner is gone; everything else is kept.
22
- *
23
- * Appends to `request.taken` / `request.released`, tightens
24
- * `request.rescanDueAt` to the earliest live handoff deadline, and returns the
25
- * entries the queue keeps.
26
- */
27
- function takeForeignMessagesFromQueue(queue, request, handoffReleaseMs) {
28
- const now = Date.now();
29
- const kept = [];
30
- for (const entry of queue) {
31
- const id = pendingMessageId(entry);
32
- const handoffAt = Number(entry?.handoffAt) || 0;
33
- const handoffPid = Number(entry?.handoffPid) || 0;
34
- if (handoffAt > 0) {
35
- const dueAt = handoffAt + handoffReleaseMs;
36
- const expired = now >= dueAt;
37
- if (!expired) {
38
- request.rescanDueAt = request.rescanDueAt === 0 ? dueAt : Math.min(request.rescanDueAt, dueAt);
39
- }
40
- if (handoffPid === process.pid) {
41
- if (expired) {
42
- if (id) request.released.push(id);
43
- continue;
44
- }
45
- kept.push(entry);
46
- continue;
47
- }
48
- if (!expired || isProcessAlive(handoffPid)) {
49
- kept.push(entry);
50
- continue;
51
- }
52
- }
53
- const text = pendingMessageText(entry);
54
- const foreignUser =
55
- id &&
56
- !request.localIds.has(id) &&
57
- !isCompletionNotificationEntry(entry) &&
58
- text &&
59
- !isInternalRuntimeNotificationText(text);
60
- if (!foreignUser) {
61
- kept.push(entry);
62
- continue;
63
- }
64
- const normalized = normalizePendingMessageEntry(entry);
65
- const structured = Array.isArray(normalized?.content) || Boolean(normalized?.options);
66
- let takenText = text;
67
- let content = normalized?.content ?? text;
68
- if (isStaleUserInjection(entry)) {
69
- takenText = lateDeliveryText(text, entry);
70
- content = Array.isArray(normalized?.content)
71
- ? [{ type: 'text', text: takenText.slice(0, takenText.length - text.length) }, ...normalized.content]
72
- : takenText;
73
- }
74
- request.taken.push({
75
- ...(structured ? { content } : {}),
76
- text: takenText,
77
- id,
78
- ...(normalized?.options ? { options: normalized.options } : {}),
79
- });
80
- // Park rather than delete until the consumer owns a copy.
81
- kept.push({ ...entry, handoffAt: now, handoffPid: process.pid });
82
- }
83
- return kept;
84
- }
85
-
86
- /**
87
- * Owns cross-process pending-message polling and the durable two-phase handoff.
88
- * Queue storage and lifecycle authority stay in the parent pending-message
89
- * service and are supplied as narrow callbacks.
90
- */
91
- export class ForeignPendingMessageController {
92
- constructor(dependencies) {
93
- this._dependencies = dependencies;
94
- this._scanLimit = Math.max(128, Number(process.env.MIXDOG_FOREIGN_SPOOL_SCAN_LIMIT) || 512);
95
- this._handoffReleaseMs = Math.max(1000, Number(process.env.MIXDOG_FOREIGN_HANDOFF_RELEASE_MS) || 10000);
96
- this._releaseTimers = new Map();
97
- this._drainRequests = new Map();
98
- this._scanMemo = new Map();
99
- this._drainScheduled = false;
100
- this._drainRunning = false;
101
- }
102
-
103
- cancelHandoffRelease(sessionId) {
104
- const existing = this._releaseTimers.get(sessionId);
105
- if (existing) {
106
- try {
107
- clearTimeout(existing.timer);
108
- } catch {
109
- /* best-effort */
110
- }
111
- }
112
- this._releaseTimers.delete(sessionId);
113
- }
114
-
115
- async drainUserInjections(sessionId) {
116
- const { currentLifecycleToken, isValidSessionId } = this._dependencies;
117
- if (!isValidSessionId(sessionId)) return [];
118
- // One durable read decides both the epoch and the tombstone refusal.
119
- const epochToken = currentLifecycleToken(sessionId);
120
- if (lifecycleTokenClosed(epochToken)) return [];
121
- return new Promise((resolve) => {
122
- const existing = this._drainRequests.get(sessionId);
123
- if (existing && existing.epochToken === epochToken) {
124
- existing.waiters.push(resolve);
125
- } else {
126
- if (existing) this._settleDrain(existing, []);
127
- this._drainRequests.set(sessionId, {
128
- sessionId,
129
- epochToken,
130
- waiters: [resolve],
131
- localIds: null,
132
- taken: [],
133
- released: [],
134
- rescanDueAt: 0,
135
- lifecycleDecided: false,
136
- });
137
- }
138
- this._scheduleDrainBatch();
139
- });
140
- }
141
-
142
- _scheduleHandoffRelease(sessionId, delayMs = this._handoffReleaseMs) {
143
- const { isValidSessionId } = this._dependencies;
144
- if (!isValidSessionId(sessionId)) return;
145
- const delay = Math.max(1, Number(delayMs) || 0);
146
- const dueAt = Date.now() + delay;
147
- const existing = this._releaseTimers.get(sessionId);
148
- if (existing) {
149
- if (existing.dueAt <= dueAt) return;
150
- try {
151
- clearTimeout(existing.timer);
152
- } catch {
153
- /* best-effort */
154
- }
155
- }
156
- const timer = setTimeout(() => {
157
- this._releaseTimers.delete(sessionId);
158
- void this._releaseExpiredHandoffs(sessionId);
159
- }, delay);
160
- // The row is durable; cleanup must not keep a shutting-down process open.
161
- try {
162
- timer.unref?.();
163
- } catch {
164
- /* ignore */
165
- }
166
- this._releaseTimers.set(sessionId, { timer, dueAt });
167
- }
168
-
169
- _releaseExpiredHandoffs(sessionId) {
170
- const {
171
- chainSpoolTail,
172
- currentLifecycleToken,
173
- getSpoolTail,
174
- isValidSessionId,
175
- lifecycleEpochMoved,
176
- normalizeStore,
177
- removeInDeliveryIds,
178
- setSpoolQueue,
179
- updateSpool,
180
- warn,
181
- } = this._dependencies;
182
- if (!isValidSessionId(sessionId)) return Promise.resolve(0);
183
- const epochToken = currentLifecycleToken(sessionId);
184
- const released = [];
185
- let nextDueIn = 0;
186
- const preceding = getSpoolTail(sessionId) || Promise.resolve();
187
- const operation = preceding
188
- .catch(() => {})
189
- .then(() =>
190
- updateSpool(sessionId, (raw) => {
191
- released.length = 0;
192
- nextDueIn = 0;
193
- // A generation move transfers ownership; never clean the new queue.
194
- if (lifecycleEpochMoved(sessionId, epochToken)) return undefined;
195
- const next = normalizeStore(raw);
196
- const queue = Array.isArray(next.sessions[sessionId]) ? next.sessions[sessionId] : [];
197
- if (queue.length === 0) return undefined;
198
- const now = Date.now();
199
- const kept = [];
200
- for (const entry of queue) {
201
- const handoffAt = Number(entry?.handoffAt) || 0;
202
- const handoffPid = Number(entry?.handoffPid) || 0;
203
- if (handoffAt > 0 && handoffPid === process.pid) {
204
- const remaining = this._handoffReleaseMs - (now - handoffAt);
205
- if (remaining <= 0) {
206
- const id = pendingMessageId(entry);
207
- if (id) released.push(id);
208
- continue;
209
- }
210
- nextDueIn = nextDueIn === 0 ? remaining : Math.min(nextDueIn, remaining);
211
- }
212
- kept.push(entry);
213
- }
214
- if (released.length === 0) return undefined;
215
- setSpoolQueue(next, sessionId, kept);
216
- next.updatedAt = now;
217
- return next;
218
- })
219
- )
220
- .then(() => {
221
- if (released.length > 0) removeInDeliveryIds(sessionId, released);
222
- if (nextDueIn > 0) {
223
- this._scheduleHandoffRelease(sessionId, nextDueIn + HANDOFF_RELEASE_SLACK_MS);
224
- }
225
- return released.length;
226
- })
227
- .catch((err) => {
228
- warn(`[session] foreign-injection handoff release failed sessionId=${sessionId}: ${err?.message || err}\n`);
229
- // The rows remain durable, so contention and I/O failures retry.
230
- this._scheduleHandoffRelease(sessionId, HANDOFF_RETRY_MS);
231
- return 0;
232
- });
233
- return chainSpoolTail(sessionId, operation);
234
- }
235
-
236
- _rememberScan(sessionId, mtime, rescanDueAt) {
237
- this._scanMemo.delete(sessionId);
238
- this._scanMemo.set(sessionId, { mtime, rescanDueAt: Number(rescanDueAt) || 0 });
239
- while (this._scanMemo.size > this._scanLimit) {
240
- const oldest = this._scanMemo.keys().next().value;
241
- if (oldest === undefined) break;
242
- this._scanMemo.delete(oldest);
243
- }
244
- }
245
-
246
- _scanNeeded(sessionId, mtime, now) {
247
- const memo = this._scanMemo.get(sessionId);
248
- if (!memo || memo.mtime !== mtime) return true;
249
- return memo.rescanDueAt > 0 && now >= memo.rescanDueAt;
250
- }
251
-
252
- _settleDrain(request, value) {
253
- for (const resolve of request.waiters) {
254
- try {
255
- resolve(value);
256
- } catch {
257
- /* a consumer cannot break the batch */
258
- }
259
- }
260
- }
261
-
262
- _scheduleDrainBatch() {
263
- if (this._drainScheduled || this._drainRunning || this._drainRequests.size === 0) return;
264
- this._drainScheduled = true;
265
- setImmediate(() => {
266
- this._drainScheduled = false;
267
- void this._flushDrainBatch();
268
- });
269
- }
270
-
271
- async _flushDrainBatch() {
272
- if (this._drainRunning) return;
273
- this._drainRunning = true;
274
- const batch = [...this._drainRequests.values()];
275
- this._drainRequests.clear();
276
- try {
277
- // Each session drains against its own shard and lock, so one busy
278
- // session never delays (or fails) another's intake.
279
- await Promise.all(batch.map((request) => this._drainOne(request)));
280
- } finally {
281
- this._drainRunning = false;
282
- this._scheduleDrainBatch();
283
- }
284
- }
285
-
286
- async _drainOne(request) {
287
- const {
288
- addInDeliveryIds,
289
- lifecycleInvalidated,
290
- localIds,
291
- normalizeStore,
292
- removeInDeliveryIds,
293
- setSpoolQueue,
294
- spoolPath,
295
- updateSpool,
296
- warn,
297
- } = this._dependencies;
298
- const { sessionId, epochToken } = request;
299
- try {
300
- let mtime = 0;
301
- try {
302
- mtime = (await stat(spoolPath(sessionId))).mtimeMs || 0;
303
- } catch {
304
- this._settleDrain(request, []);
305
- return;
306
- }
307
- if (!this._scanNeeded(sessionId, mtime, Date.now()) || lifecycleInvalidated(sessionId, epochToken)) {
308
- this._settleDrain(request, []);
309
- return;
310
- }
311
- request.localIds = localIds(sessionId);
312
- request.taken = [];
313
- request.released = [];
314
- request.rescanDueAt = 0;
315
- request.lifecycleDecided = false;
316
- await updateSpool(
317
- sessionId,
318
- (raw) => {
319
- const next = normalizeStore(raw);
320
- if (lifecycleInvalidated(sessionId, epochToken)) return undefined;
321
- request.lifecycleDecided = true;
322
- const queue = Array.isArray(next.sessions[sessionId]) ? next.sessions[sessionId] : [];
323
- if (queue.length === 0) return undefined;
324
- const kept = takeForeignMessagesFromQueue(queue, request, this._handoffReleaseMs);
325
- if (request.taken.length === 0 && request.released.length === 0) return undefined;
326
- setSpoolQueue(next, sessionId, kept);
327
- next.updatedAt = Date.now();
328
- return next;
329
- },
330
- { timeoutMs: 0 }
331
- );
332
- if (request.lifecycleDecided) this._rememberScan(sessionId, mtime, request.rescanDueAt);
333
- if (request.taken.length > 0) {
334
- addInDeliveryIds(sessionId, request.taken.map((item) => item?.id).filter(Boolean));
335
- this._scheduleHandoffRelease(sessionId, this._handoffReleaseMs + HANDOFF_RELEASE_SLACK_MS);
336
- }
337
- if (request.released.length > 0) removeInDeliveryIds(sessionId, request.released);
338
- this._settleDrain(request, request.taken);
339
- } catch (err) {
340
- if (err?.code !== 'ELOCKCONTENDED') {
341
- warn(`[session] foreign-injection drain failed: ${err?.message || err}\n`);
342
- }
343
- this._settleDrain(request, []);
344
- }
345
- }
346
- }