mixdog 0.7.18 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (847) hide show
  1. package/README.md +37 -331
  2. package/package.json +67 -99
  3. package/scripts/boot-smoke.mjs +94 -0
  4. package/scripts/build-tui.mjs +52 -0
  5. package/scripts/compact-smoke.mjs +199 -0
  6. package/scripts/lead-workflow-smoke.mjs +598 -0
  7. package/scripts/live-worker-smoke.mjs +239 -0
  8. package/scripts/output-style-smoke.mjs +101 -0
  9. package/scripts/session-context-bench.mjs +172 -0
  10. package/scripts/smoke-loop-report.mjs +221 -0
  11. package/scripts/smoke-loop.mjs +201 -0
  12. package/scripts/smoke.mjs +113 -0
  13. package/scripts/tool-failures.mjs +143 -0
  14. package/scripts/tool-smoke.mjs +452 -0
  15. package/src/agents/debugger/AGENT.md +3 -0
  16. package/src/agents/debugger/agent.json +6 -0
  17. package/src/agents/explore/AGENT.md +4 -0
  18. package/src/agents/explore/agent.json +6 -0
  19. package/src/agents/heavy-worker/AGENT.md +3 -0
  20. package/src/agents/heavy-worker/agent.json +6 -0
  21. package/src/agents/maintainer/AGENT.md +3 -0
  22. package/src/agents/maintainer/agent.json +6 -0
  23. package/src/agents/reviewer/AGENT.md +3 -0
  24. package/src/agents/reviewer/agent.json +6 -0
  25. package/src/agents/scheduler-task.md +3 -0
  26. package/src/agents/web-researcher/AGENT.md +3 -0
  27. package/src/agents/web-researcher/agent.json +6 -0
  28. package/src/agents/webhook-handler.md +3 -0
  29. package/src/agents/worker/AGENT.md +3 -0
  30. package/src/agents/worker/agent.json +6 -0
  31. package/src/app.mjs +90 -0
  32. package/src/cli.mjs +11 -0
  33. package/src/defaults/hidden-roles.json +72 -0
  34. package/src/defaults/mixdog-config.template.json +15 -0
  35. package/src/hooks/lib/permission-evaluator.cjs +488 -0
  36. package/src/hooks/lib/settings-loader.cjs +112 -0
  37. package/src/lib/keychain-cjs.cjs +332 -0
  38. package/src/lib/plugin-paths.cjs +28 -0
  39. package/src/lib/rules-builder.cjs +315 -0
  40. package/src/mixdog-session-runtime.mjs +3813 -0
  41. package/src/output-styles/default.md +38 -0
  42. package/src/output-styles/extreme-simple.md +17 -0
  43. package/src/output-styles/simple.md +17 -0
  44. package/src/repl.mjs +330 -0
  45. package/src/rules/bridge/00-common.md +5 -0
  46. package/src/rules/bridge/20-skip-protocol.md +11 -0
  47. package/src/rules/bridge/30-explorer.md +4 -0
  48. package/src/rules/bridge/40-cycle1-agent.md +28 -0
  49. package/src/rules/bridge/41-cycle2-agent.md +59 -0
  50. package/src/rules/lead/00-tool-lead.md +5 -0
  51. package/src/rules/lead/01-general.md +5 -0
  52. package/src/rules/lead/02-channels.md +3 -0
  53. package/src/rules/lead/04-workflow.md +12 -0
  54. package/src/rules/shared/00-language.md +3 -0
  55. package/src/rules/shared/01-tool.md +3 -0
  56. package/src/runtime/agent/orchestrator/bridge-trace.mjs +814 -0
  57. package/src/runtime/agent/orchestrator/cache-mtime.mjs +60 -0
  58. package/src/runtime/agent/orchestrator/config.mjs +446 -0
  59. package/src/runtime/agent/orchestrator/context/collect.mjs +796 -0
  60. package/src/runtime/agent/orchestrator/dispatch-persist.mjs +417 -0
  61. package/src/runtime/agent/orchestrator/internal-roles.mjs +188 -0
  62. package/src/runtime/agent/orchestrator/internal-tools.mjs +88 -0
  63. package/src/runtime/agent/orchestrator/mcp/client.mjs +345 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2104 -0
  65. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +784 -0
  66. package/src/runtime/agent/orchestrator/providers/api-usage.mjs +341 -0
  67. package/src/runtime/agent/orchestrator/providers/gemini.mjs +1679 -0
  68. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +959 -0
  69. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +213 -0
  70. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +38 -0
  71. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +471 -0
  72. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +615 -0
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +808 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +1719 -0
  75. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +2587 -0
  76. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +1953 -0
  77. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +136 -0
  78. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +317 -0
  79. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +109 -0
  80. package/src/runtime/agent/orchestrator/providers/registry.mjs +247 -0
  81. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +332 -0
  82. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +11 -0
  83. package/src/runtime/agent/orchestrator/providers/trace-utils.mjs +50 -0
  84. package/src/runtime/agent/orchestrator/session/cache/post-edit-marks.mjs +42 -0
  85. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
  86. package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +318 -0
  87. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +367 -0
  88. package/src/runtime/agent/orchestrator/session/compact.mjs +882 -0
  89. package/src/runtime/agent/orchestrator/session/context-utils.mjs +233 -0
  90. package/src/runtime/agent/orchestrator/session/loop.mjs +2269 -0
  91. package/src/runtime/agent/orchestrator/session/manager.mjs +2972 -0
  92. package/src/runtime/agent/orchestrator/session/result-classification.mjs +65 -0
  93. package/src/runtime/agent/orchestrator/session/store.mjs +870 -0
  94. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +166 -0
  95. package/src/runtime/agent/orchestrator/smart-bridge/bridge-llm.mjs +339 -0
  96. package/src/runtime/agent/orchestrator/smart-bridge/cache-strategy.mjs +419 -0
  97. package/src/runtime/agent/orchestrator/stall-policy.mjs +227 -0
  98. package/src/runtime/agent/orchestrator/tool-loop-guard.mjs +235 -0
  99. package/src/runtime/agent/orchestrator/tools/bash-session.mjs +723 -0
  100. package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +171 -0
  101. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +389 -0
  102. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +637 -0
  103. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +165 -0
  104. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +104 -0
  105. package/src/runtime/agent/orchestrator/tools/builtin/glob-walk.mjs +194 -0
  106. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +596 -0
  107. package/src/runtime/agent/orchestrator/tools/builtin/native-edit-runner.mjs +110 -0
  108. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +153 -0
  109. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
  110. package/src/runtime/agent/orchestrator/tools/builtin/read-open.mjs +189 -0
  111. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +731 -0
  112. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +168 -0
  113. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
  114. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +465 -0
  115. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +160 -0
  116. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +982 -0
  117. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +1087 -0
  118. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +231 -0
  119. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +223 -0
  120. package/src/runtime/agent/orchestrator/tools/builtin.mjs +478 -0
  121. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
  122. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4102 -0
  123. package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +323 -0
  124. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +154 -0
  125. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +26 -0
  126. package/src/runtime/agent/orchestrator/tools/patch-binary-fetcher.mjs +143 -0
  127. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +18 -0
  128. package/src/runtime/agent/orchestrator/tools/patch.mjs +2772 -0
  129. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +114 -0
  130. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +880 -0
  131. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +312 -0
  132. package/src/runtime/channels/backends/discord.mjs +781 -0
  133. package/src/runtime/channels/data/voice-runtime-manifest.json +138 -0
  134. package/src/runtime/channels/index.mjs +3309 -0
  135. package/src/runtime/channels/lib/config.mjs +285 -0
  136. package/src/runtime/channels/lib/drop-trace.mjs +71 -0
  137. package/src/runtime/channels/lib/event-pipeline.mjs +81 -0
  138. package/src/runtime/channels/lib/holidays.mjs +138 -0
  139. package/src/runtime/channels/lib/hook-pipe-server.mjs +671 -0
  140. package/src/runtime/channels/lib/output-forwarder.mjs +765 -0
  141. package/src/runtime/channels/lib/runtime-paths.mjs +497 -0
  142. package/src/runtime/channels/lib/scheduler.mjs +710 -0
  143. package/src/runtime/channels/lib/session-discovery.mjs +102 -0
  144. package/src/runtime/channels/lib/state-file.mjs +68 -0
  145. package/src/runtime/channels/lib/status-snapshot.mjs +224 -0
  146. package/src/runtime/channels/lib/tool-format.mjs +122 -0
  147. package/src/runtime/channels/lib/transcript-discovery.mjs +195 -0
  148. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +734 -0
  149. package/src/runtime/channels/lib/webhook.mjs +1288 -0
  150. package/src/runtime/channels/tool-defs.mjs +177 -0
  151. package/src/runtime/lib/keychain-cjs.cjs +289 -0
  152. package/src/runtime/memory/data/runtime-manifest.json +40 -0
  153. package/src/runtime/memory/index.mjs +3706 -0
  154. package/src/runtime/memory/lib/core-memory-store.mjs +336 -0
  155. package/src/runtime/memory/lib/embedding-provider.mjs +275 -0
  156. package/src/runtime/memory/lib/embedding-worker.mjs +331 -0
  157. package/src/runtime/memory/lib/memory-cycle-requests.mjs +276 -0
  158. package/src/runtime/memory/lib/memory-cycle1.mjs +783 -0
  159. package/src/runtime/memory/lib/memory-cycle2.mjs +1389 -0
  160. package/src/runtime/memory/lib/memory-cycle3.mjs +646 -0
  161. package/src/runtime/memory/lib/memory-embed.mjs +300 -0
  162. package/src/runtime/memory/lib/memory-ops-policy.mjs +149 -0
  163. package/src/runtime/memory/lib/memory-recall-store.mjs +644 -0
  164. package/src/runtime/memory/lib/memory.mjs +418 -0
  165. package/src/runtime/memory/lib/pg/adapter.mjs +328 -0
  166. package/src/runtime/memory/lib/pg/process.mjs +366 -0
  167. package/src/runtime/memory/lib/pg/supervisor.mjs +495 -0
  168. package/src/runtime/memory/lib/runtime-fetcher.mjs +464 -0
  169. package/src/runtime/memory/lib/trace-store.mjs +734 -0
  170. package/src/runtime/memory/tool-defs.mjs +79 -0
  171. package/src/runtime/search/index.mjs +925 -0
  172. package/src/runtime/search/lib/config.mjs +61 -0
  173. package/src/runtime/search/lib/web-tools.mjs +1278 -0
  174. package/src/runtime/search/tool-defs.mjs +64 -0
  175. package/src/runtime/shared/atomic-file.mjs +435 -0
  176. package/src/runtime/shared/background-tasks.mjs +376 -0
  177. package/src/runtime/shared/child-guardian.mjs +98 -0
  178. package/src/runtime/shared/config.mjs +393 -0
  179. package/src/runtime/shared/err-text.mjs +121 -0
  180. package/src/runtime/shared/launcher-control.mjs +259 -0
  181. package/src/runtime/shared/llm/http-agent.mjs +129 -0
  182. package/src/runtime/shared/open-url.mjs +37 -0
  183. package/src/runtime/shared/plugin-paths.mjs +25 -0
  184. package/src/runtime/shared/process-shutdown.mjs +147 -0
  185. package/src/runtime/shared/schedules-store.mjs +70 -0
  186. package/src/runtime/shared/tool-execution-contract.mjs +104 -0
  187. package/src/runtime/shared/tool-surface.mjs +947 -0
  188. package/src/runtime/shared/user-cwd.mjs +221 -0
  189. package/src/runtime/shared/user-data-guard.mjs +232 -0
  190. package/src/runtime/shared/workspace-router.mjs +259 -0
  191. package/src/standalone/bridge-tool.mjs +1414 -0
  192. package/src/standalone/channel-admin.mjs +366 -0
  193. package/src/standalone/channel-worker-preload.cjs +3 -0
  194. package/src/standalone/channel-worker.mjs +353 -0
  195. package/src/standalone/explore-tool.mjs +233 -0
  196. package/src/standalone/hook-bus.mjs +246 -0
  197. package/src/standalone/plugin-admin.mjs +247 -0
  198. package/src/standalone/provider-admin.mjs +338 -0
  199. package/src/standalone/seeds.mjs +94 -0
  200. package/src/standalone/usage-dashboard.mjs +510 -0
  201. package/src/tui/App.jsx +5446 -0
  202. package/src/tui/components/AnsiText.jsx +199 -0
  203. package/src/tui/components/ContextPanel.jsx +265 -0
  204. package/src/tui/components/Markdown.jsx +205 -0
  205. package/src/tui/components/MarkdownTable.jsx +204 -0
  206. package/src/tui/components/Message.jsx +103 -0
  207. package/src/tui/components/Picker.jsx +317 -0
  208. package/src/tui/components/PromptInput.jsx +584 -0
  209. package/src/tui/components/QueuedCommands.jsx +47 -0
  210. package/src/tui/components/SlashCommandPalette.jsx +114 -0
  211. package/src/tui/components/Spinner.jsx +317 -0
  212. package/src/tui/components/StatusLine.jsx +87 -0
  213. package/src/tui/components/TextEntryPanel.jsx +323 -0
  214. package/src/tui/components/ToolExecution.jsx +791 -0
  215. package/src/tui/components/TurnDone.jsx +78 -0
  216. package/src/tui/components/UsagePanel.jsx +331 -0
  217. package/src/tui/dist/index.mjs +12420 -0
  218. package/src/tui/engine.mjs +2410 -0
  219. package/src/tui/figures.mjs +50 -0
  220. package/src/tui/hooks/useEngine.mjs +16 -0
  221. package/src/tui/index.jsx +254 -0
  222. package/src/tui/input-editing.mjs +242 -0
  223. package/src/tui/markdown/format-token.mjs +194 -0
  224. package/src/tui/paste-attachments.mjs +198 -0
  225. package/src/tui/runtime/shared/process-shutdown.mjs +1 -0
  226. package/src/tui/spinner-verbs.mjs +45 -0
  227. package/src/tui/theme.mjs +67 -0
  228. package/src/tui/time-format.mjs +53 -0
  229. package/src/ui/ansi.mjs +115 -0
  230. package/src/ui/markdown.mjs +195 -0
  231. package/src/ui/statusline.mjs +730 -0
  232. package/src/ui/tool-card.mjs +99 -0
  233. package/src/vendor/statusline/bin/statusline-lib.mjs +805 -0
  234. package/src/vendor/statusline/bin/statusline-route.mjs +596 -0
  235. package/src/vendor/statusline/scripts/lib/gateway-settings.mjs +285 -0
  236. package/src/vendor/statusline/src/gateway/claude-current.mjs +320 -0
  237. package/src/vendor/statusline/src/gateway/route-meta.mjs +753 -0
  238. package/src/vendor/statusline/src/gateway/session-routes.mjs +244 -0
  239. package/src/workflows/default/WORKFLOW.md +7 -0
  240. package/src/workflows/default/workflow.json +14 -0
  241. package/vendor/ink/build/ansi-tokenizer.d.ts +38 -0
  242. package/vendor/ink/build/ansi-tokenizer.js +316 -0
  243. package/vendor/ink/build/ansi-tokenizer.js.map +1 -0
  244. package/vendor/ink/build/colorize.d.ts +3 -0
  245. package/vendor/ink/build/colorize.js +48 -0
  246. package/vendor/ink/build/colorize.js.map +1 -0
  247. package/vendor/ink/build/components/AccessibilityContext.d.ts +3 -0
  248. package/vendor/ink/build/components/AccessibilityContext.js +5 -0
  249. package/vendor/ink/build/components/AccessibilityContext.js.map +1 -0
  250. package/vendor/ink/build/components/AnimationContext.d.ts +9 -0
  251. package/vendor/ink/build/components/AnimationContext.js +13 -0
  252. package/vendor/ink/build/components/AnimationContext.js.map +1 -0
  253. package/vendor/ink/build/components/App.d.ts +24 -0
  254. package/vendor/ink/build/components/App.js +554 -0
  255. package/vendor/ink/build/components/App.js.map +1 -0
  256. package/vendor/ink/build/components/AppContext.d.ts +80 -0
  257. package/vendor/ink/build/components/AppContext.js +25 -0
  258. package/vendor/ink/build/components/AppContext.js.map +1 -0
  259. package/vendor/ink/build/components/BackgroundContext.d.ts +4 -0
  260. package/vendor/ink/build/components/BackgroundContext.js +3 -0
  261. package/vendor/ink/build/components/BackgroundContext.js.map +1 -0
  262. package/vendor/ink/build/components/Box.d.ts +130 -0
  263. package/vendor/ink/build/components/Box.js +34 -0
  264. package/vendor/ink/build/components/Box.js.map +1 -0
  265. package/vendor/ink/build/components/CursorContext.d.ts +11 -0
  266. package/vendor/ink/build/components/CursorContext.js +8 -0
  267. package/vendor/ink/build/components/CursorContext.js.map +1 -0
  268. package/vendor/ink/build/components/ErrorBoundary.d.ts +18 -0
  269. package/vendor/ink/build/components/ErrorBoundary.js +23 -0
  270. package/vendor/ink/build/components/ErrorBoundary.js.map +1 -0
  271. package/vendor/ink/build/components/ErrorOverview.d.ts +6 -0
  272. package/vendor/ink/build/components/ErrorOverview.js +90 -0
  273. package/vendor/ink/build/components/ErrorOverview.js.map +1 -0
  274. package/vendor/ink/build/components/FocusContext.d.ts +16 -0
  275. package/vendor/ink/build/components/FocusContext.js +17 -0
  276. package/vendor/ink/build/components/FocusContext.js.map +1 -0
  277. package/vendor/ink/build/components/Newline.d.ts +13 -0
  278. package/vendor/ink/build/components/Newline.js +8 -0
  279. package/vendor/ink/build/components/Newline.js.map +1 -0
  280. package/vendor/ink/build/components/Spacer.d.ts +7 -0
  281. package/vendor/ink/build/components/Spacer.js +11 -0
  282. package/vendor/ink/build/components/Spacer.js.map +1 -0
  283. package/vendor/ink/build/components/Static.d.ts +24 -0
  284. package/vendor/ink/build/components/Static.js +28 -0
  285. package/vendor/ink/build/components/Static.js.map +1 -0
  286. package/vendor/ink/build/components/StderrContext.d.ts +15 -0
  287. package/vendor/ink/build/components/StderrContext.js +13 -0
  288. package/vendor/ink/build/components/StderrContext.js.map +1 -0
  289. package/vendor/ink/build/components/StdinContext.d.ts +28 -0
  290. package/vendor/ink/build/components/StdinContext.js +20 -0
  291. package/vendor/ink/build/components/StdinContext.js.map +1 -0
  292. package/vendor/ink/build/components/StdoutContext.d.ts +15 -0
  293. package/vendor/ink/build/components/StdoutContext.js +13 -0
  294. package/vendor/ink/build/components/StdoutContext.js.map +1 -0
  295. package/vendor/ink/build/components/Text.d.ts +55 -0
  296. package/vendor/ink/build/components/Text.js +50 -0
  297. package/vendor/ink/build/components/Text.js.map +1 -0
  298. package/vendor/ink/build/components/Transform.d.ts +16 -0
  299. package/vendor/ink/build/components/Transform.js +15 -0
  300. package/vendor/ink/build/components/Transform.js.map +1 -0
  301. package/vendor/ink/build/cursor-helpers.d.ts +39 -0
  302. package/vendor/ink/build/cursor-helpers.js +62 -0
  303. package/vendor/ink/build/cursor-helpers.js.map +1 -0
  304. package/vendor/ink/build/devtools-window-polyfill.d.ts +1 -0
  305. package/vendor/ink/build/devtools-window-polyfill.js +68 -0
  306. package/vendor/ink/build/devtools-window-polyfill.js.map +1 -0
  307. package/vendor/ink/build/devtools.d.ts +1 -0
  308. package/vendor/ink/build/devtools.js +36 -0
  309. package/vendor/ink/build/devtools.js.map +1 -0
  310. package/vendor/ink/build/dom.d.ts +62 -0
  311. package/vendor/ink/build/dom.js +143 -0
  312. package/vendor/ink/build/dom.js.map +1 -0
  313. package/vendor/ink/build/get-max-width.d.ts +3 -0
  314. package/vendor/ink/build/get-max-width.js +10 -0
  315. package/vendor/ink/build/get-max-width.js.map +1 -0
  316. package/vendor/ink/build/hooks/use-animation.d.ts +49 -0
  317. package/vendor/ink/build/hooks/use-animation.js +87 -0
  318. package/vendor/ink/build/hooks/use-animation.js.map +1 -0
  319. package/vendor/ink/build/hooks/use-app.d.ts +5 -0
  320. package/vendor/ink/build/hooks/use-app.js +8 -0
  321. package/vendor/ink/build/hooks/use-app.js.map +1 -0
  322. package/vendor/ink/build/hooks/use-box-metrics.d.ts +59 -0
  323. package/vendor/ink/build/hooks/use-box-metrics.js +81 -0
  324. package/vendor/ink/build/hooks/use-box-metrics.js.map +1 -0
  325. package/vendor/ink/build/hooks/use-cursor.d.ts +12 -0
  326. package/vendor/ink/build/hooks/use-cursor.js +29 -0
  327. package/vendor/ink/build/hooks/use-cursor.js.map +1 -0
  328. package/vendor/ink/build/hooks/use-focus-manager.d.ts +43 -0
  329. package/vendor/ink/build/hooks/use-focus-manager.js +18 -0
  330. package/vendor/ink/build/hooks/use-focus-manager.js.map +1 -0
  331. package/vendor/ink/build/hooks/use-focus.d.ts +30 -0
  332. package/vendor/ink/build/hooks/use-focus.js +43 -0
  333. package/vendor/ink/build/hooks/use-focus.js.map +1 -0
  334. package/vendor/ink/build/hooks/use-input.d.ts +132 -0
  335. package/vendor/ink/build/hooks/use-input.js +126 -0
  336. package/vendor/ink/build/hooks/use-input.js.map +1 -0
  337. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.d.ts +6 -0
  338. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js +12 -0
  339. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -0
  340. package/vendor/ink/build/hooks/use-paste.d.ts +35 -0
  341. package/vendor/ink/build/hooks/use-paste.js +62 -0
  342. package/vendor/ink/build/hooks/use-paste.js.map +1 -0
  343. package/vendor/ink/build/hooks/use-stderr.d.ts +5 -0
  344. package/vendor/ink/build/hooks/use-stderr.js +8 -0
  345. package/vendor/ink/build/hooks/use-stderr.js.map +1 -0
  346. package/vendor/ink/build/hooks/use-stdin.d.ts +7 -0
  347. package/vendor/ink/build/hooks/use-stdin.js +9 -0
  348. package/vendor/ink/build/hooks/use-stdin.js.map +1 -0
  349. package/vendor/ink/build/hooks/use-stdout.d.ts +5 -0
  350. package/vendor/ink/build/hooks/use-stdout.js +8 -0
  351. package/vendor/ink/build/hooks/use-stdout.js.map +1 -0
  352. package/vendor/ink/build/hooks/use-window-size.d.ts +18 -0
  353. package/vendor/ink/build/hooks/use-window-size.js +22 -0
  354. package/vendor/ink/build/hooks/use-window-size.js.map +1 -0
  355. package/vendor/ink/build/index.d.ts +42 -0
  356. package/vendor/ink/build/index.js +24 -0
  357. package/vendor/ink/build/index.js.map +1 -0
  358. package/vendor/ink/build/ink.d.ts +146 -0
  359. package/vendor/ink/build/ink.js +1022 -0
  360. package/vendor/ink/build/ink.js.map +1 -0
  361. package/vendor/ink/build/input-parser.d.ts +10 -0
  362. package/vendor/ink/build/input-parser.js +194 -0
  363. package/vendor/ink/build/input-parser.js.map +1 -0
  364. package/vendor/ink/build/instances.d.ts +3 -0
  365. package/vendor/ink/build/instances.js +8 -0
  366. package/vendor/ink/build/instances.js.map +1 -0
  367. package/vendor/ink/build/kitty-keyboard.d.ts +23 -0
  368. package/vendor/ink/build/kitty-keyboard.js +32 -0
  369. package/vendor/ink/build/kitty-keyboard.js.map +1 -0
  370. package/vendor/ink/build/log-update.d.ts +20 -0
  371. package/vendor/ink/build/log-update.js +261 -0
  372. package/vendor/ink/build/log-update.js.map +1 -0
  373. package/vendor/ink/build/measure-element.d.ts +20 -0
  374. package/vendor/ink/build/measure-element.js +13 -0
  375. package/vendor/ink/build/measure-element.js.map +1 -0
  376. package/vendor/ink/build/measure-text.d.ts +6 -0
  377. package/vendor/ink/build/measure-text.js +21 -0
  378. package/vendor/ink/build/measure-text.js.map +1 -0
  379. package/vendor/ink/build/output.d.ts +35 -0
  380. package/vendor/ink/build/output.js +328 -0
  381. package/vendor/ink/build/output.js.map +1 -0
  382. package/vendor/ink/build/parse-keypress.d.ts +20 -0
  383. package/vendor/ink/build/parse-keypress.js +495 -0
  384. package/vendor/ink/build/parse-keypress.js.map +1 -0
  385. package/vendor/ink/build/reconciler.d.ts +4 -0
  386. package/vendor/ink/build/reconciler.js +306 -0
  387. package/vendor/ink/build/reconciler.js.map +1 -0
  388. package/vendor/ink/build/render-background.d.ts +4 -0
  389. package/vendor/ink/build/render-background.js +25 -0
  390. package/vendor/ink/build/render-background.js.map +1 -0
  391. package/vendor/ink/build/render-border.d.ts +4 -0
  392. package/vendor/ink/build/render-border.js +84 -0
  393. package/vendor/ink/build/render-border.js.map +1 -0
  394. package/vendor/ink/build/render-node-to-output.d.ts +14 -0
  395. package/vendor/ink/build/render-node-to-output.js +162 -0
  396. package/vendor/ink/build/render-node-to-output.js.map +1 -0
  397. package/vendor/ink/build/render-to-string.d.ts +38 -0
  398. package/vendor/ink/build/render-to-string.js +116 -0
  399. package/vendor/ink/build/render-to-string.js.map +1 -0
  400. package/vendor/ink/build/render.d.ts +176 -0
  401. package/vendor/ink/build/render.js +71 -0
  402. package/vendor/ink/build/render.js.map +1 -0
  403. package/vendor/ink/build/renderer.d.ts +8 -0
  404. package/vendor/ink/build/renderer.js +64 -0
  405. package/vendor/ink/build/renderer.js.map +1 -0
  406. package/vendor/ink/build/sanitize-ansi.d.ts +2 -0
  407. package/vendor/ink/build/sanitize-ansi.js +27 -0
  408. package/vendor/ink/build/sanitize-ansi.js.map +1 -0
  409. package/vendor/ink/build/squash-text-nodes.d.ts +3 -0
  410. package/vendor/ink/build/squash-text-nodes.js +36 -0
  411. package/vendor/ink/build/squash-text-nodes.js.map +1 -0
  412. package/vendor/ink/build/styles.d.ts +302 -0
  413. package/vendor/ink/build/styles.js +303 -0
  414. package/vendor/ink/build/styles.js.map +1 -0
  415. package/vendor/ink/build/utils.d.ts +9 -0
  416. package/vendor/ink/build/utils.js +19 -0
  417. package/vendor/ink/build/utils.js.map +1 -0
  418. package/vendor/ink/build/wrap-text.d.ts +3 -0
  419. package/vendor/ink/build/wrap-text.js +38 -0
  420. package/vendor/ink/build/wrap-text.js.map +1 -0
  421. package/vendor/ink/build/write-synchronized.d.ts +4 -0
  422. package/vendor/ink/build/write-synchronized.js +9 -0
  423. package/vendor/ink/build/write-synchronized.js.map +1 -0
  424. package/vendor/ink/license +10 -0
  425. package/vendor/ink/package.json +137 -0
  426. package/.claude-plugin/marketplace.json +0 -34
  427. package/.claude-plugin/plugin.json +0 -20
  428. package/.gitattributes +0 -34
  429. package/.mcp.json +0 -14
  430. package/ARCHITECTURE.md +0 -77
  431. package/CHANGELOG.md +0 -30
  432. package/CONTRIBUTING.md +0 -45
  433. package/DATA-FLOW.md +0 -79
  434. package/LICENSE +0 -21
  435. package/SECURITY.md +0 -138
  436. package/UNINSTALL.md +0 -115
  437. package/agents/maintenance.md +0 -5
  438. package/agents/memory-classification.md +0 -30
  439. package/agents/scheduler-task.md +0 -18
  440. package/agents/webhook-handler.md +0 -27
  441. package/agents/worker.md +0 -24
  442. package/bin/bridge +0 -133
  443. package/bin/statusline-launcher.mjs +0 -82
  444. package/bin/statusline-lib.mjs +0 -581
  445. package/bin/statusline-route.mjs +0 -273
  446. package/bin/statusline.mjs +0 -638
  447. package/bun.lock +0 -927
  448. package/commands/config.md +0 -16
  449. package/commands/doctor.md +0 -13
  450. package/commands/model.md +0 -61
  451. package/commands/setup.md +0 -17
  452. package/defaults/hidden-roles.json +0 -68
  453. package/defaults/memory-chunk-prompt.md +0 -63
  454. package/defaults/mixdog-config.template.json +0 -27
  455. package/defaults/user-workflow.json +0 -8
  456. package/defaults/user-workflow.md +0 -17
  457. package/hooks/hooks.json +0 -73
  458. package/hooks/lib/active-instance.cjs +0 -77
  459. package/hooks/lib/permission-evaluator.cjs +0 -411
  460. package/hooks/lib/permission-route.cjs +0 -63
  461. package/hooks/lib/settings-loader.cjs +0 -117
  462. package/hooks/post-tool-use.cjs +0 -84
  463. package/hooks/pre-mcp-sandbox.cjs +0 -158
  464. package/hooks/pre-tool-subagent.cjs +0 -258
  465. package/hooks/session-start.cjs +0 -1493
  466. package/hooks/shim-launcher.cjs +0 -65
  467. package/hooks/turn-timer.cjs +0 -82
  468. package/lib/claude-md-writer.cjs +0 -386
  469. package/lib/keychain-cjs.cjs +0 -290
  470. package/lib/plugin-paths.cjs +0 -69
  471. package/lib/rules-builder.cjs +0 -241
  472. package/native/README.md +0 -117
  473. package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
  474. package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
  475. package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
  476. package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
  477. package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
  478. package/prompts/code-review.txt +0 -16
  479. package/prompts/security-audit.txt +0 -17
  480. package/rules/bridge/00-common.md +0 -39
  481. package/rules/bridge/20-skip-protocol.md +0 -18
  482. package/rules/bridge/30-explorer.md +0 -33
  483. package/rules/bridge/40-cycle1-agent.md +0 -52
  484. package/rules/bridge/41-cycle2-agent.md +0 -62
  485. package/rules/lead/00-tool-lead.md +0 -61
  486. package/rules/lead/01-general.md +0 -26
  487. package/rules/lead/02-channels.md +0 -49
  488. package/rules/lead/03-team.md +0 -27
  489. package/rules/lead/04-workflow.md +0 -20
  490. package/rules/shared/00-language.md +0 -14
  491. package/rules/shared/01-tool.md +0 -138
  492. package/scripts/bootstrap.mjs +0 -130
  493. package/scripts/bridge-unify-smoke.mjs +0 -308
  494. package/scripts/build-runtime-linux.sh +0 -348
  495. package/scripts/build-runtime-macos.sh +0 -217
  496. package/scripts/build-runtime-windows.ps1 +0 -242
  497. package/scripts/builtin-utils-smoke.mjs +0 -398
  498. package/scripts/bump.mjs +0 -80
  499. package/scripts/check-json.mjs +0 -45
  500. package/scripts/check-syntax-changed.mjs +0 -102
  501. package/scripts/check-syntax.mjs +0 -58
  502. package/scripts/code-graph-batch.test.mjs +0 -33
  503. package/scripts/config-preserve-smoke.mjs +0 -180
  504. package/scripts/doctor.mjs +0 -489
  505. package/scripts/edit-normalize-fuzz.mjs +0 -130
  506. package/scripts/edit-normalize-smoke.mjs +0 -401
  507. package/scripts/edit-operation-smoke.mjs +0 -369
  508. package/scripts/edit2-smoke.mjs +0 -63
  509. package/scripts/ensure-deps.mjs +0 -259
  510. package/scripts/fuzzy-e2e.mjs +0 -28
  511. package/scripts/fuzzy-smoke.mjs +0 -26
  512. package/scripts/gateway-model.mjs +0 -596
  513. package/scripts/generate-runtime-manifest.mjs +0 -166
  514. package/scripts/guard-smoke.mjs +0 -66
  515. package/scripts/hidden-role-schema-smoke.mjs +0 -162
  516. package/scripts/hook-routing-smoke.mjs +0 -29
  517. package/scripts/inject-input.ps1 +0 -204
  518. package/scripts/io-complex-smoke.mjs +0 -667
  519. package/scripts/io-explore-bench.mjs +0 -424
  520. package/scripts/io-guardrails-smoke.mjs +0 -205
  521. package/scripts/io-mini-bench-baseline.json +0 -11
  522. package/scripts/io-mini-bench.mjs +0 -216
  523. package/scripts/io-route-harness.mjs +0 -933
  524. package/scripts/io-telemetry-report.mjs +0 -691
  525. package/scripts/lib/gateway-inventory.mjs +0 -178
  526. package/scripts/lib/gateway-settings.mjs +0 -78
  527. package/scripts/mutation-bench.mjs +0 -564
  528. package/scripts/mutation-io-smoke.mjs +0 -1097
  529. package/scripts/native-patch-bridge-smoke.mjs +0 -288
  530. package/scripts/native-patch-smoke.mjs +0 -304
  531. package/scripts/openai-oauth-catalog-smoke.mjs +0 -53
  532. package/scripts/patch-interior-context-smoke.mjs +0 -49
  533. package/scripts/patch-newline-utf8-smoke.mjs +0 -157
  534. package/scripts/perf-hook-smoke.mjs +0 -71
  535. package/scripts/permission-eval-smoke.mjs +0 -443
  536. package/scripts/prep-patch.mjs +0 -53
  537. package/scripts/prep-shim.mjs +0 -96
  538. package/scripts/provider-cache-smoke.mjs +0 -687
  539. package/scripts/report-runtime-health.mjs +0 -132
  540. package/scripts/resolve-bun.mjs +0 -60
  541. package/scripts/run-mcp.mjs +0 -1473
  542. package/scripts/salvage-v4a-shatter.test.mjs +0 -58
  543. package/scripts/scoped-cache-io-smoke.mjs +0 -103
  544. package/scripts/shell-policy-round3-smoke.mjs +0 -46
  545. package/scripts/smoke-runtime-negative.ps1 +0 -100
  546. package/scripts/smoke-runtime-negative.sh +0 -95
  547. package/scripts/stall-policy-smoke.mjs +0 -50
  548. package/scripts/start-memory-worker.mjs +0 -23
  549. package/scripts/statusline-launcher-smoke.mjs +0 -235
  550. package/scripts/stress-atomic-write.mjs +0 -1028
  551. package/scripts/test-fault-inject.mjs +0 -164
  552. package/scripts/test-large-file.mjs +0 -174
  553. package/scripts/tool-edge-smoke.mjs +0 -209
  554. package/scripts/uninstall.mjs +0 -238
  555. package/scripts/webhook-selfheal-smoke.mjs +0 -27
  556. package/scripts/write-overwrite-guard-smoke.mjs +0 -56
  557. package/server-main.mjs +0 -3350
  558. package/server.mjs +0 -468
  559. package/setup/config-merge.mjs +0 -246
  560. package/setup/install.mjs +0 -574
  561. package/setup/launch-core.mjs +0 -617
  562. package/setup/launch.mjs +0 -101
  563. package/setup/locate-claude.mjs +0 -56
  564. package/setup/mixdog-cli.mjs +0 -122
  565. package/setup/setup-server.mjs +0 -3305
  566. package/setup/setup.html +0 -3740
  567. package/setup/tui.mjs +0 -325
  568. package/skills/retro-skill-proposer/SKILL.md +0 -92
  569. package/skills/schedule-add/SKILL.md +0 -77
  570. package/skills/setup/SKILL.md +0 -356
  571. package/skills/webhook-add/SKILL.md +0 -81
  572. package/src/agent/bridge-stall-watchdog.mjs +0 -337
  573. package/src/agent/index.mjs +0 -2229
  574. package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +0 -1010
  575. package/src/agent/orchestrator/bridge-retry.mjs +0 -220
  576. package/src/agent/orchestrator/bridge-trace.mjs +0 -601
  577. package/src/agent/orchestrator/cache-mtime.mjs +0 -58
  578. package/src/agent/orchestrator/config.mjs +0 -405
  579. package/src/agent/orchestrator/context/collect.mjs +0 -651
  580. package/src/agent/orchestrator/dispatch-persist.mjs +0 -549
  581. package/src/agent/orchestrator/drain-registry.mjs +0 -50
  582. package/src/agent/orchestrator/explore-validator.mjs +0 -8
  583. package/src/agent/orchestrator/internal-roles.mjs +0 -118
  584. package/src/agent/orchestrator/internal-tools.mjs +0 -88
  585. package/src/agent/orchestrator/jobs.mjs +0 -116
  586. package/src/agent/orchestrator/mcp/client.mjs +0 -364
  587. package/src/agent/orchestrator/providers/anthropic-oauth.mjs +0 -1884
  588. package/src/agent/orchestrator/providers/anthropic.mjs +0 -598
  589. package/src/agent/orchestrator/providers/gemini.mjs +0 -1530
  590. package/src/agent/orchestrator/providers/grok-oauth.mjs +0 -779
  591. package/src/agent/orchestrator/providers/model-catalog.mjs +0 -374
  592. package/src/agent/orchestrator/providers/openai-compat-stream.mjs +0 -366
  593. package/src/agent/orchestrator/providers/openai-compat.mjs +0 -1511
  594. package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +0 -1891
  595. package/src/agent/orchestrator/providers/openai-oauth.mjs +0 -1456
  596. package/src/agent/orchestrator/providers/openai-ws.mjs +0 -127
  597. package/src/agent/orchestrator/providers/registry.mjs +0 -192
  598. package/src/agent/orchestrator/providers/retry-classifier.mjs +0 -325
  599. package/src/agent/orchestrator/session/cache/post-edit-marks.mjs +0 -42
  600. package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +0 -142
  601. package/src/agent/orchestrator/session/cache/read-cache.mjs +0 -319
  602. package/src/agent/orchestrator/session/cache/scoped-cache.mjs +0 -361
  603. package/src/agent/orchestrator/session/loop.mjs +0 -1619
  604. package/src/agent/orchestrator/session/manager.mjs +0 -1991
  605. package/src/agent/orchestrator/session/result-classification.mjs +0 -65
  606. package/src/agent/orchestrator/session/store.mjs +0 -632
  607. package/src/agent/orchestrator/session/stream-watchdog.mjs +0 -130
  608. package/src/agent/orchestrator/session/tool-result-offload.mjs +0 -166
  609. package/src/agent/orchestrator/session/trim.mjs +0 -491
  610. package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +0 -115
  611. package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +0 -331
  612. package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +0 -150
  613. package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +0 -228
  614. package/src/agent/orchestrator/smart-bridge/index.mjs +0 -215
  615. package/src/agent/orchestrator/smart-bridge/profiles.mjs +0 -37
  616. package/src/agent/orchestrator/smart-bridge/registry.mjs +0 -348
  617. package/src/agent/orchestrator/stall-policy.mjs +0 -201
  618. package/src/agent/orchestrator/tool-loop-guard.mjs +0 -75
  619. package/src/agent/orchestrator/tools/bash-session.mjs +0 -722
  620. package/src/agent/orchestrator/tools/builtin/advisory-lock.mjs +0 -171
  621. package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +0 -511
  622. package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -480
  623. package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +0 -256
  624. package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +0 -58
  625. package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +0 -240
  626. package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +0 -113
  627. package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +0 -74
  628. package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +0 -242
  629. package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +0 -211
  630. package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +0 -1364
  631. package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +0 -126
  632. package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +0 -141
  633. package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +0 -194
  634. package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +0 -60
  635. package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +0 -168
  636. package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +0 -173
  637. package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +0 -48
  638. package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +0 -99
  639. package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +0 -193
  640. package/src/agent/orchestrator/tools/builtin/list-tool.mjs +0 -597
  641. package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +0 -110
  642. package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +0 -300
  643. package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +0 -152
  644. package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +0 -118
  645. package/src/agent/orchestrator/tools/builtin/read-open.mjs +0 -190
  646. package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +0 -728
  647. package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +0 -173
  648. package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +0 -602
  649. package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +0 -196
  650. package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +0 -422
  651. package/src/agent/orchestrator/tools/builtin/search-builders.mjs +0 -158
  652. package/src/agent/orchestrator/tools/builtin/search-tool.mjs +0 -869
  653. package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +0 -962
  654. package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +0 -223
  655. package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +0 -206
  656. package/src/agent/orchestrator/tools/builtin/write-tool.mjs +0 -401
  657. package/src/agent/orchestrator/tools/builtin.mjs +0 -503
  658. package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +0 -24
  659. package/src/agent/orchestrator/tools/code-graph.mjs +0 -4095
  660. package/src/agent/orchestrator/tools/cwd-tool.mjs +0 -298
  661. package/src/agent/orchestrator/tools/destructive-warning.mjs +0 -323
  662. package/src/agent/orchestrator/tools/edit-normalize.mjs +0 -603
  663. package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +0 -154
  664. package/src/agent/orchestrator/tools/graph-manifest.json +0 -26
  665. package/src/agent/orchestrator/tools/host-input.mjs +0 -204
  666. package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +0 -143
  667. package/src/agent/orchestrator/tools/patch-manifest.json +0 -26
  668. package/src/agent/orchestrator/tools/patch-tool-defs.mjs +0 -20
  669. package/src/agent/orchestrator/tools/patch.mjs +0 -2754
  670. package/src/agent/orchestrator/tools/progress-message.mjs +0 -118
  671. package/src/agent/orchestrator/tools/shell-command.mjs +0 -865
  672. package/src/agent/orchestrator/tools/shell-policy-imports.mjs +0 -7
  673. package/src/agent/orchestrator/tools/shell-snapshot.mjs +0 -313
  674. package/src/agent/orchestrator/workflow-store.mjs +0 -93
  675. package/src/agent/tool-defs.mjs +0 -110
  676. package/src/channels/backends/discord.mjs +0 -784
  677. package/src/channels/data/voice-runtime-manifest.json +0 -138
  678. package/src/channels/index.mjs +0 -3268
  679. package/src/channels/lib/config.mjs +0 -292
  680. package/src/channels/lib/drop-trace.mjs +0 -71
  681. package/src/channels/lib/event-pipeline.mjs +0 -81
  682. package/src/channels/lib/holidays.mjs +0 -138
  683. package/src/channels/lib/hook-pipe-server.mjs +0 -822
  684. package/src/channels/lib/output-forwarder.mjs +0 -765
  685. package/src/channels/lib/runtime-paths.mjs +0 -552
  686. package/src/channels/lib/scheduler.mjs +0 -723
  687. package/src/channels/lib/session-discovery.mjs +0 -103
  688. package/src/channels/lib/state-file.mjs +0 -68
  689. package/src/channels/lib/status-snapshot.mjs +0 -219
  690. package/src/channels/lib/tool-format.mjs +0 -140
  691. package/src/channels/lib/transcript-discovery.mjs +0 -195
  692. package/src/channels/lib/voice-runtime-fetcher.mjs +0 -734
  693. package/src/channels/lib/webhook.mjs +0 -1318
  694. package/src/channels/tool-defs.mjs +0 -170
  695. package/src/daemon/host.mjs +0 -118
  696. package/src/daemon/mcp-transport.mjs +0 -47
  697. package/src/daemon/session.mjs +0 -100
  698. package/src/daemon/thin-client.mjs +0 -71
  699. package/src/daemon/transport.mjs +0 -163
  700. package/src/gateway/claude-current.mjs +0 -255
  701. package/src/gateway/oauth-usage.mjs +0 -598
  702. package/src/gateway/route-meta.mjs +0 -629
  703. package/src/gateway/server.mjs +0 -713
  704. package/src/memory/data/runtime-manifest.json +0 -40
  705. package/src/memory/index.mjs +0 -3332
  706. package/src/memory/lib/core-memory-store.mjs +0 -330
  707. package/src/memory/lib/embedding-provider.mjs +0 -269
  708. package/src/memory/lib/embedding-worker.mjs +0 -323
  709. package/src/memory/lib/memory-cycle1.mjs +0 -645
  710. package/src/memory/lib/memory-cycle2.mjs +0 -1284
  711. package/src/memory/lib/memory-cycle3.mjs +0 -540
  712. package/src/memory/lib/memory-embed.mjs +0 -299
  713. package/src/memory/lib/memory-ops-policy.mjs +0 -190
  714. package/src/memory/lib/memory-recall-store.mjs +0 -638
  715. package/src/memory/lib/memory.mjs +0 -412
  716. package/src/memory/lib/pg/adapter.mjs +0 -308
  717. package/src/memory/lib/pg/process.mjs +0 -360
  718. package/src/memory/lib/pg/supervisor.mjs +0 -396
  719. package/src/memory/lib/runtime-fetcher.mjs +0 -458
  720. package/src/memory/lib/trace-store.mjs +0 -728
  721. package/src/memory/tool-defs.mjs +0 -79
  722. package/src/search/index.mjs +0 -1173
  723. package/src/search/lib/backends/anthropic-oauth.mjs +0 -98
  724. package/src/search/lib/backends/exa.mjs +0 -50
  725. package/src/search/lib/backends/firecrawl.mjs +0 -61
  726. package/src/search/lib/backends/gemini-api.mjs +0 -83
  727. package/src/search/lib/backends/grok-oauth.mjs +0 -86
  728. package/src/search/lib/backends/index.mjs +0 -150
  729. package/src/search/lib/backends/openai-api.mjs +0 -144
  730. package/src/search/lib/backends/openai-oauth.mjs +0 -102
  731. package/src/search/lib/backends/openai-web-search.mjs +0 -76
  732. package/src/search/lib/backends/tavily.mjs +0 -55
  733. package/src/search/lib/backends/xai-api.mjs +0 -113
  734. package/src/search/lib/config.mjs +0 -192
  735. package/src/search/lib/provider-usage.mjs +0 -67
  736. package/src/search/lib/providers.mjs +0 -47
  737. package/src/search/lib/search-intent.mjs +0 -109
  738. package/src/search/lib/setup-handler.mjs +0 -261
  739. package/src/search/lib/web-tools.mjs +0 -1219
  740. package/src/search/tool-defs.mjs +0 -83
  741. package/src/setup/defender-exclusion.mjs +0 -183
  742. package/src/shared/atomic-file.mjs +0 -436
  743. package/src/shared/config.mjs +0 -372
  744. package/src/shared/daemon-recycle.mjs +0 -108
  745. package/src/shared/disable-claude-builtins.mjs +0 -91
  746. package/src/shared/err-text.mjs +0 -12
  747. package/src/shared/llm/http-agent.mjs +0 -123
  748. package/src/shared/open-url.mjs +0 -62
  749. package/src/shared/plugin-paths.mjs +0 -58
  750. package/src/shared/schedules-store.mjs +0 -70
  751. package/src/shared/seed.mjs +0 -161
  752. package/src/shared/user-cwd.mjs +0 -225
  753. package/src/shared/user-data-guard.mjs +0 -244
  754. package/src/status/aggregator.mjs +0 -584
  755. package/src/status/server.mjs +0 -413
  756. package/tools.json +0 -1671
  757. /package/{defaults → src/defaults}/cycle3-review-prompt.md +0 -0
  758. /package/{defaults → src/defaults}/memory-promote-prompt.md +0 -0
  759. /package/{hooks → src/hooks}/lib/permission-rules.cjs +0 -0
  760. /package/{lib → src/lib}/config-cjs.cjs +0 -0
  761. /package/{lib → src/lib}/hook-pipe-path.cjs +0 -0
  762. /package/{lib → src/lib}/mixdog-debug.cjs +0 -0
  763. /package/{lib → src/lib}/text-utils.cjs +0 -0
  764. /package/{rules → src/rules}/bridge/42-cycle3-agent.md +0 -0
  765. /package/src/{agent → runtime/agent}/orchestrator/activity-bus.mjs +0 -0
  766. /package/src/{agent → runtime/agent}/orchestrator/providers/anthropic-betas.mjs +0 -0
  767. /package/src/{agent → runtime/agent}/orchestrator/session/abort-lookup.mjs +0 -0
  768. /package/src/{agent → runtime/agent}/orchestrator/session/cache/scoped-cache-outcome.mjs +0 -0
  769. /package/src/{agent → runtime/agent}/orchestrator/session/cache/util.mjs +0 -0
  770. /package/src/{agent → runtime/agent}/orchestrator/session/read-dedup.mjs +0 -0
  771. /package/src/{agent → runtime/agent}/orchestrator/session/save-session-worker.mjs +0 -0
  772. /package/src/{agent → runtime/agent}/orchestrator/smart-bridge/session-builder.mjs +0 -0
  773. /package/src/{agent → runtime/agent}/orchestrator/tools/bash-policy-scan.mjs +0 -0
  774. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/atomic-write.mjs +0 -0
  775. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/binary-file.mjs +0 -0
  776. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/cache-layers.mjs +0 -0
  777. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/cwd-utils.mjs +0 -0
  778. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/device-paths.mjs +0 -0
  779. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -0
  780. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/diff-utils.mjs +0 -0
  781. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/fs-reachability.mjs +0 -0
  782. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/grep-formatting.mjs +0 -0
  783. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/hash-utils.mjs +0 -0
  784. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/list-formatting.mjs +0 -0
  785. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/open-config-tool.mjs +0 -0
  786. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/path-locks.mjs +0 -0
  787. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/path-utils.mjs +0 -0
  788. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-args.mjs +0 -0
  789. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-batch.mjs +0 -0
  790. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-constants.mjs +0 -0
  791. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-image-resize.mjs +0 -0
  792. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-image.mjs +0 -0
  793. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-lines.mjs +0 -0
  794. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-mode-tool.mjs +0 -0
  795. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-range-index.mjs +0 -0
  796. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-ranges.mjs +0 -0
  797. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-special-files.mjs +0 -0
  798. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-tool.mjs +0 -0
  799. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-windows.mjs +0 -0
  800. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/shell-analysis.mjs +0 -0
  801. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/shell-output.mjs +0 -0
  802. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/snapshot-helpers.mjs +0 -0
  803. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/snapshot-validation.mjs +0 -0
  804. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/text-stats.mjs +0 -0
  805. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/windows-roots.mjs +0 -0
  806. /package/src/{agent → runtime/agent}/orchestrator/tools/code-graph-prewarm-worker.mjs +0 -0
  807. /package/src/{agent → runtime/agent}/orchestrator/tools/env-scrub.mjs +0 -0
  808. /package/src/{agent → runtime/agent}/orchestrator/tools/mutation-content-cache.mjs +0 -0
  809. /package/src/{agent → runtime/agent}/orchestrator/tools/mutation-planner.mjs +0 -0
  810. /package/src/{agent → runtime/agent}/orchestrator/tools/next-call-utils.mjs +0 -0
  811. /package/src/{agent → runtime/agent}/orchestrator/tools/result-compression.mjs +0 -0
  812. /package/src/{agent → runtime/agent}/orchestrator/tools/shell-exec-policy.mjs +0 -0
  813. /package/src/{agent → runtime/agent}/orchestrator/tools/shell-policy-danger-target.mjs +0 -0
  814. /package/src/{agent → runtime/agent}/orchestrator/tools/shell-policy.mjs +0 -0
  815. /package/src/{channels → runtime/channels}/lib/cli-worker-host.mjs +0 -0
  816. /package/src/{channels → runtime/channels}/lib/config-lock.mjs +0 -0
  817. /package/src/{channels → runtime/channels}/lib/event-queue.mjs +0 -0
  818. /package/src/{channels → runtime/channels}/lib/executor.mjs +0 -0
  819. /package/src/{channels → runtime/channels}/lib/format.mjs +0 -0
  820. /package/src/{channels → runtime/channels}/lib/interaction-workflows.mjs +0 -0
  821. /package/src/{channels → runtime/channels}/lib/memory-client.mjs +0 -0
  822. /package/src/{channels → runtime/channels}/lib/session-control.mjs +0 -0
  823. /package/src/{channels → runtime/channels}/lib/settings.mjs +0 -0
  824. /package/src/{channels → runtime/channels}/lib/whisper-server.mjs +0 -0
  825. /package/src/{memory → runtime/memory}/lib/agent-ipc.mjs +0 -0
  826. /package/src/{memory → runtime/memory}/lib/bridge-trace-queries.mjs +0 -0
  827. /package/src/{memory → runtime/memory}/lib/llm-worker-host.mjs +0 -0
  828. /package/src/{memory → runtime/memory}/lib/memory-cycle.mjs +0 -0
  829. /package/src/{memory → runtime/memory}/lib/memory-extraction.mjs +0 -0
  830. /package/src/{memory → runtime/memory}/lib/memory-maintenance-store.mjs +0 -0
  831. /package/src/{memory → runtime/memory}/lib/memory-recall-id-patch.mjs +0 -0
  832. /package/src/{memory → runtime/memory}/lib/memory-recall-read-query.mjs +0 -0
  833. /package/src/{memory → runtime/memory}/lib/memory-recall-scope-filter.mjs +0 -0
  834. /package/src/{memory → runtime/memory}/lib/memory-retrievers.mjs +0 -0
  835. /package/src/{memory → runtime/memory}/lib/memory-score.mjs +0 -0
  836. /package/src/{memory → runtime/memory}/lib/memory-text-utils.mjs +0 -0
  837. /package/src/{memory → runtime/memory}/lib/model-profile.mjs +0 -0
  838. /package/src/{memory → runtime/memory}/lib/project-id-resolver.mjs +0 -0
  839. /package/src/{search → runtime/search}/lib/cache.mjs +0 -0
  840. /package/src/{search → runtime/search}/lib/formatter.mjs +0 -0
  841. /package/src/{search → runtime/search}/lib/state.mjs +0 -0
  842. /package/src/{shared → runtime/shared}/abort-controller.mjs +0 -0
  843. /package/src/{shared → runtime/shared}/llm/cost.mjs +0 -0
  844. /package/src/{shared → runtime/shared}/llm/index.mjs +0 -0
  845. /package/src/{shared → runtime/shared}/llm/pid-cleanup.mjs +0 -0
  846. /package/src/{shared → runtime/shared}/llm/usage-log.mjs +0 -0
  847. /package/src/{shared → runtime/shared}/wsl.mjs +0 -0
