mixdog 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. package/README.md +7 -5
  2. package/package.json +1 -1
  3. package/scripts/gate-local.mjs +19 -3
  4. package/scripts/model-catalog-audit.mjs +1 -15
  5. package/src/agents/reviewer/AGENT.md +3 -3
  6. package/src/agents/reviewer/agent.json +1 -1
  7. package/src/defaults/shipped-history.json +5 -0
  8. package/src/defaults/skills/pptx/SKILL.md +6 -6
  9. package/src/defaults/skills/pptx/references/review.md +6 -4
  10. package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
  11. package/src/defaults/skills/setup/references/actions.md +13 -3
  12. package/src/defaults/skills/visualize/SKILL.md +12 -9
  13. package/src/repl/slash-commands.mjs +16 -1
  14. package/src/rules/shared/60-verification.md +3 -1
  15. package/src/rules/shared/70-delivery.md +4 -2
  16. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
  17. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
  18. package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
  19. package/src/runtime/agent/orchestrator/config.mjs +10 -4
  20. package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
  21. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
  22. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
  23. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
  24. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
  25. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
  26. package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
  27. package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
  28. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
  29. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
  30. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
  31. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
  32. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
  33. package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
  34. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
  35. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
  36. package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
  41. package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
  42. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
  43. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
  44. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
  45. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
  46. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
  49. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
  50. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
  51. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
  52. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
  53. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
  56. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
  58. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
  59. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
  60. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
  61. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
  63. package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
  65. package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
  66. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
  67. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
  68. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
  73. package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
  74. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
  75. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
  76. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
  77. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
  78. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
  79. package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
  80. package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
  81. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
  82. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
  83. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
  84. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
  85. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
  86. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
  87. package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
  88. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  89. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
  90. package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
  91. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
  92. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
  93. package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
  94. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
  95. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
  96. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
  97. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
  98. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
  108. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
  112. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
  113. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
  115. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
  116. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
  117. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
  119. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
  120. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
  121. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
  122. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
  123. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
  125. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
  126. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
  127. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
  128. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
  129. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
  130. package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
  132. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
  133. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
  134. package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
  135. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
  136. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
  137. package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
  138. package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
  139. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
  140. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
  141. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
  142. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
  143. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
  146. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
  147. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
  148. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
  149. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
  150. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +268 -181
  151. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
  152. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
  153. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
  154. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
  155. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
  156. package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
  157. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
  158. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
  159. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
  160. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
  161. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
  162. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
  163. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
  164. package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
  165. package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
  166. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
  167. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
  169. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
  170. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
  171. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
  172. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
  173. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
  174. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
  175. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
  176. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
  177. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
  178. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
  179. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
  181. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
  182. package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
  183. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
  184. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
  185. package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
  186. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
  187. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
  188. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
  189. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
  190. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +819 -0
  191. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
  192. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
  193. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
  194. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
  195. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
  196. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
  197. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
  198. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
  199. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  200. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
  201. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
  202. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
  203. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
  205. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
  206. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
  207. package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
  208. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
  209. package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
  210. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
  211. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
  212. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
  213. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
  214. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
  215. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
  216. package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
  217. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
  219. package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
  220. package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
  221. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
  222. package/src/runtime/attachments/store.d.mts +3 -0
  223. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
  224. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
  225. package/src/runtime/channels/lib/worker-main.mjs +17 -14
  226. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
  227. package/src/runtime/effort-judge/judge-client.mjs +56 -18
  228. package/src/runtime/memory/lib/memory.mjs +1 -1
  229. package/src/runtime/memory/lib/pg/process.mjs +34 -24
  230. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
  231. package/src/runtime/memory/lib/session-ingest.mjs +2 -2
  232. package/src/runtime/office/README.md +1 -1
  233. package/src/runtime/office/shared/values.mjs +0 -5
  234. package/src/runtime/shared/atomic-file.mjs +25 -4
  235. package/src/runtime/shared/background-tasks.mjs +92 -14
  236. package/src/runtime/shared/err-text.mjs +25 -0
  237. package/src/runtime/shared/error-presentation.mjs +159 -19
  238. package/src/runtime/shared/extension-scopes.mjs +5 -3
  239. package/src/runtime/shared/file-lock.mjs +37 -11
  240. package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
  241. package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
  242. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
  243. package/src/runtime/shared/llm/model-catalog.mjs +53 -52
  244. package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
  245. package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
  246. package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
  247. package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
  248. package/src/runtime/shared/model-display.mjs +13 -0
  249. package/src/runtime/shared/plugin-manifest.mjs +18 -9
  250. package/src/runtime/shared/pristine-execution-contract.json +9 -2
  251. package/src/runtime/shared/pristine-execution.mjs +28 -4
  252. package/src/runtime/shared/provider-accounts.mjs +124 -20
  253. package/src/runtime/shared/provider-api-key.mjs +12 -0
  254. package/src/runtime/shared/quota-resume-store.mjs +11 -0
  255. package/src/runtime/shared/session-baseline-store.mjs +960 -0
  256. package/src/runtime/shared/shell-display.mjs +9 -3
  257. package/src/runtime/shared/skill-mentions.d.mts +10 -0
  258. package/src/runtime/shared/skill-mentions.mjs +133 -0
  259. package/src/runtime/shared/skill-script-runtime.mjs +264 -0
  260. package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
  261. package/src/runtime/shared/task-notification-envelope.mjs +2 -2
  262. package/src/runtime/shared/tool-primitives.mjs +35 -2
  263. package/src/runtime/shared/turn-changes.mjs +447 -219
  264. package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
  265. package/src/runtime/shared/turn-snapshot.mjs +170 -48
  266. package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
  267. package/src/runtime/shared/worker-requests.mjs +15 -2
  268. package/src/runtime/shared/worktrees/contract.mjs +0 -24
  269. package/src/runtime/shared/worktrees/test-support.mjs +19 -4
  270. package/src/session-runtime/automation-agents.mjs +8 -2
  271. package/src/session-runtime/boot/apis.mjs +61 -0
  272. package/src/session-runtime/boot/config.mjs +5 -2
  273. package/src/session-runtime/boot/facade.mjs +1 -0
  274. package/src/session-runtime/boot/infrastructure.mjs +35 -18
  275. package/src/session-runtime/conversation-import/discovery.mjs +698 -0
  276. package/src/session-runtime/conversation-import/service.mjs +369 -0
  277. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
  278. package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
  279. package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
  280. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  281. package/src/session-runtime/mcp-glue/connect.mjs +83 -16
  282. package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
  283. package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
  284. package/src/session-runtime/mcp-glue.mjs +25 -2
  285. package/src/session-runtime/mcp-oauth-login.mjs +174 -0
  286. package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
  287. package/src/session-runtime/model-route/set-route.mjs +83 -15
  288. package/src/session-runtime/model-route/web-search-route.mjs +1 -1
  289. package/src/session-runtime/native-web-search/routes.mjs +22 -3
  290. package/src/session-runtime/new-session-config.mjs +3 -2
  291. package/src/session-runtime/notification-bus.mjs +9 -2
  292. package/src/session-runtime/provider-auth/accounts.mjs +33 -15
  293. package/src/session-runtime/provider-models/model-meta.mjs +12 -3
  294. package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
  295. package/src/session-runtime/provider-readiness.mjs +16 -10
  296. package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
  297. package/src/session-runtime/quick-web-search-models.mjs +13 -38
  298. package/src/session-runtime/resource-extension-sync.mjs +24 -5
  299. package/src/session-runtime/resource-mcp-api.mjs +198 -78
  300. package/src/session-runtime/resource-plugins-api.mjs +29 -41
  301. package/src/session-runtime/resource-scope-decorate.mjs +6 -8
  302. package/src/session-runtime/resource-skills-api.mjs +23 -2
  303. package/src/session-runtime/runtime-review-api.mjs +13 -0
  304. package/src/session-runtime/schedule-session-run.mjs +1 -1
  305. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
  306. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
  307. package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
  308. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
  309. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
  310. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
  311. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
  312. package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
  313. package/src/session-runtime/services/channel-session-router.mjs +4 -1
  314. package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
  315. package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
  316. package/src/session-runtime/services/provider-admin.mjs +64 -18
  317. package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
  318. package/src/session-runtime/settings-compaction-api.mjs +1 -0
  319. package/src/session-runtime/setup-tool/executor.mjs +12 -1
  320. package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
  321. package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
  322. package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
  323. package/src/session-runtime/skills-api.mjs +7 -3
  324. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  325. package/src/session-runtime/webhook-session-run.mjs +16 -4
  326. package/src/skill-script-entry.mjs +36 -0
  327. package/src/standalone/daemon-drain-policy.mjs +8 -0
  328. package/src/standalone/daemon-stored-session-views.mjs +11 -3
  329. package/src/standalone/daemon-telemetry.mjs +55 -0
  330. package/src/standalone/daemon.mjs +44 -11
  331. package/src/standalone/session-protocol.mjs +12 -0
  332. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
  333. package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
  334. package/src/standalone/session-service/agent-tree.mjs +12 -0
  335. package/src/standalone/session-service/quota-resume.mjs +8 -0
  336. package/src/standalone/session-service/retention/busy.mjs +15 -1
  337. package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
  338. package/src/standalone/session-service-api.mjs +5 -0
  339. package/src/standalone/session-service.mjs +1 -0
  340. package/src/tui/App.jsx +9 -1
  341. package/src/tui/app/app-view/floating-panel.jsx +9 -1
  342. package/src/tui/app/app-view.jsx +7 -0
  343. package/src/tui/app/create-app-pickers.mjs +4 -0
  344. package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
  345. package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
  346. package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
  347. package/src/tui/app/extension-pickers.mjs +2 -1
  348. package/src/tui/app/model-options.mjs +13 -16
  349. package/src/tui/app/skill-mention-palette.mjs +88 -0
  350. package/src/tui/app/slash-commands.mjs +7 -2
  351. package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
  352. package/src/tui/app/slash-palette.mjs +23 -7
  353. package/src/tui/app/transcript-row-estimate.mjs +11 -3
  354. package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
  355. package/src/tui/app/use-prompt-state.mjs +5 -0
  356. package/src/tui/components/Message.jsx +22 -1
  357. package/src/tui/components/PromptInput.jsx +21 -3
  358. package/src/tui/components/SlashCommandPalette.jsx +12 -3
  359. package/src/tui/components/StatusLine.jsx +2 -0
  360. package/src/tui/components/TranscriptItem.jsx +9 -1
  361. package/src/tui/components/prompt-input/key-handler.mjs +21 -8
  362. package/src/tui/components/status-line/local-line.mjs +5 -2
  363. package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
  364. package/src/tui/components/user-message-skills.mjs +38 -0
  365. package/src/tui/dist/index.mjs +1323 -214
  366. package/src/tui/session/queue-helpers.mjs +7 -2
  367. package/src/tui/session/quota-resume.mjs +46 -14
  368. package/src/tui/session/session-api/commands.mjs +33 -24
  369. package/src/tui/session/session-api/extensions.mjs +26 -2
  370. package/src/tui/session/session-api/integrations.mjs +7 -0
  371. package/src/tui/session/session-api/lifecycle.mjs +5 -1
  372. package/src/tui/session/session-api/routes.mjs +71 -7
  373. package/src/tui/session/session-api/settings.mjs +12 -14
  374. package/src/tui/session/session-flow/drain.mjs +21 -5
  375. package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
  376. package/src/tui/session/tui-steering-persist.mjs +25 -9
  377. package/src/tui/session/turn.mjs +55 -15
  378. package/src/tui/statusline-ansi-bridge.mjs +1 -1
  379. package/src/ui/statusline-agents.mjs +15 -4
  380. package/src/ui/statusline.mjs +7 -3
  381. package/src/ui/streaming-markdown-heal.mjs +34 -3
  382. package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
  383. package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
  384. package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
  385. package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
  386. package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
