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
@@ -0,0 +1,581 @@
1
+ // Provider error kind: one semantic verdict for a thrown provider error,
2
+ // shared by retry policy, account rotation and the UI. Leaf module: it reads
3
+ // the typed fields provider boundaries stamp on errors (status, code,
4
+ // headers, retryAfterMs, resetAt, quotaScope, reauthRequired) and falls back
5
+ // to the older fields (httpStatus, responseFailed, providerError, SDK error
6
+ // bodies, RPC status strings). Message text is consulted only for untyped
7
+ // errors and only for unambiguous wordings.
8
+
9
+ export const PROVIDER_ERROR_KINDS = Object.freeze([
10
+ 'overloaded',
11
+ 'rate_limited',
12
+ 'quota_exhausted',
13
+ 'entitlement',
14
+ 'billing',
15
+ 'auth',
16
+ 'permission',
17
+ 'context_overflow',
18
+ 'request_too_large',
19
+ 'policy',
20
+ 'service_tier_unavailable',
21
+ 'invalid_request',
22
+ 'transient',
23
+ 'unknown',
24
+ ]);
25
+
26
+ const MAX_CAUSE_CHAIN_DEPTH = 8;
27
+
28
+ export function boundedCauseChain(err) {
29
+ const chain = [];
30
+ const seen = new Set();
31
+ let cursor = err;
32
+ while (cursor && chain.length < MAX_CAUSE_CHAIN_DEPTH && !seen.has(cursor)) {
33
+ chain.push(cursor);
34
+ seen.add(cursor);
35
+ cursor = cursor?.cause;
36
+ }
37
+ return chain;
38
+ }
39
+
40
+ export function headerValue(headers, name) {
41
+ if (!headers) return null;
42
+ const lower = name.toLowerCase();
43
+ if (typeof headers.get === 'function') return headers.get(name) ?? headers.get(lower);
44
+ for (const [key, value] of Object.entries(headers)) {
45
+ if (String(key).toLowerCase() === lower) return Array.isArray(value) ? value[0] : value;
46
+ }
47
+ return null;
48
+ }
49
+
50
+ function wireDetail(err) {
51
+ const failed = err?.responseFailed;
52
+ return failed?.response?.error || failed?.error || err?.providerError || failed || null;
53
+ }
54
+
55
+ // Every place a provider error may carry its response headers, outermost
56
+ // first: the error itself, the SDK response, preserved wire `error.headers`.
57
+ function headerSources(err) {
58
+ const detail = wireDetail(err);
59
+ return [
60
+ err?.headers,
61
+ err?.response?.headers,
62
+ err?.data?.responseHeaders,
63
+ err?.error?.headers,
64
+ detail?.headers,
65
+ err?.providerError?.headers,
66
+ err?.payload?.error?.headers,
67
+ ].filter((headers) => headers && typeof headers === 'object');
68
+ }
69
+
70
+ /** The first value of response header `name` across every preserved header source. */
71
+ export function errorHeaderValue(err, name) {
72
+ for (const headers of headerSources(err)) {
73
+ const value = headerValue(headers, name);
74
+ if (value != null && value !== '') return value;
75
+ }
76
+ return null;
77
+ }
78
+
79
+ export function typedErrorCode(err) {
80
+ const detail = wireDetail(err);
81
+ for (const field of [detail?.code, detail?.type, err?.providerErrorCode, err?.code, err?.error?.code]) {
82
+ if (typeof field === 'string' && field.trim()) return field.trim().toLowerCase();
83
+ }
84
+ return '';
85
+ }
86
+
87
+ // ── Retry-After ─────────────────────────────────────────────────────────────
88
+ const MESSAGE_DELAY_CODES = new Set(['rate_limit_exceeded', 'slow_down']);
89
+ const MESSAGE_DELAY_RE =
90
+ /(?:try again in|retry (?:again )?(?:in|after)|wait(?: for)?)\s*(\d+(?:\.\d+)?)\s*(ms|milliseconds?|s|secs?|seconds?|m|mins?|minutes?)\b/i;
91
+
92
+ // Zero or non-positive advice is no advice: the caller's local backoff applies
93
+ // and a later source may still advise.
94
+ function finitePositive(value) {
95
+ if (value == null || value === '') return null;
96
+ const n = Number(value);
97
+ return Number.isFinite(n) && n > 0 ? n : null;
98
+ }
99
+
100
+ function retryInfoDelayMs(details) {
101
+ if (!Array.isArray(details)) return null;
102
+ for (const detail of details) {
103
+ const delay = detail?.retryDelay;
104
+ let ms = null;
105
+ if (typeof delay === 'string') {
106
+ const match = delay.trim().match(/^(\d+(?:\.\d+)?)s$/);
107
+ if (match) ms = Number(match[1]) * 1000;
108
+ } else if (delay && typeof delay === 'object') {
109
+ ms = Number(delay.seconds || 0) * 1000 + Number(delay.nanos || 0) / 1_000_000;
110
+ }
111
+ if (finitePositive(ms) != null) return Math.ceil(ms);
112
+ }
113
+ return null;
114
+ }
115
+
116
+ function messageDelayMs(err) {
117
+ const detail = wireDetail(err) || err?.error || null;
118
+ for (const message of [detail?.message, err?.error?.message, err?.message]) {
119
+ if (typeof message !== 'string' || !message) continue;
120
+ const match = message.match(MESSAGE_DELAY_RE);
121
+ if (!match) continue;
122
+ const value = finitePositive(match[1]);
123
+ if (value == null) continue;
124
+ const unit = String(match[2] || '').toLowerCase();
125
+ if (unit === 'ms' || unit.startsWith('millisecond')) return Math.ceil(value);
126
+ if (unit === 'm' || unit.startsWith('min')) return Math.ceil(value * 60_000);
127
+ return Math.ceil(value * 1000);
128
+ }
129
+ return null;
130
+ }
131
+
132
+ /**
133
+ * The server-advised wait before re-issuing, in ms; null when the server gave
134
+ * none. Precedence: the boundary-stamped `retryAfterMs`, Retry-After headers
135
+ * (any preserved source), Google RetryInfo (`details` / SDK `errorDetails`),
136
+ * and finally the delay a TYPED rate_limit_exceeded / slow_down message names.
137
+ * Window resets (`resetAt`, anthropic-ratelimit-unified-reset) are never
138
+ * retry advice: they are reported separately for display and cooldown.
139
+ */
140
+ export function retryAfterMsFromError(err) {
141
+ if (!err || typeof err !== 'object') return null;
142
+ // A deadline captured once at the boundary (`retryAfterAt`)
143
+ // survives a transport switch: report what is left of it.
144
+ for (const item of boundedCauseChain(err).slice(0, 2)) {
145
+ const at = Number(item?.retryAfterAt);
146
+ if (Number.isFinite(at) && at > 0) return Math.max(0, at - Date.now());
147
+ }
148
+ for (const item of boundedCauseChain(err).slice(0, 2)) {
149
+ const stamped = finitePositive(item?.retryAfterMs);
150
+ if (stamped != null) return stamped;
151
+ }
152
+ const retryAfterMs = finitePositive(errorHeaderValue(err, 'retry-after-ms'));
153
+ if (retryAfterMs != null) return retryAfterMs;
154
+ const retryAfter = errorHeaderValue(err, 'retry-after');
155
+ if (retryAfter != null) {
156
+ const seconds = finitePositive(retryAfter);
157
+ if (seconds != null) return Math.ceil(seconds * 1000);
158
+ const untilDate = finitePositive(Date.parse(String(retryAfter)) - Date.now());
159
+ if (untilDate != null) return untilDate;
160
+ }
161
+ const detail = wireDetail(err);
162
+ for (const details of [
163
+ err.details,
164
+ err.error?.details,
165
+ err.data?.error?.details,
166
+ err.errorDetails,
167
+ err.error?.errorDetails,
168
+ detail?.details,
169
+ ]) {
170
+ const delay = retryInfoDelayMs(details);
171
+ if (delay != null) return delay;
172
+ }
173
+ if (MESSAGE_DELAY_CODES.has(typedErrorCode(err))) return messageDelayMs(err);
174
+ return null;
175
+ }
176
+
177
+ // ── Transport evidence ──────────────────────────────────────────────────────
178
+ export const TRANSIENT_SDK_NAMES = new Set([
179
+ 'APIConnectionError',
180
+ 'APIConnectionTimeoutError',
181
+ 'ConnectTimeoutError',
182
+ 'HeadersTimeoutError',
183
+ 'BodyTimeoutError',
184
+ ]);
185
+ const STALL_NAMES = new Set(['StreamStalledError', 'StreamStalledAbortError', 'AgentStallAbortError']);
186
+ // 'terminated' / 'other side closed' / 'socket hang up' are the body-read
187
+ // forms of the same disconnect (undici aborts the response body when the peer
188
+ // closes mid-stream and may not attach a cause).
189
+ export const BARE_FETCH_TRANSPORT_MESSAGE_RE =
190
+ /^(?:fetch failed|failed to fetch|couldn'?t fetch\.?|load failed|network error|terminated|other side closed|socket hang up)$/i;
191
+ const TRANSIENT_ERROR_CODES = new Set([
192
+ 'ECONNRESET',
193
+ 'ETIMEDOUT',
194
+ 'ESOCKETTIMEDOUT',
195
+ 'EAI_AGAIN',
196
+ 'ENOTFOUND',
197
+ 'EAI_NODATA',
198
+ 'ECONNREFUSED',
199
+ 'ENETUNREACH',
200
+ 'EHOSTUNREACH',
201
+ 'EPIPE',
202
+ 'EPROVIDERTIMEOUT',
203
+ 'EGEMINITIMEOUT',
204
+ 'ESTREAMSTALL',
205
+ 'EWSACQUIRETIMEOUT',
206
+ 'UND_ERR_SOCKET',
207
+ 'UND_ERR_CONNECT_TIMEOUT',
208
+ 'UND_ERR_HEADERS_TIMEOUT',
209
+ 'UND_ERR_BODY_TIMEOUT',
210
+ 'UND_ERR_CONNECT',
211
+ 'EPROTO',
212
+ 'UND_ERR_DESTROYED',
213
+ 'UND_ERR_CLOSED',
214
+ 'ECONNABORTED',
215
+ 'ENETRESET',
216
+ 'ERR_STREAM_DESTROYED',
217
+ 'ERR_HTTP2_STREAM_ERROR',
218
+ 'ERR_HTTP2_SESSION_ERROR',
219
+ 'ERR_HTTP2_INVALID_SESSION',
220
+ 'ERR_SOCKET_CONNECTION_TIMEOUT',
221
+ 'ERR_SSL_WRONG_VERSION_NUMBER',
222
+ 'ERR_STREAM_PREMATURE_CLOSE',
223
+ ]);
224
+ // TLS record corruption on a flaky link or a meddling proxy. Node builds the
225
+ // ERR_SSL_* code from the OpenSSL reason string, which differs across OpenSSL
226
+ // versions, so the stable suffix names the class.
227
+ export const TLS_RECORD_FAILURE_RE = /^ERR_SSL_[A-Z0-9_/]*BAD_RECORD_MAC$/i;
228
+
229
+ /** True for a socket/TLS errno that describes a transient transport fault. */
230
+ export function isTransientErrorCode(code) {
231
+ const value = String(code || '');
232
+ return TRANSIENT_ERROR_CODES.has(value) || TLS_RECORD_FAILURE_RE.test(value);
233
+ }
234
+
235
+ const TRANSIENT_WS_CLOSE_CODES = new Set([1000, 1001, 1005, 1006, 1011, 1012]);
236
+
237
+ function transportEvidence(err, chain, status) {
238
+ if (err.truncatedStream === true || err.code === 'TRUNCATED_STREAM' || err.streamStalled === true) return true;
239
+ if (TRANSIENT_WS_CLOSE_CODES.has(Number(err.wsCloseCode ?? err.streamCloseCode ?? 0))) return true;
240
+ if (chain.some((item) => isTransientErrorCode(item?.code))) return true;
241
+ const names = chain.map((item) => String(item?.name || ''));
242
+ if (names.some((name) => TRANSIENT_SDK_NAMES.has(name) || STALL_NAMES.has(name))) return true;
243
+ return !status && chain.some((item) => BARE_FETCH_TRANSPORT_MESSAGE_RE.test(String(item?.message || '').trim()));
244
+ }
245
+
246
+ // ── Context / size wording (untyped fallback) ───────────────────────────────
247
+ // Token-context refusals: the conversation is longer than the model's window.
248
+ export const TOKEN_CONTEXT_OVERFLOW_PATTERNS = [
249
+ /input (?:length|tokens?) exceeds? the context window/i,
250
+ /exceeds? the (?:maximum )?context (?:window|length)/i,
251
+ /maximum context length/i,
252
+ /context[_ ]length[_ ]exceeded/i,
253
+ /prompt is too long/i,
254
+ /reduce the length of (?:the )?(?:messages|input|prompt)/i,
255
+ // Wordings other backends use for the same refusal, each tied to a context
256
+ // or input-length noun so a tokens-per-minute rate limit never matches.
257
+ /prompt too long/i, // z.ai, Ollama
258
+ /prompt exceeds max length/i, // z.ai CN endpoint
259
+ /input is too long for requested model/i, // Amazon Bedrock
260
+ /input token count.*exceeds the maximum/i, // Google
261
+ /maximum prompt length is \d+/i, // xAI
262
+ /exceeds (?:the )?maximum allowed input length/i, // OpenRouter relays
263
+ /is longer than the model'?s context length/i, // Together AI
264
+ /exceeds the available context size/i, // llama.cpp server
265
+ /greater than the context length/i, // LM Studio
266
+ /context window exceeds limit/i, // MiniMax
267
+ /exceeded model token limit/i, // Kimi
268
+ /too large for model with \d+ maximum context length/i, // Mistral
269
+ /range of input length should be/i, // DashScope / Qwen
270
+ /model_context_window_exceeded/i, // z.ai finish reason surfaced as text
271
+ ];
272
+ // Byte/media size refusals: the request body itself is too large.
273
+ export const REQUEST_SIZE_PATTERNS = [
274
+ /request payload size exceeds the limit/i, // Google (400, byte-size limit)
275
+ // A 413 re-wrapped by a proxy or aggregator without its status.
276
+ /request entity too large/i,
277
+ /request exceeds the maximum size/i,
278
+ ];
279
+
280
+ // Capacity wording on an untyped 429 ("… is at capacity").
281
+ const CAPACITY_MESSAGE_RE = /\bat capacity\b|\boverloaded\b|\bserver is busy\b/i;
282
+ // Unambiguous quota wordings, read only under `legacyQuotaWording`.
283
+ const LEGACY_BILLING_MESSAGE_RE = /\binsufficient_quota\b|exceeded your (?:current )?quota/i;
284
+ const LEGACY_QUOTA_MESSAGE_RE = /\bquota_exceeded\b|\busage_limit_reached\b|hit your usage limit/i;
285
+
286
+ // ── Typed codes ─────────────────────────────────────────────────────────────
287
+ const CODE_KINDS = new Map(
288
+ Object.entries({
289
+ policy: [
290
+ 'cyber_policy',
291
+ 'bio_policy',
292
+ 'cyber_policy_violation',
293
+ 'bio_policy_violation',
294
+ 'misalignment_policy_violation',
295
+ 'content_policy_violation',
296
+ 'content_filter',
297
+ 'safety',
298
+ 'recitation',
299
+ 'invalid_prompt',
300
+ ],
301
+ billing: [
302
+ 'insufficient_quota',
303
+ 'credit_balance_exhausted',
304
+ 'organization_spend_limit_exceeded',
305
+ 'project_spend_limit_exceeded',
306
+ 'organization_usage_limit_exceeded',
307
+ 'billing_not_active',
308
+ 'billing_hard_limit_reached',
309
+ 'payment_required',
310
+ 'insufficient_g1_credits_balance',
311
+ ],
312
+ entitlement: ['usage_not_included'],
313
+ quota_exhausted: ['quota_exceeded', 'quota_exhausted', 'usage_limit_reached', 'provider_accounts_exhausted'],
314
+ context_overflow: ['context_length_exceeded', 'context_window_exceeded', 'model_context_window_exceeded'],
315
+ request_too_large: ['request_too_large', 'payload_too_large', 'request_entity_too_large'],
316
+ auth: ['invalid_api_key', 'authentication_error', 'unauthenticated', 'unauthorized', 'invalid_authentication'],
317
+ permission: ['permission_error', 'permission_denied', 'forbidden'],
318
+ overloaded: [
319
+ 'server_is_overloaded',
320
+ 'overloaded_error',
321
+ 'overloaded',
322
+ 'server_overloaded',
323
+ 'model_capacity_exhausted',
324
+ 'model_capacity_exceeded',
325
+ ],
326
+ // The requested service tier has no capacity: the same request at the
327
+ // same tier is refused again, so it is final rather than an overload.
328
+ service_tier_unavailable: ['flex_unavailable'],
329
+ rate_limited: ['rate_limit_exceeded', 'rate_limit_error', 'rate_limited', 'slow_down', 'too_many_requests'],
330
+ transient: [
331
+ 'server_error',
332
+ 'api_error',
333
+ 'internal',
334
+ 'internal_error',
335
+ 'unavailable',
336
+ 'service_unavailable',
337
+ 'deadline_exceeded',
338
+ 'timeout',
339
+ 'previous_response_not_found',
340
+ 'websocket_connection_limit_reached',
341
+ 'stream_disconnected',
342
+ 'network_error',
343
+ // Replay safety is still the stream-outcome gate's call (classifyError).
344
+ 'malformed_stream',
345
+ ],
346
+ invalid_request: [
347
+ 'invalid_request',
348
+ 'invalid_request_error',
349
+ 'invalid_argument',
350
+ 'failed_precondition',
351
+ 'bad_request',
352
+ 'not_found',
353
+ 'not_found_error',
354
+ 'model_not_found',
355
+ 'unsupported_parameter',
356
+ ],
357
+ }).flatMap(([kind, codes]) => codes.map((code) => [code, kind]))
358
+ );
359
+ const RESOURCE_EXHAUSTED = 'resource_exhausted';
360
+ // When several typed codes are present (an envelope type plus a specific
361
+ // code), the most specific verdict wins.
362
+ const KIND_RANK = [
363
+ 'policy',
364
+ 'billing',
365
+ 'entitlement',
366
+ 'quota_exhausted',
367
+ 'context_overflow',
368
+ 'request_too_large',
369
+ 'auth',
370
+ 'permission',
371
+ 'service_tier_unavailable',
372
+ 'overloaded',
373
+ 'rate_limited',
374
+ 'transient',
375
+ 'invalid_request',
376
+ ];
377
+
378
+ function codeFields(item) {
379
+ const detail = wireDetail(item);
380
+ return [
381
+ detail?.code,
382
+ detail?.type,
383
+ detail?.status,
384
+ item?.providerErrorCode,
385
+ item?.code,
386
+ item?.type,
387
+ item?.error?.code,
388
+ item?.error?.type,
389
+ item?.error?.status,
390
+ item?.error?.error?.code,
391
+ item?.error?.error?.type,
392
+ item?.payload?.code,
393
+ item?.payload?.type,
394
+ item?.payload?.error?.code,
395
+ item?.payload?.error?.type,
396
+ item?.geminiStatus,
397
+ item?.status,
398
+ ];
399
+ }
400
+
401
+ function typedCodes(chain) {
402
+ const codes = [];
403
+ for (const item of chain) {
404
+ if (!item || typeof item !== 'object') continue;
405
+ for (const field of codeFields(item)) {
406
+ if (typeof field !== 'string') continue;
407
+ const code = field.trim().toLowerCase();
408
+ if (code && !codes.includes(code)) codes.push(code);
409
+ }
410
+ }
411
+ return codes;
412
+ }
413
+
414
+ const VALID_STATUS = (n) => Number.isFinite(n) && n >= 100 && n <= 599;
415
+
416
+ function statusOf(err) {
417
+ for (const value of [err?.httpStatus, err?.status, err?.statusCode, err?.response?.status]) {
418
+ const n = Number(value);
419
+ if (VALID_STATUS(n)) return Math.floor(n);
420
+ }
421
+ return 0;
422
+ }
423
+
424
+ function kindFromStatus(status) {
425
+ if (status === 401) return 'auth';
426
+ if (status === 402) return 'billing';
427
+ if (status === 403) return 'permission';
428
+ if (status === 413) return 'request_too_large';
429
+ if (status === 429) return 'rate_limited';
430
+ if (status === 529) return 'overloaded';
431
+ if (status === 408 || status === 409 || status === 425) return 'transient';
432
+ if (status === 525 || status === 526) return null;
433
+ if (status >= 400 && status < 500) return 'invalid_request';
434
+ if (status >= 500 && status < 600) return 'transient';
435
+ return null;
436
+ }
437
+
438
+ function firstOf(chain, read) {
439
+ for (const item of chain) {
440
+ const value = item && typeof item === 'object' ? read(item) : undefined;
441
+ if (value !== undefined && value !== null) return value;
442
+ }
443
+ return null;
444
+ }
445
+
446
+ function resetAtOf(err, chain) {
447
+ const stamped = firstOf(chain, (item) => {
448
+ const n = Number(item.resetAt);
449
+ return Number.isFinite(n) && n > 0 ? n : null;
450
+ });
451
+ if (stamped != null) return stamped;
452
+ const exhausted = Number(err?.quotaExhausted?.resetAt);
453
+ return Number.isFinite(exhausted) && exhausted > 0 ? exhausted : null;
454
+ }
455
+
456
+ function quotaScopeOf(chain) {
457
+ return firstOf(chain, (item) => {
458
+ const scope = typeof item.quotaScope === 'string' ? item.quotaScope.trim().toLowerCase() : '';
459
+ return scope === 'minute' || scope === 'day' || scope === 'plan' ? scope : null;
460
+ });
461
+ }
462
+
463
+ // The most specific kind the typed codes name; { kind: null } when none does.
464
+ function kindFromCodes(codes, scope) {
465
+ let kind = null;
466
+ let code = '';
467
+ for (const candidate of codes) {
468
+ let candidateKind = CODE_KINDS.get(candidate) || null;
469
+ if (candidate === RESOURCE_EXHAUSTED) {
470
+ // Google uses one code for per-minute throttles and spent quotas; the
471
+ // boundary names a spent quota with quotaScope day/plan. Without that
472
+ // evidence it is a request-local rate limit.
473
+ candidateKind = scope === 'day' || scope === 'plan' ? 'quota_exhausted' : 'rate_limited';
474
+ }
475
+ if (candidateKind && (kind === null || KIND_RANK.indexOf(candidateKind) < KIND_RANK.indexOf(kind))) {
476
+ kind = candidateKind;
477
+ code = candidate;
478
+ }
479
+ }
480
+ return { kind, code };
481
+ }
482
+
483
+ /** The kind an error's typed codes alone name (no status, flag or wording); null when none does. */
484
+ export function typedCodeKind(err) {
485
+ if (!err || (typeof err !== 'object' && typeof err !== 'function')) return null;
486
+ const chain = boundedCauseChain(err);
487
+ return kindFromCodes(typedCodes(chain), quotaScopeOf(chain)).kind;
488
+ }
489
+
490
+ function messageOf(err, chain) {
491
+ const detail = wireDetail(err);
492
+ return [detail?.message, err?.error?.message, ...chain.map((item) => item?.message)]
493
+ .filter((message) => typeof message === 'string' && message)
494
+ .join('\n');
495
+ }
496
+
497
+ /**
498
+ * Classify a provider error into one semantic kind.
499
+ * `options.text:false` skips the message-wording fallbacks, for retry
500
+ * policy that must decide from typed evidence alone. `options.quotaFlags:false`
501
+ * ignores the header-derived providerQuota / quotaExceeded flags.
502
+ * @returns {{ kind: string, code: string, status: number, retryAfterMs: number|null, resetAt: number|null }}
503
+ */
504
+ export function providerErrorKind(err, options = {}) {
505
+ if (!err || (typeof err !== 'object' && typeof err !== 'function')) {
506
+ return { kind: 'unknown', code: '', status: 0, retryAfterMs: null, resetAt: null };
507
+ }
508
+ const chain = boundedCauseChain(err);
509
+ const status = statusOf(err);
510
+ const retryAfterMs = retryAfterMsFromError(err);
511
+ const resetAt = resetAtOf(err, chain);
512
+ const scope = quotaScopeOf(chain);
513
+ const codes = typedCodes(chain);
514
+ const describe = (kind, code = typedErrorCode(err)) => ({ kind, code: code || '', status, retryAfterMs, resetAt });
515
+
516
+ // Validated account-pool evidence and boundary-stamped re-auth decide first.
517
+ if (err.quotaExhausted && typeof err.quotaExhausted === 'object') return describe('quota_exhausted');
518
+ if (chain.some((item) => item?.reauthRequired === true)) return describe('auth');
519
+
520
+ let { kind, code } = kindFromCodes(codes, scope);
521
+ // Explicit quota flags (Anthropic unified-status rejected headers) outrank a
522
+ // generic rate-limit code or status; they never turn an overload (or a more
523
+ // specific refusal) into quota.
524
+ const quotaFlagged =
525
+ options.quotaFlags !== false &&
526
+ chain.some((item) => item?.providerQuota === true || item?.quotaExceeded === true);
527
+ if (quotaFlagged && (!kind || kind === 'rate_limited')) kind = 'quota_exhausted';
528
+ // Wordings, for untyped errors only (a typed code always decides).
529
+ const text = options.text !== false && (!kind || kind === 'invalid_request') ? messageOf(err, chain) : '';
530
+ // Capacity wording counts only on a typed 429 ("… is at capacity"): it
531
+ // keeps such a 429 from reading as a rate limit. An untyped 5xx stays an
532
+ // ordinary transient server fault, whatever its body says. Quota or billing
533
+ // wording never yields a quota kind: that takes a typed code, a quota flag
534
+ // or a quota scope (text may refine only the displayed message).
535
+ if (!kind && !codes.length && text && status === 429 && CAPACITY_MESSAGE_RE.test(text)) kind = 'overloaded';
536
+ // Presentation-only fallback (`legacyQuotaWording`): a fully UNTYPED error
537
+ // (no status, code, retry advice, quota flag or scope — e.g. persisted
538
+ // failure text) may still read as a usage limit from unambiguous wording.
539
+ // Retry, rotation and blocking never enable it.
540
+ if (
541
+ options.legacyQuotaWording === true &&
542
+ !kind &&
543
+ !codes.length &&
544
+ !status &&
545
+ retryAfterMs == null &&
546
+ !scope &&
547
+ text
548
+ ) {
549
+ if (LEGACY_BILLING_MESSAGE_RE.test(text)) kind = 'billing';
550
+ else if (LEGACY_QUOTA_MESSAGE_RE.test(text)) kind = 'quota_exhausted';
551
+ }
552
+ if (!kind) kind = kindFromStatus(status);
553
+ if ((!kind || kind === 'invalid_request') && text) {
554
+ if (TOKEN_CONTEXT_OVERFLOW_PATTERNS.some((re) => re.test(text))) kind = 'context_overflow';
555
+ else if (REQUEST_SIZE_PATTERNS.some((re) => re.test(text))) kind = 'request_too_large';
556
+ }
557
+ if (!kind && transportEvidence(err, chain, status)) kind = 'transient';
558
+ // A provider wire error event without a deterministic code is a server-side fault.
559
+ if (!kind && (err.responseFailed != null || err.providerWireError === true)) kind = 'transient';
560
+ kind = kind || 'unknown';
561
+ // The quota window the server names outranks the code's default reading.
562
+ if (scope === 'minute' && kind === 'quota_exhausted') kind = 'rate_limited';
563
+ // A day/plan window on a rate limit is a spent quota. A resetAt alone is
564
+ // not: rate-limit 429s carry window resets too (kept for display/cooldown).
565
+ if (kind === 'rate_limited' && (scope === 'day' || scope === 'plan')) kind = 'quota_exhausted';
566
+ return describe(kind, code || undefined);
567
+ }
568
+
569
+ /** Kinds whose refusal no wait or replay can change: quota, plan and billing. */
570
+ export const QUOTA_KINDS = new Set(['quota_exhausted', 'entitlement', 'billing']);
571
+ /** Kinds that are deterministic refusals of this request (never replayed as-is). */
572
+ export const DETERMINISTIC_KINDS = new Set([
573
+ ...QUOTA_KINDS,
574
+ 'policy',
575
+ 'auth',
576
+ 'permission',
577
+ 'context_overflow',
578
+ 'request_too_large',
579
+ 'service_tier_unavailable',
580
+ 'invalid_request',
581
+ ]);