@@ -0,0 +1,959 @@
1
+ /**
2
+ * Grok CLI OAuth provider ("Grok Build").
3
+ *
4
+ * Authenticates against xAI's shared OAuth client via PKCE (discovery at
5
+ * https://auth.x.ai/.well-known/openid-configuration). Credentials come from
6
+ * either mixdog's own token store (grok-oauth.json) OR the Grok CLI's
7
+ * ~/.grok/auth.json — the same dual-source pattern openai-oauth uses with
8
+ * ~/.codex/auth.json — so an existing `grok` CLI login is picked up without a
9
+ * second sign-in.
10
+ *
11
+ * Inference + catalog merge two sources, routed per model:
12
+ * - api.x.ai/v1 (default): grok-4.x chat models and the web_search backend.
13
+ * - cli-chat-proxy.grok.com/v1 (the grok-build proxy): proxy-only models
14
+ * grok-build and grok-composer-2.5-fast, which api.x.ai does not publish.
15
+ * The proxy version-gates /responses (HTTP 426); we clear it with the Grok
16
+ * CLI client headers (proxyHeaders, real local version from version.json).
17
+ *
18
+ * Inference is delegated to an inner OpenAICompatProvider('xai') — the only
19
+ * preset wired for the Responses API — with the base URL + (for proxy models)
20
+ * the CLI headers injected via config.extraHeaders, bearer swapped for the
21
+ * OAuth access token. The model catalog is the union of both endpoints.
22
+ */
23
+ import { createServer } from 'http';
24
+ import { randomBytes, createHash } from 'crypto';
25
+ import { readFileSync, existsSync, mkdirSync, statSync, unlinkSync } from 'fs';
26
+ import { join } from 'path';
27
+ import { homedir } from 'os';
28
+ import { getPluginData } from '../config.mjs';
29
+ import { writeJsonAtomicSync } from '../../../shared/atomic-file.mjs';
30
+ import { enrichModels, getModelMetadataSync } from './model-catalog.mjs';
31
+ import { makeModelCache } from './model-cache.mjs';
32
+ import { OpenAICompatProvider } from './openai-compat.mjs';
33
+ import { createTimeoutSignal } from '../stall-policy.mjs';
34
+ import { populateHttpStatusFromMessage } from './retry-classifier.mjs';
35
+ import { getLlmDispatcher, preconnect } from '../../../shared/llm/http-agent.mjs';
36
+
37
+ // --- Constants ---
38
+ // xAI's shared OAuth client. The consent screen renders this as "Grok Build".
39
+ const CLIENT_ID = 'b1a00492-073a-47ea-816f-4c329264a828';
40
+ const ISSUER = 'https://auth.x.ai';
41
+ const DISCOVERY_URL = `${ISSUER}/.well-known/openid-configuration`;
42
+ const SCOPE = 'openid profile email offline_access grok-cli:access api:access';
43
+ const CALLBACK_HOST = '127.0.0.1';
44
+ const CALLBACK_PORT = 56121;
45
+ const CALLBACK_PATH = '/callback';
46
+ const REDIRECT_URI = `http://${CALLBACK_HOST}:${CALLBACK_PORT}${CALLBACK_PATH}`;
47
+ // Primary inference + search target. The OAuth token's `api:access` scope works
48
+ // against the STANDARD xAI API (GET /models 200, POST /responses 200, web_search
49
+ // 200 with citations). grok-4.x and web search live here. Proxy-only models
50
+ // (grok-build, grok-composer-2.5-fast) are NOT published on api.x.ai — they route
51
+ // to PROXY_BASE_URL below, which is version-gated and needs the Grok CLI client
52
+ // headers (see proxyHeaders).
53
+ const INFERENCE_BASE_URL = 'https://api.x.ai/v1';
54
+ const TOKEN_REFRESH_SKEW_MS = 5 * 60_000;
55
+
56
+ // --- grok-build CLI proxy (Composer 2.5, grok-build) ---
57
+ // These models live ONLY on the grok-build proxy, not api.x.ai. /models is
58
+ // readable with the bare OAuth bearer; /responses is version-gated (HTTP 426)
59
+ // and requires the Grok CLI's client headers. We route only proxy-only models
60
+ // here and keep grok-4.x + search on api.x.ai.
61
+ const PROXY_BASE_URL = 'https://cli-chat-proxy.grok.com/v1';
62
+ const GROK_CLIENT_IDENTIFIER = 'grok-shell';
63
+ const GROK_CLI_VERSION_FALLBACK = '0.2.16';
64
+
65
+ // Route to the proxy: any grok-composer* model, plus the bare `grok-build`
66
+ // coding agent. NOT grok-build-0.1 — that is a real api.x.ai model and must stay
67
+ // on api.x.ai, so we match grok-build exactly rather than by prefix.
68
+ const PROXY_EXACT_MODELS = new Set(['grok-build']);
69
+ function isProxyOnlyModel(model) {
70
+ const m = String(model || '');
71
+ return /^grok-composer/i.test(m) || PROXY_EXACT_MODELS.has(m);
72
+ }
73
+
74
+ // Use the REAL installed Grok CLI version for the proxy version gate
75
+ // (x-grok-client-version), read from ~/.grok/version.json (or the version
76
+ // stamped into models_cache.json). Cached; only falls back to a known-good
77
+ // constant when neither local file is readable.
78
+ let _grokCliVersionCache = null;
79
+ function grokCliVersion() {
80
+ if (_grokCliVersionCache) return _grokCliVersionCache;
81
+ const grokDir = join(homedir(), '.grok');
82
+ for (const [file, field] of [['version.json', 'version'], ['models_cache.json', 'grok_version']]) {
83
+ try {
84
+ const raw = JSON.parse(readFileSync(join(grokDir, file), 'utf-8'));
85
+ const v = String(raw?.[field] || raw?.stable_version || '').trim();
86
+ if (v) { _grokCliVersionCache = v; return v; }
87
+ } catch { /* try next source */ }
88
+ }
89
+ _grokCliVersionCache = GROK_CLI_VERSION_FALLBACK;
90
+ return _grokCliVersionCache;
91
+ }
92
+
93
+ // Headers the Grok CLI sends to clear the proxy version gate — extracted from
94
+ // the grok binary: x-grok-client-version (the actual 426 gate),
95
+ // x-grok-client-identifier, and a matching User-Agent.
96
+ function proxyHeaders() {
97
+ const v = grokCliVersion();
98
+ return {
99
+ 'x-grok-client-version': v,
100
+ 'x-grok-client-identifier': GROK_CLIENT_IDENTIFIER,
101
+ 'User-Agent': `xai-grok-build/${v}`,
102
+ };
103
+ }
104
+
105
+ function resolveGrokOAuthResponsesTransport(config, proxy) {
106
+ // Proxy-only models route through cli-chat-proxy.grok.com; the shared xAI
107
+ // WebSocket connector targets api.x.ai, so keep proxy models on HTTP.
108
+ if (proxy) return 'http';
109
+ const raw = config?.responsesTransport
110
+ ?? config?.transport
111
+ ?? process.env.MIXDOG_GROK_OAUTH_RESPONSES_TRANSPORT
112
+ ?? process.env.MIXDOG_GROK_OAUTH_TRANSPORT
113
+ ?? '';
114
+ const mode = String(raw).trim().toLowerCase();
115
+ return mode || 'http';
116
+ }
117
+
118
+ // Retired model aliases xAI no longer exposes by their old ids. The live
119
+ // catalog surfaces the coding model as grok-build-0.1; map the legacy ids to
120
+ // it so a stale config selection doesn't hit a model-not-found. Exact table,
121
+ // not a heuristic. Mirrors openclaw extensions/xai/model-definitions.ts.
122
+ const RETIRED_MODEL_ALIASES = Object.freeze({
123
+ 'grok-code-fast-1': 'grok-build-0.1',
124
+ 'grok-code-fast': 'grok-build-0.1',
125
+ 'grok-code-fast-1-0825': 'grok-build-0.1',
126
+ });
127
+ export function normalizeGrokModelId(id) {
128
+ return (id && RETIRED_MODEL_ALIASES[id]) || id;
129
+ }
130
+ const MODEL_CACHE_TTL_MS = 24 * 60 * 60_000;
131
+ const DISCOVERY_TIMEOUT_MS = 15_000;
132
+ const TOKEN_TIMEOUT_MS = 30_000;
133
+ const LOGIN_TIMEOUT_MS = 5 * 60_000;
134
+
135
+ // Grok CLI credential file. Composite top-level key is "<issuer>::<client_id>".
136
+ function grokCliAuthPath() {
137
+ return join(homedir(), '.grok', 'auth.json');
138
+ }
139
+
140
+ // SSRF guard for any endpoint pulled from the discovery document or saved
141
+ // tokens. xAI OAuth endpoints must be https on x.ai / *.x.ai — reject
142
+ // anything else outright so a hostile discovery response can't redirect the
143
+ // token / refresh request. Mirrors openclaw's isTrustedXaiOAuthEndpoint.
144
+ function assertTrustedXaiEndpoint(endpoint, label) {
145
+ let url;
146
+ try {
147
+ url = new URL(String(endpoint));
148
+ } catch {
149
+ throw new Error(`[grok-oauth] invalid ${label}: ${endpoint}`);
150
+ }
151
+ const host = url.hostname.toLowerCase();
152
+ if (url.protocol !== 'https:' || (host !== 'x.ai' && !host.endsWith('.x.ai'))) {
153
+ throw new Error(`[grok-oauth] untrusted ${label}: ${endpoint}`);
154
+ }
155
+ return url.toString();
156
+ }
157
+
158
+ let _discoveryCache = null;
159
+ async function fetchDiscovery() {
160
+ if (_discoveryCache) return _discoveryCache;
161
+ const timeout = createTimeoutSignal(null, DISCOVERY_TIMEOUT_MS, 'grok-oauth discovery');
162
+ try {
163
+ const res = await fetch(DISCOVERY_URL, {
164
+ headers: { Accept: 'application/json' },
165
+ // No redirect-following: the discovery doc is a fixed well-known URL.
166
+ // A 3xx could bounce the request to an untrusted host before the
167
+ // endpoint trust checks below ever run.
168
+ redirect: 'error',
169
+ signal: timeout.signal,
170
+ dispatcher: getLlmDispatcher(),
171
+ });
172
+ if (!res.ok) throw new Error(`discovery ${res.status}`);
173
+ const j = await res.json();
174
+ const discovery = {
175
+ authorization_endpoint: assertTrustedXaiEndpoint(j?.authorization_endpoint, 'authorization endpoint'),
176
+ token_endpoint: assertTrustedXaiEndpoint(j?.token_endpoint, 'token endpoint'),
177
+ };
178
+ _discoveryCache = discovery;
179
+ return discovery;
180
+ } finally {
181
+ timeout.cleanup();
182
+ }
183
+ }
184
+
185
+ // --- Token store ---
186
+ function getOwnTokenPath() {
187
+ const dir = getPluginData();
188
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
189
+ return join(dir, 'grok-oauth.json');
190
+ }
191
+
192
+ // expires_at may arrive as a unix number (own store) or an ISO-8601 string
193
+ // (Grok CLI auth.json). Normalize both to epoch milliseconds; 0 means unknown.
194
+ function _normalizeExpiresAt(value) {
195
+ if (typeof value === 'string') {
196
+ const ms = Date.parse(value);
197
+ return Number.isFinite(ms) ? ms : 0;
198
+ }
199
+ const n = Number(value || 0);
200
+ if (!Number.isFinite(n) || n <= 0) return 0;
201
+ return n < 1e12 ? n * 1000 : n;
202
+ }
203
+
204
+ // Fallback expiry from the access_token's JWT `exp` claim (epoch ms) when the
205
+ // store carries no explicit expires_at — without it expires_at stays 0, which
206
+ // ensureAuth reads as "never expires", disabling proactive refresh. Returns 0
207
+ // for opaque (non-JWT) tokens. JWT `exp` is epoch SECONDS (RFC 7519).
208
+ function _expiryFromAccessToken(token) {
209
+ try {
210
+ const parts = String(token || '').split('.');
211
+ if (parts.length !== 3) return 0;
212
+ const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf-8'));
213
+ const exp = Number(payload?.exp);
214
+ return Number.isFinite(exp) && exp > 0 ? exp * 1000 : 0;
215
+ } catch { return 0; }
216
+ }
217
+
218
+ function _mtimeMs(path) {
219
+ try { return statSync(path).mtimeMs; } catch { return 0; }
220
+ }
221
+
222
+ // mixdog's own login store (grok-oauth.json). Single writer, accurate
223
+ // numeric expires_at from refresh.
224
+ function _loadOwnTokens() {
225
+ const path = getOwnTokenPath();
226
+ if (!existsSync(path)) return null;
227
+ try {
228
+ const raw = JSON.parse(readFileSync(path, 'utf-8'));
229
+ if (!raw?.access_token || !raw?.refresh_token) return null;
230
+ return {
231
+ access_token: raw.access_token,
232
+ refresh_token: raw.refresh_token,
233
+ expires_at: _normalizeExpiresAt(raw.expires_at ?? raw.expiresAt) || _expiryFromAccessToken(raw.access_token),
234
+ token_endpoint: raw.token_endpoint || null,
235
+ source: 'own',
236
+ mtimeMs: _mtimeMs(path),
237
+ };
238
+ } catch { return null; }
239
+ }
240
+
241
+ // Grok CLI store (~/.grok/auth.json). Read-only seed: the access token lives
242
+ // under `key`, keyed by "<issuer>::<client_id>". We never write back here —
243
+ // after the first refresh mixdog manages its own copy, mirroring how
244
+ // openai-oauth treats ~/.codex/auth.json.
245
+ function _loadGrokCliTokens() {
246
+ const path = grokCliAuthPath();
247
+ if (!existsSync(path)) return null;
248
+ try {
249
+ const raw = JSON.parse(readFileSync(path, 'utf-8'));
250
+ if (!raw || typeof raw !== 'object') return null;
251
+ // The Grok CLI keys every entry by "<issuer>::<client_id>" — look up
252
+ // exactly that. No scan-for-matching-client_id fallback: a different
253
+ // issuer under the same client_id is a different account/endpoint and
254
+ // must not be silently selected.
255
+ const entry = raw[`${ISSUER}::${CLIENT_ID}`];
256
+ if (!entry?.key || !entry?.refresh_token) return null;
257
+ return {
258
+ access_token: entry.key,
259
+ refresh_token: entry.refresh_token,
260
+ expires_at: _normalizeExpiresAt(entry.expires_at) || _expiryFromAccessToken(entry.key),
261
+ token_endpoint: null,
262
+ source: 'grok-cli',
263
+ mtimeMs: _mtimeMs(path),
264
+ };
265
+ } catch { return null; }
266
+ }
267
+
268
+ // Own store first (accurate expires_at). Fall back to the Grok CLI login.
269
+ function loadTokens() {
270
+ return _loadOwnTokens() || _loadGrokCliTokens();
271
+ }
272
+
273
+ function saveTokens(tokens) {
274
+ writeJsonAtomicSync(getOwnTokenPath(), {
275
+ access_token: tokens.access_token,
276
+ refresh_token: tokens.refresh_token,
277
+ expires_at: tokens.expires_at || 0,
278
+ token_endpoint: tokens.token_endpoint || null,
279
+ }, { lock: true, fsyncDir: true });
280
+ }
281
+
282
+ function _scrubTokens(text) {
283
+ return String(text || '')
284
+ .replace(/Bearer [A-Za-z0-9._\-]+/g, 'Bearer [REDACTED]')
285
+ .replace(/"access_token"\s*:\s*"[^"]+"/g, '"access_token":"[REDACTED]"')
286
+ .replace(/"refresh_token"\s*:\s*"[^"]+"/g, '"refresh_token":"[REDACTED]"')
287
+ .replace(/"key"\s*:\s*"[^"]+"/g, '"key":"[REDACTED]"');
288
+ }
289
+
290
+ // Public predicate used by config.buildDefaultConfig — enabled when either
291
+ // token source carries credentials. Single truth: same loader the runtime uses.
292
+ export function hasGrokOAuthCredentials() {
293
+ try {
294
+ const tokens = loadTokens();
295
+ return !!(tokens?.access_token && tokens?.refresh_token);
296
+ } catch { return false; }
297
+ }
298
+
299
+ export function describeGrokOAuthCredentials() {
300
+ try {
301
+ const tokens = loadTokens();
302
+ if (!tokens?.access_token) {
303
+ return { authenticated: false, status: 'Not Set', detail: '~/.grok/auth.json or mixdog token store' };
304
+ }
305
+ const hasRefresh = Boolean(tokens.refresh_token);
306
+ const expiresAt = _normalizeExpiresAt(tokens.expires_at);
307
+ const expiring = expiresAt > 0 && expiresAt < Date.now() + TOKEN_REFRESH_SKEW_MS;
308
+ const expired = expiresAt > 0 && expiresAt <= Date.now();
309
+ const detail = tokens.source === 'own'
310
+ ? 'Mixdog token store'
311
+ : tokens.source === 'grok-cli'
312
+ ? '~/.grok/auth.json'
313
+ : (tokens.source || 'oauth');
314
+ if (!hasRefresh) {
315
+ return {
316
+ authenticated: expiresAt === 0 || !expired,
317
+ status: expired ? 'Reauth Required' : 'Access Only',
318
+ detail: `${detail}; no refresh token`,
319
+ expiresAt,
320
+ };
321
+ }
322
+ if (expired) return { authenticated: true, status: 'Refresh Required', detail, expiresAt };
323
+ if (expiring) return { authenticated: true, status: 'Refresh Soon', detail, expiresAt };
324
+ return { authenticated: true, status: 'Valid', detail, expiresAt };
325
+ } catch (err) {
326
+ return { authenticated: false, status: 'Error', detail: String(err?.message || err).slice(0, 200) };
327
+ }
328
+ }
329
+
330
+ export function forgetGrokOAuthCredentials() {
331
+ let removed = false;
332
+ const ownPath = getOwnTokenPath();
333
+ if (existsSync(ownPath)) {
334
+ unlinkSync(ownPath);
335
+ removed = true;
336
+ }
337
+ const cliPath = grokCliAuthPath();
338
+ if (existsSync(cliPath)) {
339
+ try {
340
+ const raw = JSON.parse(readFileSync(cliPath, 'utf-8'));
341
+ const key = `${ISSUER}::${CLIENT_ID}`;
342
+ if (raw?.[key]) {
343
+ delete raw[key];
344
+ writeJsonAtomicSync(cliPath, raw, { lock: true, fsyncDir: true });
345
+ removed = true;
346
+ }
347
+ } catch (err) {
348
+ throw new Error(`Grok OAuth reset failed for ${cliPath}: ${err?.message || err}`);
349
+ }
350
+ }
351
+ return { removed };
352
+ }
353
+
354
+ // Write rotated tokens back to the Grok CLI store (~/.grok/auth.json) so the
355
+ // CLI — and any other reader of this single-use refresh-token lineage — picks
356
+ // up the rotation instead of replaying a now-consumed token. Mirrors
357
+ // anthropic-oauth's credential write-back. Best-effort:
358
+ // the own store is the authority, so a failed write-back never breaks a
359
+ // successful refresh. Host-owned file: no secret/mode so we don't re-permission it.
360
+ function _writeBackGrokCliTokens(refreshed) {
361
+ const path = grokCliAuthPath();
362
+ if (!existsSync(path)) return;
363
+ try {
364
+ const raw = JSON.parse(readFileSync(path, 'utf-8'));
365
+ const entry = raw?.[`${ISSUER}::${CLIENT_ID}`];
366
+ if (!entry || typeof entry !== 'object') return;
367
+ entry.key = refreshed.access_token;
368
+ entry.refresh_token = refreshed.refresh_token;
369
+ entry.expires_at = new Date(refreshed.expires_at || Date.now()).toISOString();
370
+ // Preserve the host file's existing POSIX mode — writeJsonAtomicSync
371
+ // otherwise defaults the replacement to 0o600, re-permissioning a file
372
+ // the Grok CLI owns.
373
+ let mode;
374
+ try { mode = statSync(path).mode & 0o777; } catch { /* keep helper default */ }
375
+ writeJsonAtomicSync(path, raw, { lock: true, fsyncDir: true, mode });
376
+ } catch (err) {
377
+ process.stderr.write(`[grok-oauth] CLI store write-back failed: ${_scrubTokens(err?.message || String(err)).slice(0, 200)}\n`);
378
+ }
379
+ }
380
+
381
+ let _refreshInFlight = null;
382
+ async function refreshTokens(tokens) {
383
+ if (!tokens?.refresh_token) {
384
+ throw new Error('[grok-oauth] refresh token not available — run the Grok CLI login or the Setup login again');
385
+ }
386
+ const tokenEndpoint = tokens.token_endpoint
387
+ ? assertTrustedXaiEndpoint(tokens.token_endpoint, 'token endpoint')
388
+ : (await fetchDiscovery()).token_endpoint;
389
+ const timeout = createTimeoutSignal(null, TOKEN_TIMEOUT_MS, 'grok-oauth refresh');
390
+ try {
391
+ const res = await fetch(tokenEndpoint, {
392
+ method: 'POST',
393
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
394
+ body: new URLSearchParams({
395
+ grant_type: 'refresh_token',
396
+ client_id: CLIENT_ID,
397
+ refresh_token: tokens.refresh_token,
398
+ }),
399
+ // Never follow a redirect on a secret-bearing request: a trusted
400
+ // token endpoint that 307/308-redirects would replay the
401
+ // refresh_token to the redirect target. Fail loud instead.
402
+ redirect: 'error',
403
+ signal: timeout.signal,
404
+ dispatcher: getLlmDispatcher(),
405
+ });
406
+ const text = await res.text();
407
+ let json = null;
408
+ try { json = text ? JSON.parse(text) : null; } catch { /* handled below */ }
409
+ if (!res.ok) {
410
+ // 400/401 (or an explicit invalid_grant/revoked/reused body) means
411
+ // this refresh_token was already consumed by the CLI's single-use
412
+ // lineage. Tag it so refreshTokensWithFallback can adopt the CLI's
413
+ // newer token and retry instead of dead-ending.
414
+ const isInvalidGrant = res.status === 400 || res.status === 401
415
+ || /invalid_grant|revoked|reused/i.test(text);
416
+ throw Object.assign(
417
+ new Error(`[grok-oauth] token refresh ${res.status}: ${_scrubTokens(text).slice(0, 200)}`),
418
+ { isInvalidGrant },
419
+ );
420
+ }
421
+ const accessToken = json?.access_token;
422
+ if (!accessToken) throw new Error('[grok-oauth] token refresh returned no access token');
423
+ const refreshed = {
424
+ access_token: accessToken,
425
+ // xAI rotates refresh tokens; reuse the prior one only when the
426
+ // response omits it (RFC 6749 permits reuse).
427
+ refresh_token: json?.refresh_token || tokens.refresh_token,
428
+ expires_at: typeof json?.expires_in === 'number'
429
+ ? Date.now() + json.expires_in * 1000
430
+ : _normalizeExpiresAt(json?.expires_at),
431
+ token_endpoint: tokenEndpoint,
432
+ };
433
+ // Write the CLI store first, own store last: the own store then carries
434
+ // the newest mtime, so ensureAuth's freshest-wins resync treats our own
435
+ // refresh as authoritative and doesn't needlessly flip back to the CLI.
436
+ _writeBackGrokCliTokens(refreshed);
437
+ saveTokens(refreshed);
438
+ return { ...refreshed, source: 'own', mtimeMs: _mtimeMs(getOwnTokenPath()) };
439
+ } finally {
440
+ timeout.cleanup();
441
+ }
442
+ }
443
+
444
+ // invalid_grant means our refresh_token was already consumed/rotated elsewhere
445
+ // (the Grok CLI shares this single-use lineage). Re-read BOTH on-disk stores
446
+ // and retry once with whichever carries a different (newer) refresh_token —
447
+ // own-store still holds the dead one, so the CLI store is the likely source of
448
+ // the rotation. Mirrors anthropic-oauth's refreshOAuthCredentialsWithFallback.
449
+ async function refreshTokensWithFallback(tokens) {
450
+ try {
451
+ return await refreshTokens(tokens);
452
+ } catch (firstErr) {
453
+ if (!firstErr?.isInvalidGrant) throw firstErr;
454
+ process.stderr.write('[grok-oauth] invalid_grant — re-reading disk, retrying refresh\n');
455
+ // Prefer the freshest store first so we adopt the most recent CLI
456
+ // rotation and never replay an even older stale lineage before it.
457
+ const candidates = [_loadOwnTokens(), _loadGrokCliTokens()].filter(Boolean)
458
+ .sort((a, b) => (b.mtimeMs || 0) - (a.mtimeMs || 0));
459
+ const fresh = candidates.find(c => c.refresh_token && c.refresh_token !== tokens.refresh_token);
460
+ if (!fresh) {
461
+ throw new Error('[grok-oauth] refresh token revoked and no newer token on disk — run the Grok CLI login or the Setup login again');
462
+ }
463
+ return await refreshTokens(fresh);
464
+ }
465
+ }
466
+
467
+ // --- Model catalog cache (24h disk TTL) ---
468
+ const _modelCache = makeModelCache({ fileName: 'grok-oauth-models.json', ttlMs: MODEL_CACHE_TTL_MS });
469
+ const PROXY_MODEL_METADATA = {
470
+ 'grok-build': { display: 'Grok Build', contextWindow: 512000 },
471
+ 'grok-composer-2.5-fast': { display: 'Composer 2.5 Fast', contextWindow: 200000 },
472
+ };
473
+
474
+ function _grokModelSupportsEffort(id) {
475
+ const text = String(id || '').toLowerCase();
476
+ if (!text) return false;
477
+ if (NON_CHAT_MODEL_RE.test(text)) return false;
478
+ if (text.includes('non-reasoning')) return false;
479
+ if (text === 'grok-build' || text.startsWith('grok-build-')) return false;
480
+ if (text.startsWith('grok-composer')) return false;
481
+ return text.includes('reasoning') || /^grok-\d/.test(text);
482
+ }
483
+
484
+ function _grokApiContextWindow(model) {
485
+ const id = String(model?.id || model?.model || model || '').trim();
486
+ const native = Number(model?.context_window ?? model?.context_length ?? model?.contextWindow ?? 0);
487
+ if (Number.isFinite(native) && native > 0) return native;
488
+ const fallback = Number(PROXY_MODEL_METADATA[id]?.contextWindow || 0);
489
+ return Number.isFinite(fallback) && fallback > 0 ? fallback : 0;
490
+ }
491
+
492
+ function _displayGrokModel(model) {
493
+ const raw = String(model?.id || model?.model || model || '').trim();
494
+ if (!raw) return raw;
495
+ const displayName = String(model?.display || '').trim();
496
+ if (displayName && displayName !== raw) return displayName;
497
+ const apiName = String(model?.name || PROXY_MODEL_METADATA[raw]?.display || '').trim();
498
+ if (apiName && apiName !== raw) return apiName;
499
+ let text = raw
500
+ .replace(/^grok-/i, 'Grok ')
501
+ .replace(/-0?309\b/g, '')
502
+ .replace(/-/g, ' ')
503
+ .replace(/\b\w/g, (m) => m.toUpperCase())
504
+ .replace(/\bNon Reasoning\b/g, 'Non Reasoning')
505
+ .replace(/\bMulti Agent\b/g, 'Multi Agent');
506
+ text = text.replace(/\s+/g, ' ').trim();
507
+ return text || raw;
508
+ }
509
+
510
+ function _normalizeGrokFamily(id) {
511
+ return _grokModelSupportsEffort(id) ? 'grok' : 'grok-static';
512
+ }
513
+
514
+ function _normalizeGrokModel(m) {
515
+ const id = m?.id;
516
+ if (!id) return null;
517
+ const contextWindow = _grokApiContextWindow(m);
518
+ return {
519
+ id,
520
+ name: id,
521
+ display: _displayGrokModel(m),
522
+ provider: 'grok-oauth',
523
+ family: _normalizeGrokFamily(id),
524
+ reasoningLevels: _grokModelSupportsEffort(id) ? ['none', 'low', 'medium', 'high'] : [],
525
+ tier: 'version',
526
+ latest: false,
527
+ // API/proxy model catalogs provide context_length/context_window. Only
528
+ // proxy-only models use the tiny static fallback above.
529
+ contextWindow,
530
+ created: typeof m?.created === 'number' ? m.created : null,
531
+ };
532
+ }
533
+
534
+ function _sanitizeGrokModels(models) {
535
+ if (!Array.isArray(models)) return models;
536
+ let changed = false;
537
+ const next = models.map((m) => {
538
+ let out = m;
539
+ const display = _displayGrokModel(m);
540
+ const family = _normalizeGrokFamily(m?.id);
541
+ const reasoningLevels = _grokModelSupportsEffort(m?.id) ? ['none', 'low', 'medium', 'high'] : [];
542
+ if (display && display !== out?.display) {
543
+ changed = true;
544
+ out = { ...out, display, name: out?.name || out?.id };
545
+ }
546
+ if (family !== out?.family || JSON.stringify(reasoningLevels) !== JSON.stringify(out?.reasoningLevels || [])) {
547
+ changed = true;
548
+ out = { ...out, family, reasoningLevels };
549
+ }
550
+ const apiContextWindow = _grokApiContextWindow(out);
551
+ if (Number.isFinite(apiContextWindow) && apiContextWindow > 0 && apiContextWindow !== out?.contextWindow) {
552
+ changed = true;
553
+ out = { ...out, contextWindow: apiContextWindow };
554
+ }
555
+ const trustedContext = Number(getModelMetadataSync(m?.id, 'grok-oauth')?.contextWindow);
556
+ if (!(apiContextWindow > 0) && Number.isFinite(trustedContext) && trustedContext > 0 && trustedContext !== out?.contextWindow) {
557
+ changed = true;
558
+ return { ...out, contextWindow: trustedContext };
559
+ }
560
+ if (!(apiContextWindow > 0) && !(trustedContext > 0) && out?.contextWindow) {
561
+ changed = true;
562
+ return { ...out, contextWindow: 0 };
563
+ }
564
+ return out;
565
+ });
566
+ return changed ? next : models;
567
+ }
568
+
569
+ // Image/video generation ids — excluded from "latest chat model" resolution.
570
+ const NON_CHAT_MODEL_RE = /imagine|image|video/i;
571
+
572
+ function _markLatestGrok(models) {
573
+ let best = null;
574
+ for (const m of models) {
575
+ if (!m?.id || NON_CHAT_MODEL_RE.test(m.id) || isProxyOnlyModel(m.id)) continue;
576
+ if (!best || (Number(m.created) || 0) > (Number(best.created) || 0)) best = m;
577
+ }
578
+ if (best) best.latest = true;
579
+ }
580
+
581
+ // Newest chat model by RELEASE DATE (the catalog's `created`), read from the
582
+ // on-disk catalog cache. Deterministic — no version-string guessing (xAI's
583
+ // grok-4.20 actually predates grok-4.3 despite the higher-looking number).
584
+ // Returns null until the catalog is cached; use ensureLatestGrokModel when null.
585
+ export function resolveLatestGrokModel() {
586
+ const cached = _modelCache.loadSync();
587
+ if (!Array.isArray(cached)) return null;
588
+ let best = null;
589
+ for (const m of cached) {
590
+ if (!m?.id || NON_CHAT_MODEL_RE.test(m.id) || isProxyOnlyModel(m.id) || !(Number(m.created) > 0)) continue;
591
+ if (!best || Number(m.created) > Number(best.created)) best = m;
592
+ }
593
+ return best?.id || null;
594
+ }
595
+
596
+ export async function ensureLatestGrokModel(provider) {
597
+ let m = resolveLatestGrokModel();
598
+ if (m) return m;
599
+ await provider._refreshModelCache();
600
+ m = resolveLatestGrokModel();
601
+ if (m) return m;
602
+ throw new Error('[grok-oauth] model catalog unavailable after warmup — cannot resolve default model');
603
+ }
604
+
605
+ let _modelRefreshInFlight = null;
606
+
607
+ export class GrokOAuthProvider {
608
+ // OpenAI-compatible usage: prompt_tokens includes cached. See registry.mjs.
609
+ static inputExcludesCache = false;
610
+ name = 'grok-oauth';
611
+ config;
612
+ tokens = null;
613
+ _inner = null;
614
+ _innerKey = null;
615
+
616
+ constructor(config) {
617
+ this.config = config || {};
618
+ this.tokens = loadTokens();
619
+ // Warm a kept-alive socket to the xAI inference API so the first
620
+ // request skips the cold TLS handshake. Best-effort; never throws.
621
+ preconnect(INFERENCE_BASE_URL);
622
+ }
623
+
624
+ async ensureAuth({ forceRefresh = false } = {}) {
625
+ if (!this.tokens) this.tokens = loadTokens();
626
+ if (!this.tokens) {
627
+ throw new Error('[grok-oauth] credentials not found — run the Grok CLI login or the Setup login first');
628
+ }
629
+ // Freshest-wins resync across BOTH stores. The single-use refresh-token
630
+ // lineage is shared with the Grok CLI, so an independent CLI refresh must
631
+ // be adopted proactively — not only reactively on invalid_grant. A disk
632
+ // scan watermark guarantees termination: if the newest file isn't
633
+ // loadable (e.g. a logged-out host file beside a valid own store) we
634
+ // still record the scanned mtime so the same check can't re-fire forever.
635
+ const ownM = _mtimeMs(getOwnTokenPath());
636
+ const cliM = _mtimeMs(grokCliAuthPath());
637
+ const maxM = Math.max(ownM, cliM);
638
+ if (maxM > (this._lastDiskScan || 0) && maxM > (this.tokens.mtimeMs || 0)) {
639
+ const disk = (ownM >= cliM ? _loadOwnTokens() : _loadGrokCliTokens()) || loadTokens();
640
+ if (disk?.access_token) this.tokens = disk;
641
+ this._lastDiskScan = maxM;
642
+ }
643
+ const expiring = this.tokens.expires_at
644
+ && this.tokens.expires_at < Date.now() + TOKEN_REFRESH_SKEW_MS;
645
+ if (forceRefresh || expiring) {
646
+ if (_refreshInFlight) {
647
+ this.tokens = await _refreshInFlight;
648
+ } else {
649
+ _refreshInFlight = refreshTokensWithFallback(this.tokens)
650
+ .finally(() => { _refreshInFlight = null; });
651
+ this.tokens = await _refreshInFlight;
652
+ }
653
+ }
654
+ return this.tokens;
655
+ }
656
+
657
+ // Build (or rebuild on token change) the inner OpenAI-compatible provider
658
+ // that owns request shaping. name 'xai' selects the Responses API path the
659
+ // Grok CLI proxy speaks; baseURL + bearer are overridden for grok-build.
660
+ _ensureInner(token, model) {
661
+ // Proxy-only models (grok-composer*, grok-build) live on the grok-build
662
+ // CLI proxy: different baseURL + the Grok CLI client headers. Everything
663
+ // else stays on api.x.ai. The cache key includes the route so an
664
+ // interleaved sequence of api/proxy calls each get the right inner.
665
+ const proxy = isProxyOnlyModel(model);
666
+ const key = `${proxy ? 'proxy' : 'api'}:${token}`;
667
+ if (this._inner && this._innerKey === key) return this._inner;
668
+ this._inner = new OpenAICompatProvider('xai', {
669
+ ...this.config,
670
+ apiKey: token,
671
+ baseURL: proxy ? PROXY_BASE_URL : INFERENCE_BASE_URL,
672
+ // Default to the proven HTTP Responses transport for Grok OAuth.
673
+ // Non-proxy api.x.ai models can opt into the shared xAI WebSocket
674
+ // connector via config/env; proxy-only models stay HTTP because
675
+ // the WS connector targets api.x.ai, not the Grok CLI proxy.
676
+ responsesTransport: resolveGrokOAuthResponsesTransport(this.config, proxy),
677
+ // Proxy-only models additionally need the Grok CLI client headers to
678
+ // clear the proxy version gate (HTTP 426 otherwise).
679
+ ...(proxy ? { extraHeaders: proxyHeaders() } : {}),
680
+ });
681
+ this._innerKey = key;
682
+ return this._inner;
683
+ }
684
+
685
+ async send(messages, model, tools, sendOpts) {
686
+ const useModel = normalizeGrokModelId(
687
+ model || await ensureLatestGrokModel(this),
688
+ );
689
+ const tokens = await this.ensureAuth();
690
+ const inner = this._ensureInner(tokens.access_token, useModel);
691
+ try {
692
+ // Call _doSend directly, bypassing OpenAICompatProvider.send()'s
693
+ // own 401 handler — that one reloads a static apiKey from config,
694
+ // which is wrong for OAuth. We own the refresh-and-retry below.
695
+ // Caller's model passes through (or catalog-top default), with
696
+ // retired aliases normalized. api.x.ai exposes the full grok-4.x
697
+ // catalog to this token — no single-model lock.
698
+ return await inner._doSend(messages, useModel, tools, sendOpts);
699
+ } catch (err) {
700
+ // Refresh-and-retry only on 401 (stale/expired access token).
701
+ // Resolve the status from the structured field (falling back to the
702
+ // shared classifier that derives it from the error text) rather than
703
+ // ad-hoc string matching. A 403 is an entitlement signal (the
704
+ // account's tier lacks the model) — refreshing the same grant can't
705
+ // fix it, so it must surface unretried.
706
+ populateHttpStatusFromMessage(err);
707
+ if (Number(err?.httpStatus || err?.status) === 401) {
708
+ process.stderr.write('[grok-oauth] 401, force-refreshing token...\n');
709
+ const fresh = await this.ensureAuth({ forceRefresh: true });
710
+ const retryInner = this._ensureInner(fresh.access_token, useModel);
711
+ return await retryInner._doSend(messages, useModel, tools, sendOpts);
712
+ }
713
+ throw err;
714
+ }
715
+ }
716
+
717
+ async _fetchModelItems() {
718
+ const tokens = await this.ensureAuth();
719
+ const timeout = createTimeoutSignal(null, 10_000, 'grok-oauth model list');
720
+ try {
721
+ const res = await fetch(`${INFERENCE_BASE_URL}/models`, {
722
+ method: 'GET',
723
+ headers: { Authorization: `Bearer ${tokens.access_token}` },
724
+ // Bearer-bearing request — refuse redirects so the access token
725
+ // is never replayed to a redirect target.
726
+ redirect: 'error',
727
+ signal: timeout.signal,
728
+ dispatcher: getLlmDispatcher(),
729
+ });
730
+ if (!res.ok) throw new Error(`models ${res.status}`);
731
+ const data = await res.json();
732
+ if (!Array.isArray(data?.data)) {
733
+ throw new Error('[grok-oauth] unexpected /models response shape (no data[])');
734
+ }
735
+ return data.data;
736
+ } finally {
737
+ timeout.cleanup();
738
+ }
739
+ }
740
+
741
+ // The grok-build proxy catalog (grok-build, grok-composer-2.5-fast). /models
742
+ // is readable with the bare bearer + the Grok CLI client headers. Best-effort:
743
+ // a proxy hiccup must NOT break the api.x.ai catalog, so failures return [].
744
+ async _fetchProxyModelItems() {
745
+ let tokens;
746
+ try { tokens = await this.ensureAuth(); } catch { return []; }
747
+ const timeout = createTimeoutSignal(null, 10_000, 'grok-oauth proxy model list');
748
+ try {
749
+ const res = await fetch(`${PROXY_BASE_URL}/models`, {
750
+ method: 'GET',
751
+ headers: { Authorization: `Bearer ${tokens.access_token}`, ...proxyHeaders() },
752
+ redirect: 'error',
753
+ signal: timeout.signal,
754
+ dispatcher: getLlmDispatcher(),
755
+ });
756
+ if (!res.ok) return [];
757
+ const data = await res.json();
758
+ return Array.isArray(data?.data) ? data.data : [];
759
+ } catch {
760
+ return [];
761
+ } finally {
762
+ timeout.cleanup();
763
+ }
764
+ }
765
+
766
+ // Merge api.x.ai ∪ grok-build proxy catalogs, deduped by id (api wins on
767
+ // overlap). The proxy contributes grok-build and grok-composer-2.5-fast,
768
+ // which api.x.ai does not publish. api.x.ai failures still propagate (the
769
+ // primary catalog); proxy failures are swallowed best-effort above.
770
+ async _fetchAllModelItems() {
771
+ const [apiItems, proxyItems] = await Promise.all([
772
+ this._fetchModelItems(),
773
+ this._fetchProxyModelItems(),
774
+ ]);
775
+ const byId = new Map();
776
+ for (const m of proxyItems) if (m?.id) byId.set(m.id, m);
777
+ for (const m of apiItems) if (m?.id) byId.set(m.id, m);
778
+ return [...byId.values()];
779
+ }
780
+
781
+ async listModels() {
782
+ const cached = _modelCache.loadSync();
783
+ if (cached) {
784
+ const sanitized = _sanitizeGrokModels(cached);
785
+ if (sanitized !== cached) _modelCache.save(sanitized);
786
+ return sanitized;
787
+ }
788
+ // No swallow-to-[] fallback. Catalog/auth failures propagate to the
789
+ // caller (registry warmup + setup model listing), both of which already
790
+ // wrap this in their own catch.
791
+ const items = await this._fetchAllModelItems();
792
+ const normalized = items.map(_normalizeGrokModel).filter(Boolean);
793
+ _markLatestGrok(normalized);
794
+ const enriched = _sanitizeGrokModels(await enrichModels(normalized));
795
+ _modelCache.save(enriched);
796
+ return enriched;
797
+ }
798
+
799
+ async _refreshModelCache() {
800
+ if (_modelRefreshInFlight) return _modelRefreshInFlight;
801
+ _modelRefreshInFlight = (async () => {
802
+ try {
803
+ const items = await this._fetchAllModelItems();
804
+ const normalized = items.map(_normalizeGrokModel).filter(Boolean);
805
+ _markLatestGrok(normalized);
806
+ const enriched = _sanitizeGrokModels(await enrichModels(normalized));
807
+ _modelCache.save(enriched);
808
+ if (!process.env.MIXDOG_QUIET_PROVIDER_LOG) process.stderr.write(`[grok-oauth] catalog refreshed (${enriched.length} models)\n`);
809
+ return enriched;
810
+ } catch (err) {
811
+ if (!process.env.MIXDOG_QUIET_PROVIDER_LOG) process.stderr.write(`[grok-oauth] catalog refresh failed (${err.message})\n`);
812
+ return null;
813
+ } finally {
814
+ _modelRefreshInFlight = null;
815
+ }
816
+ })();
817
+ return _modelRefreshInFlight;
818
+ }
819
+
820
+ async isAvailable() {
821
+ return this.tokens !== null || loadTokens() !== null;
822
+ }
823
+ }
824
+
825
+ // --- Login flow (PKCE, export for CLI / setup use) ---
826
+ function generatePKCE() {
827
+ const verifier = randomBytes(32).toString('base64url');
828
+ const challenge = createHash('sha256').update(verifier).digest('base64url');
829
+ return { verifier, challenge };
830
+ }
831
+
832
+ async function exchangeAuthorizationCode({ discovery, pkce, code }) {
833
+ const cleanCode = String(code || '').trim();
834
+ if (!cleanCode) throw new Error('[grok-oauth] authorization code is required');
835
+ const tokenRes = await fetch(discovery.token_endpoint, {
836
+ method: 'POST',
837
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
838
+ body: new URLSearchParams({
839
+ grant_type: 'authorization_code',
840
+ client_id: CLIENT_ID,
841
+ code: cleanCode,
842
+ code_verifier: pkce.verifier,
843
+ redirect_uri: REDIRECT_URI,
844
+ // xAI re-validates the PKCE challenge at token exchange
845
+ // (not just the verifier), so echo it back. Omitting
846
+ // these makes the exchange fail. Matches the Grok CLI.
847
+ code_challenge: pkce.challenge,
848
+ code_challenge_method: 'S256',
849
+ }),
850
+ // Secret-bearing (authorization code + verifier): refuse
851
+ // redirects so they can't be replayed to an untrusted host.
852
+ redirect: 'error',
853
+ signal: AbortSignal.timeout(TOKEN_TIMEOUT_MS),
854
+ });
855
+ if (!tokenRes.ok) {
856
+ const text = await tokenRes.text().catch(() => '');
857
+ throw new Error(`[grok-oauth] token exchange ${tokenRes.status}: ${_scrubTokens(text).slice(0, 500)}`);
858
+ }
859
+ const json = await tokenRes.json();
860
+ if (!json.access_token || !json.refresh_token) {
861
+ throw new Error('[grok-oauth] token exchange response missing access_token or refresh_token');
862
+ }
863
+ const tokens = {
864
+ access_token: json.access_token,
865
+ refresh_token: json.refresh_token,
866
+ expires_at: typeof json.expires_in === 'number'
867
+ ? Date.now() + json.expires_in * 1000
868
+ : _normalizeExpiresAt(json.expires_at),
869
+ token_endpoint: discovery.token_endpoint,
870
+ };
871
+ saveTokens(tokens);
872
+ return tokens;
873
+ }
874
+
875
+ export async function beginOAuthLogin() {
876
+ const discovery = await fetchDiscovery();
877
+ const pkce = generatePKCE();
878
+ const state = randomBytes(16).toString('hex');
879
+ const nonce = randomBytes(16).toString('hex');
880
+ const url = new URL(discovery.authorization_endpoint);
881
+ url.searchParams.set('response_type', 'code');
882
+ url.searchParams.set('client_id', CLIENT_ID);
883
+ url.searchParams.set('redirect_uri', REDIRECT_URI);
884
+ url.searchParams.set('scope', SCOPE);
885
+ url.searchParams.set('state', state);
886
+ url.searchParams.set('nonce', nonce);
887
+ url.searchParams.set('code_challenge', pkce.challenge);
888
+ url.searchParams.set('code_challenge_method', 'S256');
889
+ url.searchParams.set('plan', 'generic');
890
+ url.searchParams.set('referrer', 'mixdog');
891
+
892
+ let server = null;
893
+ let timeout = null;
894
+ let finish = null;
895
+ const waitForCallback = new Promise((resolve, reject) => {
896
+ let settled = false;
897
+ finish = (value, error = null) => {
898
+ if (settled) return;
899
+ settled = true;
900
+ if (timeout) clearTimeout(timeout);
901
+ try { server?.close(); } catch { /* already closed */ }
902
+ if (error) reject(error);
903
+ else resolve(value);
904
+ };
905
+ server = createServer(async (req, res) => {
906
+ const u = new URL(req.url || '/', `http://${CALLBACK_HOST}:${CALLBACK_PORT}`);
907
+ if (u.pathname !== CALLBACK_PATH) {
908
+ res.writeHead(404);
909
+ res.end();
910
+ return;
911
+ }
912
+ const code = u.searchParams.get('code');
913
+ if (!code || u.searchParams.get('state') !== state) {
914
+ res.writeHead(400);
915
+ res.end('Invalid');
916
+ finish(null);
917
+ return;
918
+ }
919
+ res.writeHead(200, { 'Content-Type': 'text/html' });
920
+ res.end('<html><body><h2>Grok login successful! You can close this tab.</h2></body></html>');
921
+ try {
922
+ const tokens = await exchangeAuthorizationCode({ discovery, pkce, code });
923
+ finish(tokens);
924
+ } catch (err) {
925
+ finish(null, err instanceof Error ? err : new Error(String(err)));
926
+ }
927
+ });
928
+ timeout = setTimeout(() => finish(null), LOGIN_TIMEOUT_MS);
929
+ server.listen(CALLBACK_PORT, CALLBACK_HOST, async () => {
930
+ process.stderr.write(`\n[grok-oauth] Open this URL to log in (consent shows as "Grok Build"):\n${url.toString()}\n\n`);
931
+ try {
932
+ const { openInBrowser } = await import('../../../shared/open-url.mjs');
933
+ openInBrowser(url.toString());
934
+ } catch (err) {
935
+ process.stderr.write(`[grok-oauth] browser open failed: ${String(err?.message || err).slice(0, 200)}\n`);
936
+ }
937
+ });
938
+ server.on('error', (err) => finish(null, new Error(`[grok-oauth] callback server failed on ${CALLBACK_HOST}:${CALLBACK_PORT}: ${err?.message || err}`)));
939
+ });
940
+
941
+ return {
942
+ provider: 'grok-oauth',
943
+ url: url.toString(),
944
+ waitForCallback,
945
+ completeCode: async (code) => {
946
+ const tokens = await exchangeAuthorizationCode({ discovery, pkce, code });
947
+ finish?.(tokens);
948
+ return tokens;
949
+ },
950
+ cancel: () => {
951
+ finish?.(null);
952
+ },
953
+ };
954
+ }
955
+
956
+ export async function loginOAuth() {
957
+ const login = await beginOAuthLogin();
958
+ return await login.waitForCallback;
959
+ }