@@ -15,6 +15,10 @@ import { preserveGoalStateAfterTurn } from './goal-turn-state.mjs';
15
15
  export { preserveGoalStateAfterTurn } from './goal-turn-state.mjs';
16
16
  export { transcriptToolCallDisplayMode } from './turn-tool-cards.mjs';
17
17
  import { isRejected429, safeErrorDetails } from '../../runtime/shared/error-presentation.mjs';
18
+ import {
19
+ QUOTA_KINDS,
20
+ providerErrorKind,
21
+ } from '../../runtime/agent/orchestrator/providers/provider-error-kind.mjs';
18
22
  import { registerTaskWaitSteeringCheck } from '../../runtime/agent/orchestrator/session/task-wait-control.mjs';
19
23
  import { promptDisplayText, STEERING_SUPPRESSED_DISPLAY } from './queue-helpers.mjs';
20
24
  import { yieldToRenderer } from './render-timing.mjs';
@@ -47,14 +51,11 @@ import {
47
51
  startLiveTail,
48
52
  } from './turn-tool-cards.mjs';
49
53
 
50
- function isUsageLimitError(error) {
54
+ // A usage limit is exactly a spent quota, a plan-gated feature or a billing
55
+ // refusal; overloads, rate limits and server faults recover by waiting.
56
+ function isUsageLimitError(error, kind = providerErrorKind(error)) {
51
57
  if (!error || isRejected429(error)) return false;
52
- const status = Number(error?.httpStatus || error?.status || error?.response?.status || 0);
53
- if (error?.providerQuota === true || error?.quotaExceeded === true || status === 429) return true;
54
- const text = String(error?.message || error);
55
- return /\brate[_ -]?limit\b|\bquota\b|too many requests|resource exhausted|insufficient_quota|quota_exceeded/i.test(
56
- text
57
- );
58
+ return QUOTA_KINDS.has(kind.kind);
58
59
  }
59
60
 
60
61
  function turnOutcome(cancelled, failed) {
@@ -165,7 +166,7 @@ function promptRestoreFor(displayText, options, submittedIds, content = null) {
165
166
  };
166
167
  }
167
168
 
168
- function commitPromptRestore(flags, turn) {
169
+ export function commitPromptRestore(flags, turn) {
169
170
  const restore = flags.activePromptRestore;
170
171
  if (!restore) return;
171
172
  if (!turn.promptCommitted && typeof restore.onCommitted === 'function') {
@@ -322,9 +323,26 @@ function applyTurnUsageDelta({ turn, getState, set, syncContextStats }, delta) {
322
323
  set({ stats: { ...getState().stats }, ...(spinner ? { spinner: { ...spinner, inputTokens, outputTokens } } : {}) });
323
324
  }
324
325
 
326
+ // The runtime reports the skills a user turn actually loaded (`Skill:` header
327
+ // or inline `$name`); the prompt row carries them as `appliedSkills`, the same
328
+ // field a restored row reads from the persisted transcript metadata.
329
+ function applySkillsToPromptRow({ turn, getState, patchItem }, names, detail = {}) {
330
+ const appliedSkills = (Array.isArray(names) ? names : []).filter((name) => typeof name === 'string' && name);
331
+ if (!appliedSkills.length) return;
332
+ const messageId = typeof detail?.messageId === 'string' ? detail.messageId : '';
333
+ const submitted = turn.submittedIds[0];
334
+ const row = getState().items.findLast(
335
+ (item) => item?.kind === 'user' && (messageId ? item.messageId === messageId : item.id === submitted)
336
+ );
337
+ if (row) patchItem(row.id, { appliedSkills });
338
+ }
339
+
325
340
  function turnHandlers(ctx) {
326
341
  const { isCurrentTurn, drainPendingSteering } = ctx;
327
342
  return {
343
+ onSkillsApplied: (names, detail) => {
344
+ if (isCurrentTurn()) applySkillsToPromptRow(ctx, names, detail);
345
+ },
328
346
  drainSteering: (_sessionId, drainOptions) =>
329
347
  isCurrentTurn() ? drainPendingSteering({ ...drainOptions, turnEpoch: ctx.turn.epoch }) : [],
330
348
  onStreamDelta: () => {},
@@ -372,7 +390,7 @@ function toolHandlers(ctx) {
372
390
  };
373
391
  }
374
392
 
375
- function streamHandlers(ctx) {
393
+ export function streamHandlers(ctx) {
376
394
  const { isCurrentTurn, stream } = ctx;
377
395
  return {
378
396
  onStageChange: async (stage, detail = null) => {
@@ -381,7 +399,10 @@ function streamHandlers(ctx) {
381
399
  onTextDelta: (chunk) => {
382
400
  const textChunk = String(chunk ?? '');
383
401
  if (!textChunk || !isCurrentTurn()) return;
384
- ctx.markPromptCommitted();
402
+ // Same verdict as the runtime's interruption check (finalizeInterruptedTurn
403
+ // trims): whitespace-only text is not output, so it must not commit the
404
+ // prompt — the runtime would rewind it while the host skipped the requeue.
405
+ if (textChunk.trim()) ctx.markPromptCommitted();
385
406
  appendTextDelta(stream, textChunk);
386
407
  },
387
408
  onTextReset: (reset = {}) => (isCurrentTurn() ? resetStreamedText(stream, reset) : false),
@@ -431,13 +452,30 @@ export function failTurn(ctx, error) {
431
452
  }
432
453
  turn.failed = true;
433
454
  cards.aggregates.finalizeToolHeaders();
434
- turn.usageLimited = isUsageLimitError(error);
455
+ // Presentation only: legacy untyped failure text may still name a usage limit.
456
+ const errorKind = providerErrorKind(error, { legacyQuotaWording: true });
457
+ // The UI reads this descriptor instead of re-parsing the error text.
458
+ turn.errorKind = {
459
+ kind: errorKind.kind,
460
+ code: errorKind.code,
461
+ status: errorKind.status,
462
+ retryAfterMs: errorKind.retryAfterMs,
463
+ resetAt: errorKind.resetAt,
464
+ };
465
+ turn.usageLimited = isUsageLimitError(error, errorKind);
435
466
  const exhausted = error?.quotaExhausted;
436
- if (exhausted && typeof exhausted === 'object') {
467
+ // Quota metadata: the pool's validated exhaustion, or a spent quota whose
468
+ // provider named the real reset time.
469
+ const resetKnown = errorKind.kind === 'quota_exhausted' && Number.isFinite(errorKind.resetAt);
470
+ if ((exhausted && typeof exhausted === 'object') || resetKnown) {
471
+ const source = exhausted && typeof exhausted === 'object' ? exhausted : {};
472
+ let resetAt = null;
473
+ if (Number.isFinite(source.resetAt)) resetAt = source.resetAt;
474
+ else if (Number.isFinite(errorKind.resetAt)) resetAt = errorKind.resetAt;
437
475
  turn.quota = {
438
- provider: String(exhausted.provider || turn.routeMeta?.provider || ''),
439
- model: String(exhausted.model || turn.routeMeta?.model || ''),
440
- resetAt: Number.isFinite(exhausted.resetAt) ? exhausted.resetAt : null,
476
+ provider: String(source.provider || turn.routeMeta?.provider || ''),
477
+ model: String(source.model || turn.routeMeta?.model || ''),
478
+ resetAt,
441
479
  };
442
480
  }
443
481
  turn.failureDetail = toolErrorDisplay(error, 'turn').replace(/^Error:\s*/i, '');
@@ -468,6 +506,7 @@ export function turnDoneItem({ turn, stream, cards, getState, nextId }) {
468
506
  ...(turn.failureDiagnostic ? { errorDetails: turn.failureDiagnostic } : {}),
469
507
  ...turn.routeMeta,
470
508
  ...(turn.failed && turn.quota ? { quota: turn.quota } : {}),
509
+ ...(turn.failed && turn.errorKind ? { errorKind: turn.errorKind } : {}),
471
510
  };
472
511
  }
473
512
 
@@ -547,6 +586,7 @@ async function settleTurn(ctx) {
547
586
  result: turn.askResult,
548
587
  session: runtime.session || null,
549
588
  error: turn.failureDetail || null,
589
+ errorKind: turn.failed ? turn.errorKind || null : null,
550
590
  };
551
591
  // Publish termination before optional Goal work can delay the caller.
552
592
  bag.settleSteeredSubmissions?.(turn.epoch, detail);
@@ -65,7 +65,7 @@ export function statuslineFooterIdentityChanged(args, lastArgs) {
65
65
  if (!lastArgs) return true;
66
66
  if (args.sessionId !== lastArgs.sessionId) return true;
67
67
  if (args.provider !== lastArgs.provider || args.model !== lastArgs.model) return true;
68
- if (args.effort !== lastArgs.effort || args.fast !== lastArgs.fast) return true;
68
+ if (args.effort !== lastArgs.effort || args.fast !== lastArgs.fast || args.ultra !== lastArgs.ultra) return true;
69
69
  if (args.contextWindow !== lastArgs.contextWindow || args.rawContextWindow !== lastArgs.rawContextWindow) return true;
70
70
  if (args.displayContextWindow !== lastArgs.displayContextWindow) return true;
71
71
  if (args.compactBoundaryTokens !== lastArgs.compactBoundaryTokens) return true;
@@ -25,8 +25,7 @@ let _hiddenStatuslineAgents = null;
25
25
  function normalizeAgentWorkerForStatusline(worker = {}) {
26
26
  const tag = String(worker.tag || worker.agent || worker.name || '').trim();
27
27
  if (!tag) return null;
28
- const statuses = agentStatusValues(worker);
29
- const status = isActiveAgentEntry(statuses) ? 'running' : 'idle';
28
+ const status = isActiveAgentEntry(lifecycleStatuses(worker)) ? 'running' : 'idle';
30
29
  return {
31
30
  tag,
32
31
  status,
@@ -63,11 +62,12 @@ function normalizeAgentJobForStatusline(job = {}) {
63
62
  model: job.model || null,
64
63
  };
65
64
  }
66
- if (!isActiveAgentEntry(statuses)) return null;
65
+ const lifecycle = lifecycleStatuses(job);
66
+ if (!isActiveAgentEntry(lifecycle)) return null;
67
67
  return {
68
68
  tag,
69
69
  taskId,
70
- status: isQueuedAgentEntry(statuses) ? 'queued' : 'running',
70
+ status: isQueuedAgentEntry(lifecycle) ? 'queued' : 'running',
71
71
  startedAtMs,
72
72
  agent: job.agent || null,
73
73
  stage: job.stage || job.workerStatus || job.status || null,
@@ -214,6 +214,17 @@ function agentStatusValues(value = {}) {
214
214
  .filter((status, index, values) => Boolean(status) && values.indexOf(status) === index);
215
215
  }
216
216
 
217
+ /** The statuses that decide whether an entry is working. `status` is the
218
+ * lifecycle; `stage` is the runtime phase copied in beside it, which can read
219
+ * idle/done/error mid-work, so it decides only for an entry with no status. A
220
+ * cancel in either field still counts (it keeps both in play). */
221
+ function lifecycleStatuses(value = {}) {
222
+ const statuses = agentStatusValues(value);
223
+ if (statuses.some((status) => /cancel|killed/i.test(status))) return statuses;
224
+ const status = String(value.status || '').trim();
225
+ return status ? [status] : statuses;
226
+ }
227
+
217
228
  function isTerminalAgentEntry(statuses = []) {
218
229
  return statuses.some((status) => TERMINAL_AGENT_STATUS.test(String(status || '')));
219
230
  }
@@ -197,6 +197,7 @@ export async function renderStatusline({
197
197
  model = '',
198
198
  effort = '',
199
199
  fast = false,
200
+ ultra = false,
200
201
  cwd = '',
201
202
  stats,
202
203
  sessionId,
@@ -223,6 +224,7 @@ export async function renderStatusline({
223
224
  model,
224
225
  effort,
225
226
  fast,
227
+ ultra,
226
228
  cwd,
227
229
  stats,
228
230
  sessionId,
@@ -233,7 +235,7 @@ export async function renderStatusline({
233
235
  ...displayArgs,
234
236
  });
235
237
  } catch {
236
- return fallbackLine({ provider, model, effort, fast, cwd, stats, ...displayArgs });
238
+ return fallbackLine({ provider, model, effort, fast, ultra, cwd, stats, ...displayArgs });
237
239
  }
238
240
  }
239
241
 
@@ -244,6 +246,7 @@ function renderNativeStatusline({
244
246
  model = '',
245
247
  effort = '',
246
248
  fast = false,
249
+ ultra = false,
247
250
  stats,
248
251
  sessionId,
249
252
  contextWindow = 0,
@@ -275,7 +278,7 @@ function renderNativeStatusline({
275
278
 
276
279
  const sep = ` ${D}│${R} `;
277
280
  const l1Parts = [
278
- formatModelSegment({ provider, model, effort, fast, cols }),
281
+ formatModelSegment({ provider, model, effort, fast, ultra, cols }),
279
282
  formatContextSegment(ctxPct, cols, s.currentContextSource),
280
283
  ...quotaSegmentsFor({ provider, model, effort, fast, sessionId, clientHostPid, gatewayStatus, cols }),
281
284
  ].filter(Boolean);
@@ -664,6 +667,7 @@ function fallbackLine({
664
667
  model = '',
665
668
  effort = '',
666
669
  fast = false,
670
+ ultra = false,
667
671
  cwd: _cwd = '',
668
672
  stats,
669
673
  contextWindow = 0,
@@ -687,7 +691,7 @@ function fallbackLine({
687
691
  });
688
692
  const sep = ` ${D}│${R} `;
689
693
  const parts = [
690
- formatModelSegment({ provider, model, effort, fast, cols }),
694
+ formatModelSegment({ provider, model, effort, fast, ultra, cols }),
691
695
  formatContextSegment(ctxPct, cols, s.currentContextSource),
692
696
  ].filter(Boolean);
693
697
  if (!parts.length) return statusSubtle('> mixdog');
@@ -213,12 +213,43 @@ function healIncompleteLink(text, isPendingLocalPath) {
213
213
  return `${prefix}[${closeEmphasis(caption)}${']'.repeat(Math.max(0, depth - 1))}]()`;
214
214
  }
215
215
 
216
+ const PIPE_ROW = /^ {0,3}\|/;
217
+ const DELIMITER_ROW = /^ {0,3}\|?\s*:?-+:?\s*(?:\|\s*:?-+:?\s*)*\|?\s*$/;
218
+ const PARTIAL_DELIMITER_ROW = /^ {0,3}\|?[\s:|-]*$/;
219
+
220
+ function tableCells(line) {
221
+ const cells = line.trim().split(/(?<!\\)\|/);
222
+ if (cells[0].trim() === '') cells.shift();
223
+ if (cells.length && cells[cells.length - 1].trim() === '') cells.pop();
224
+ return cells.length;
225
+ }
226
+
227
+ // A table streams in as its header row, then its delimiter row a token at a
228
+ // time. Until the delimiter is complete (and has the header's cell count) the
229
+ // rows are a paragraph of raw pipes, which then re-laid out as a table of a
230
+ // different height — the reply grew and shrank under a followed transcript.
231
+ // Hold both rows back until the table can form in one step.
232
+ function trimPendingTableHead(text) {
233
+ let offset = 0;
234
+ for (const blank of text.matchAll(/\n[ \t]*\r?\n/g)) offset = blank.index + blank[0].length;
235
+ const block = text.slice(offset);
236
+ const lines = block.split('\n').map((line) => line.replace(/\r$/, ''));
237
+ if (lines.length === 0 || lines.length > 2 || !PIPE_ROW.test(lines[0])) return text;
238
+ if (lines.length === 2) {
239
+ const delimiter = lines[1];
240
+ if (!PARTIAL_DELIMITER_ROW.test(delimiter)) return text;
241
+ if (DELIMITER_ROW.test(delimiter) && tableCells(delimiter) === tableCells(lines[0])) return text;
242
+ }
243
+ return text.slice(0, offset);
244
+ }
245
+
216
246
  export function healStreamingMarkdownTail(text, isPendingLocalPath) {
217
- const value = String(text ?? '');
247
+ const source = String(text ?? '');
248
+ const fence = source.includes('`') || source.includes('~') ? openFence(source) : null;
249
+ if (fence) return trimPartialClosingFence(source, fence);
250
+ const value = source.includes('|') ? trimPendingTableHead(source) : source;
218
251
  const hasSyntax = HEALABLE_MARKDOWN_SYNTAX.test(value);
219
252
  if (!value || (!hasSyntax && !isPendingLocalPath)) return value;
220
- const fence = openFence(value);
221
- if (fence) return trimPartialClosingFence(value, fence);
222
253
  const healed = hasSyntax
223
254
  ? closeEmphasis(healIncompleteLink(closeInlineCode(value, isPendingLocalPath), isPendingLocalPath))
224
255
  : value;
@@ -1,6 +1,8 @@
1
1
  import fs from 'fs';
2
2
  import os from 'os';
3
3
  import path from 'path';
4
+ import { getModelMetadataSync } from '../../../../runtime/shared/llm/model-catalog.mjs';
5
+ import { providerCachedModelsSync } from '../../../../runtime/shared/llm/provider-catalog-cache.mjs';
4
6
 
5
7
  export const CLAUDE_CURRENT_MODE = 'claude-current';
6
8
  export const CLAUDE_CURRENT_CHOICE_ID = 'claude-current';
@@ -95,11 +97,21 @@ function snapshotEquivalent(a, b) {
95
97
  return keys.every(k => (a[k] ?? null) === (b[k] ?? null));
96
98
  }
97
99
 
100
+ // The newest roster model of a family, by the roster's own release stamps.
101
+ function newestRosterModel(family) {
102
+ const stamp = (row) => Date.parse(row.releaseDate) || (Number(row.created) > 0 ? Number(row.created) : 0);
103
+ const rows = providerCachedModelsSync('anthropic-oauth').filter((row) =>
104
+ String(row.id).toLowerCase().startsWith(`claude-${family}-`)
105
+ );
106
+ rows.sort((a, b) => stamp(b) - stamp(a));
107
+ return rows[0]?.id || null;
108
+ }
109
+
98
110
  function familyDefaultModel(family) {
99
111
  const f = String(family || '').toLowerCase();
100
112
  if (!f) return null;
101
113
  const envName = `ANTHROPIC_DEFAULT_${f.toUpperCase()}_MODEL`;
102
- return cleanString(process.env[envName]) || DEFAULT_FAMILY_MODEL[f] || null;
114
+ return cleanString(process.env[envName]) || newestRosterModel(f) || DEFAULT_FAMILY_MODEL[f] || null;
103
115
  }
104
116
 
105
117
  export function stripClaudeContextSuffix(model) {
@@ -109,9 +121,7 @@ export function stripClaudeContextSuffix(model) {
109
121
  function contextWindowFromRawModel(raw, resolved) {
110
122
  const s = cleanString(raw).toLowerCase();
111
123
  if (/\[1m\]/.test(s)) return 1000000;
112
- if (/^claude-(opus|sonnet)-4-(6|7|8)(?:$|-)/i.test(resolved || '')) return 1000000;
113
- if (/^claude-haiku-4-5/i.test(resolved || '')) return 200000;
114
- return null;
124
+ return (resolved && getModelMetadataSync(resolved, 'anthropic-oauth')?.contextWindow) || null;
115
125
  }
116
126
 
117
127
  export function resolveClaudeModelAlias(model) {
@@ -1,162 +0,0 @@
1
- // Pure pre-turn extraction of the previous human request and the assistant
2
- // text around it, from the session history as it stands BEFORE the current
3
- // turn is committed (the boundary resolveTurnAutoEffort runs at). Nothing here
4
- // reads the current prompt's outcome; nothing is mutated; no text is matched
5
- // against word lists. Ownership comes only from typed provenance that the
6
- // runtime already writes (meta.runtimeUserContext, meta.synthetic, meta.source,
7
- // the compaction/skill/reminder predicates in compact/messages.mjs).
8
- //
9
- // Result of previousHumanContext(messages, { retryPrompt }):
10
- // {
11
- // version: 1,
12
- // boundary: number, // messages[0..boundary) were considered
13
- // retryTrimmedIndex: number, // index of the unanswered resubmitted prompt
14
- // // dropped from the view, or -1
15
- // prevHuman: { text, index, source, runtimeContext } | null,
16
- // // latest actual human message before the boundary. `text` is the
17
- // // runtime-context-stripped, trimmed text (untruncated). `source` is
18
- // // meta.source or null ('steering' = a human interjection).
19
- // // `runtimeContext` is 'stripped' | 'none'.
20
- // prevHumanMissing: 'empty-history' | 'no-human-request' | null,
21
- // canonicalReply: { text, index } | null,
22
- // // exactly what the shipped rp `prev` is: the latest non-empty
23
- // // assistant message before the boundary, whatever turn it is from.
24
- // pairedReply: { text, index } | null,
25
- // // latest non-empty assistant text inside prevHuman's own turn span
26
- // // (after prevHuman up to the next human message / boundary). Never
27
- // // falls back to another turn: a tool-only or unanswered turn gives
28
- // // null with pairedMissing set.
29
- // pairedMissing: 'no-human-request' | 'no-assistant-text-in-turn' | null,
30
- // replyIsPaired: boolean, // canonicalReply and pairedReply are the same message
31
- // skipped: [{ index, role, reason }], // user messages passed over after
32
- // // prevHuman's search began (newest first); reasons: 'summary',
33
- // // 'protected-context', 'skill-body', 'synthetic-flag',
34
- // // 'typed-source', 'runtime-owned', 'empty'.
35
- // }
36
- //
37
- // Policy decisions (PREVIOUS_HUMAN_POLICY):
38
- // synthetic meta.synthetic === true, or a source the runtime stores as
39
- // "not the user speaking" (task-notification, skill-context),
40
- // or anything isActualUserInstructionMessage rejects
41
- // (goal-continuation/closeout, compact-*, *-recovery, control
42
- // lines), is skipped, not treated as a request.
43
- // steering meta.source === 'steering' is a human interjection (the
44
- // provider layer keeps it as its own user turn for that
45
- // reason) and counts as a human request.
46
- // retry when retryPrompt repeats the trailing unanswered user prompt
47
- // (trailingUnansweredPromptIndex), that stale copy is excluded
48
- // so the prompt is never its own "previous request".
49
- // summary compact summaries are skipped; nothing before them is
50
- // recovered, so history truncated by compaction yields
51
- // 'no-human-request' rather than a guess.
52
- // Limitation: user messages stored without meta (old transcripts) cannot be
53
- // told apart from the human when a runtime wrapper was never recorded; they
54
- // are accepted as human, and a wrapper with stale provenance stays unstripped.
55
- import { stripRuntimeUserContext } from '../agent/orchestrator/session/runtime-user-context.mjs';
56
- import {
57
- isActualUserInstructionMessage,
58
- isInjectedSkillBodyMessage,
59
- isProtectedContextUserMessage,
60
- isSummaryMessage,
61
- } from '../agent/orchestrator/session/compact/messages.mjs';
62
- import { trailingUnansweredPromptIndex } from '../agent/orchestrator/session/manager/failed-turn-rewind.mjs';
63
- import { promptContentText } from '../agent/orchestrator/session/manager/prompt-utils.mjs';
64
-
65
- export const PREVIOUS_HUMAN_POLICY = Object.freeze({
66
- synthetic: 'skip',
67
- steering: 'human',
68
- retry: 'exclude-trailing-unanswered-copy',
69
- summary: 'skip-no-recovery',
70
- });
71
-
72
- const TYPED_NON_HUMAN_SOURCES = new Set(['task-notification', 'skill-context']);
73
-
74
- const textOf = (message) => promptContentText(message?.content).trim();
75
-
76
- /** { human, reason?, message } for a user message; null for other roles. */
77
- function classify(message) {
78
- if (message?.role !== 'user') return null;
79
- const stripped = stripRuntimeUserContext(message);
80
- const meta = stripped.meta && typeof stripped.meta === 'object' ? stripped.meta : {};
81
- const no = (reason) => ({ human: false, reason, message: stripped });
82
- if (isSummaryMessage(stripped)) return no('summary');
83
- if (isProtectedContextUserMessage(stripped)) return no('protected-context');
84
- if (isInjectedSkillBodyMessage(stripped)) return no('skill-body');
85
- if (meta.synthetic === true) return no('synthetic-flag');
86
- if (TYPED_NON_HUMAN_SOURCES.has(String(meta.source || ''))) return no('typed-source');
87
- if (!isActualUserInstructionMessage(stripped)) return no('runtime-owned');
88
- if (!textOf(stripped)) return no('empty');
89
- return { human: true, message: stripped, stripped: stripped !== message };
90
- }
91
-
92
- function latestAssistant(messages, from, to) {
93
- for (let index = to - 1; index >= from; index -= 1) {
94
- if (messages[index]?.role !== 'assistant') continue;
95
- const text = textOf(messages[index]);
96
- if (text) return { text, index };
97
- }
98
- return null;
99
- }
100
-
101
- export function previousHumanContext(messages, { retryPrompt } = {}) {
102
- const list = Array.isArray(messages) ? messages : [];
103
- const retryTrimmedIndex = retryPrompt == null ? -1 : trailingUnansweredPromptIndex(list, retryPrompt);
104
- const boundary = retryTrimmedIndex >= 0 ? retryTrimmedIndex : list.length;
105
- const verdicts = [];
106
- for (let index = 0; index < boundary; index += 1) verdicts.push(classify(list[index]));
107
-
108
- const skipped = [];
109
- let humanIndex = -1;
110
- for (let index = boundary - 1; index >= 0; index -= 1) {
111
- const verdict = verdicts[index];
112
- if (!verdict) continue;
113
- if (verdict.human) {
114
- humanIndex = index;
115
- break;
116
- }
117
- skipped.push({ index, role: 'user', reason: verdict.reason });
118
- // A summary replaces earlier conversational context; do not recover a
119
- // request from an older retained fragment behind that boundary.
120
- if (verdict.reason === 'summary') break;
121
- }
122
-
123
- const canonicalReply = latestAssistant(list, 0, boundary);
124
- let prevHuman = null;
125
- let pairedReply = null;
126
- let pairedMissing = 'no-human-request';
127
- if (humanIndex >= 0) {
128
- const verdict = verdicts[humanIndex];
129
- const source = verdict.message.meta?.source;
130
- prevHuman = {
131
- text: textOf(verdict.message),
132
- index: humanIndex,
133
- source: typeof source === 'string' && source ? source : null,
134
- runtimeContext: verdict.stripped ? 'stripped' : 'none',
135
- };
136
- let end = boundary;
137
- for (let index = humanIndex + 1; index < boundary; index += 1) {
138
- if (verdicts[index]?.human) {
139
- end = index;
140
- break;
141
- }
142
- }
143
- pairedReply = latestAssistant(list, humanIndex + 1, end);
144
- pairedMissing = pairedReply ? null : 'no-assistant-text-in-turn';
145
- }
146
-
147
- let prevHumanMissing = null;
148
- if (!prevHuman) prevHumanMissing = boundary === 0 ? 'empty-history' : 'no-human-request';
149
-
150
- return {
151
- version: 1,
152
- boundary,
153
- retryTrimmedIndex,
154
- prevHuman,
155
- prevHumanMissing,
156
- canonicalReply,
157
- pairedReply,
158
- pairedMissing,
159
- replyIsPaired: Boolean(pairedReply && canonicalReply && pairedReply.index === canonicalReply.index),
160
- skipped,
161
- };
162
- }
@@ -1,10 +0,0 @@
1
- // Experimental input only. An unavailable verified request preserves rp exactly.
2
- // Ownership and pairing are established by the caller, never inferred here.
3
- export function verifiedContextText({ request, prev, prevRequestVerified } = {}) {
4
- const current = String(request || '').slice(0, 1500);
5
- const reply = String(prev || '').slice(-1000);
6
- const prior = Array.from(String(prevRequestVerified || ''))
7
- .slice(0, 300)
8
- .join('');
9
- return `request: ${current}${prior ? `\nprevious request: ${prior}` : ''}\nprevious reply: ${reply}`;
10
- }
@@ -1,32 +0,0 @@
1
- // Pure, DB-free merge of session-fallback recall rows into the already-ranked
2
- // global hybrid rows. Extracted into its own module so the starve-prevention +
3
- // dedupe contract can be unit-tested without booting the memory worker (which
4
- // has heavy top-level side effects: http server, pg, onnx embedding).
5
- //
6
- // Contract:
7
- // - APPEND session rows, never prepend. Blind prepend lets session rows
8
- // (limit+) starve the global first page and distorts sort/offset/limit.
9
- // - Re-apply the SAME sort policy as the global path so global hybrid hits
10
- // (carrying a real retrievalScore) keep their rank; session rows
11
- // (retrievalScore 0 under importance, ts-ordered under date) only fill
12
- // genuinely open slots.
13
- // - Dedupe drops any session row whose id already appears as a global row OR
14
- // as a global root's inlined chunk member (prevents member/leaf double
15
- // output).
16
- import { compareRecallByScore, compareRecallNewestFirst } from './recall-order.mjs';
17
-
18
- export function mergeSessionRowsIntoGlobal(globalRows, sessionRows, { sort = 'importance' } = {}) {
19
- const filtered = Array.isArray(globalRows) ? [...globalRows] : [];
20
- if (!Array.isArray(sessionRows) || sessionRows.length === 0) return filtered;
21
- const seen = new Set(filtered.map((r) => Number(r.id)));
22
- for (const r of filtered) {
23
- if (Array.isArray(r.members)) {
24
- for (const m of r.members) seen.add(Number(m.id));
25
- }
26
- }
27
- const merged = sessionRows.filter((r) => !seen.has(Number(r.id)));
28
- if (merged.length === 0) return filtered;
29
- const out = [...filtered, ...merged];
30
- out.sort(sort === 'date' ? compareRecallNewestFirst : compareRecallByScore);
31
- return out;
32
- }