@remodex/rmx 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (588) hide show
  1. package/AGENTS_INSTALL.md +91 -0
  2. package/LICENSE +21 -0
  3. package/README.md +242 -0
  4. package/assets/architecture.png +0 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/claude-code-models.gif +0 -0
  7. package/assets/codex-app-picker.png +0 -0
  8. package/bin/ocx.mjs +584 -0
  9. package/bin/package-main.mjs +9 -0
  10. package/gui/dist/assets/index-CZqebSPQ.css +1 -0
  11. package/gui/dist/assets/index-CkETtt7P.js +71 -0
  12. package/gui/dist/favicon.png +0 -0
  13. package/gui/dist/fonts/google-sans-cyrillic.woff2 +0 -0
  14. package/gui/dist/fonts/google-sans-latin.woff2 +0 -0
  15. package/gui/dist/icons.svg +24 -0
  16. package/gui/dist/index.html +25 -0
  17. package/gui/dist/logo.png +0 -0
  18. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  19. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  20. package/gui/dist/provider-icons/claude-color.svg +1 -0
  21. package/gui/dist/provider-icons/cline-color.svg +16 -0
  22. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  23. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  24. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  25. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  26. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  27. package/gui/dist/provider-icons/discord.svg +1 -0
  28. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  29. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  30. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  31. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  32. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  33. package/gui/dist/provider-icons/grok.svg +1 -0
  34. package/gui/dist/provider-icons/groq-color.svg +1 -0
  35. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  36. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  37. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  38. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  39. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  40. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  41. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  42. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  43. package/gui/dist/provider-icons/openai.svg +1 -0
  44. package/gui/dist/provider-icons/opencode.svg +2 -0
  45. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  46. package/gui/dist/provider-icons/pi.svg +21 -0
  47. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  48. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  49. package/gui/dist/provider-icons/telegram.svg +1 -0
  50. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  51. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  52. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  53. package/package.json +118 -0
  54. package/src/AGENTS.md +28 -0
  55. package/src/adapters/anthropic-image-guard.ts +251 -0
  56. package/src/adapters/anthropic-image-normalize.ts +518 -0
  57. package/src/adapters/anthropic.ts +1205 -0
  58. package/src/adapters/azure.ts +36 -0
  59. package/src/adapters/base.ts +83 -0
  60. package/src/adapters/client-fingerprint.ts +59 -0
  61. package/src/adapters/command-code.ts +453 -0
  62. package/src/adapters/cursor/arg-codec.ts +38 -0
  63. package/src/adapters/cursor/arg-normalize.ts +104 -0
  64. package/src/adapters/cursor/cursor-errors.ts +165 -0
  65. package/src/adapters/cursor/discovery.ts +276 -0
  66. package/src/adapters/cursor/effort-map.ts +139 -0
  67. package/src/adapters/cursor/exec-policy.ts +88 -0
  68. package/src/adapters/cursor/framing.ts +250 -0
  69. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  70. package/src/adapters/cursor/kv-store.ts +52 -0
  71. package/src/adapters/cursor/live-models.ts +153 -0
  72. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  73. package/src/adapters/cursor/live-transport.ts +1235 -0
  74. package/src/adapters/cursor/mcp-config.ts +42 -0
  75. package/src/adapters/cursor/mcp-manager.ts +333 -0
  76. package/src/adapters/cursor/message-mapper.ts +49 -0
  77. package/src/adapters/cursor/native-exec-common.ts +59 -0
  78. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  79. package/src/adapters/cursor/native-exec-fs.ts +332 -0
  80. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  81. package/src/adapters/cursor/native-exec-network.ts +43 -0
  82. package/src/adapters/cursor/native-exec-shell.ts +548 -0
  83. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  84. package/src/adapters/cursor/native-exec.ts +604 -0
  85. package/src/adapters/cursor/protobuf-events.ts +735 -0
  86. package/src/adapters/cursor/protobuf-request.ts +719 -0
  87. package/src/adapters/cursor/request-builder.ts +280 -0
  88. package/src/adapters/cursor/thread-continuity.ts +67 -0
  89. package/src/adapters/cursor/tool-definitions.ts +621 -0
  90. package/src/adapters/cursor/transport-retry.ts +132 -0
  91. package/src/adapters/cursor/transport.ts +57 -0
  92. package/src/adapters/cursor/types.ts +59 -0
  93. package/src/adapters/cursor.ts +196 -0
  94. package/src/adapters/google-antigravity-replay.ts +520 -0
  95. package/src/adapters/google-antigravity-wire.ts +140 -0
  96. package/src/adapters/google-errors.ts +85 -0
  97. package/src/adapters/google-http.ts +100 -0
  98. package/src/adapters/google-tool-schema.ts +173 -0
  99. package/src/adapters/google-truncation.ts +24 -0
  100. package/src/adapters/google-wire-compiler.ts +232 -0
  101. package/src/adapters/google.ts +859 -0
  102. package/src/adapters/identity.ts +77 -0
  103. package/src/adapters/image.ts +23 -0
  104. package/src/adapters/kiro-constants.ts +16 -0
  105. package/src/adapters/kiro-errors.ts +208 -0
  106. package/src/adapters/kiro-events.ts +197 -0
  107. package/src/adapters/kiro-images.ts +129 -0
  108. package/src/adapters/kiro-retry.ts +312 -0
  109. package/src/adapters/kiro-thinking.ts +104 -0
  110. package/src/adapters/kiro-tool-fallback.ts +36 -0
  111. package/src/adapters/kiro-tools.ts +224 -0
  112. package/src/adapters/kiro-truncation.ts +33 -0
  113. package/src/adapters/kiro-wire.ts +129 -0
  114. package/src/adapters/kiro.ts +1924 -0
  115. package/src/adapters/mimo-free.ts +263 -0
  116. package/src/adapters/openai-chat.ts +1265 -0
  117. package/src/adapters/openai-responses.ts +1309 -0
  118. package/src/adapters/run-turn-queue.ts +114 -0
  119. package/src/adapters/tool-catalog-nudge.ts +71 -0
  120. package/src/adapters/upstream-http-error.ts +48 -0
  121. package/src/android-remote/assets.ts +218 -0
  122. package/src/android-remote/attachments.ts +168 -0
  123. package/src/android-remote/auth.ts +237 -0
  124. package/src/android-remote/cloudflare-provisioning.ts +409 -0
  125. package/src/android-remote/cloudflare-secret.ts +106 -0
  126. package/src/android-remote/cloudflare-tunnel.ts +488 -0
  127. package/src/android-remote/cloudflared.ts +286 -0
  128. package/src/android-remote/codex-app-server.ts +565 -0
  129. package/src/android-remote/desktop-history-page.ts +936 -0
  130. package/src/android-remote/desktop-ipc.ts +3643 -0
  131. package/src/android-remote/desktop-ownership-store.ts +98 -0
  132. package/src/android-remote/desktop-project-registration.ts +129 -0
  133. package/src/android-remote/desktop-session-stream.ts +1110 -0
  134. package/src/android-remote/desktop-workspace-state.ts +443 -0
  135. package/src/android-remote/file-change-parser.ts +112 -0
  136. package/src/android-remote/gateway.ts +9108 -0
  137. package/src/android-remote/mutation-store.ts +299 -0
  138. package/src/android-remote/projection.ts +1780 -0
  139. package/src/android-remote/queued-turn-store.ts +248 -0
  140. package/src/android-remote/session-command-recovery.ts +1384 -0
  141. package/src/android-remote/store.ts +466 -0
  142. package/src/android-remote/thread-reconciliation.ts +133 -0
  143. package/src/android-remote/thread-source-paths.ts +307 -0
  144. package/src/android-remote/thread-stream.ts +546 -0
  145. package/src/android-remote/turn-activity.ts +235 -0
  146. package/src/android-remote/user-message-identity.ts +94 -0
  147. package/src/bridge.ts +1793 -0
  148. package/src/chat/inbound.ts +295 -0
  149. package/src/chat/outbound.ts +821 -0
  150. package/src/claude/agents-inject.ts +267 -0
  151. package/src/claude/alias.ts +149 -0
  152. package/src/claude/auth-detect.ts +229 -0
  153. package/src/claude/auth-mode-migration.ts +32 -0
  154. package/src/claude/auth-mode.ts +62 -0
  155. package/src/claude/context-windows.ts +189 -0
  156. package/src/claude/desktop-3p-guard.ts +35 -0
  157. package/src/claude/desktop-3p-paths.ts +84 -0
  158. package/src/claude/desktop-3p.ts +601 -0
  159. package/src/claude/desktop-health.ts +26 -0
  160. package/src/claude/desktop-profile.ts +263 -0
  161. package/src/claude/gateway-cache.ts +70 -0
  162. package/src/claude/inbound-debug.ts +163 -0
  163. package/src/claude/inbound.ts +519 -0
  164. package/src/claude/model-info.ts +154 -0
  165. package/src/claude/outbound.ts +898 -0
  166. package/src/cli/access.ts +108 -0
  167. package/src/cli/account-api.ts +296 -0
  168. package/src/cli/account-auth.ts +250 -0
  169. package/src/cli/account-catalog-refresh.ts +14 -0
  170. package/src/cli/account-extended.ts +476 -0
  171. package/src/cli/account-main.ts +317 -0
  172. package/src/cli/account.ts +297 -0
  173. package/src/cli/agent-driven.ts +70 -0
  174. package/src/cli/agent.ts +184 -0
  175. package/src/cli/catalog-prewarm.ts +27 -0
  176. package/src/cli/claude-desktop.ts +211 -0
  177. package/src/cli/claude.ts +302 -0
  178. package/src/cli/codex-shim-autorestore.ts +45 -0
  179. package/src/cli/codex-shim-readiness.ts +69 -0
  180. package/src/cli/combo.ts +124 -0
  181. package/src/cli/config-command.ts +183 -0
  182. package/src/cli/debug.ts +228 -0
  183. package/src/cli/desktop-first-run.ts +25 -0
  184. package/src/cli/doctor.ts +1022 -0
  185. package/src/cli/export-command.ts +201 -0
  186. package/src/cli/help.ts +370 -0
  187. package/src/cli/index.ts +1565 -0
  188. package/src/cli/init.ts +224 -0
  189. package/src/cli/integrations.ts +225 -0
  190. package/src/cli/interactive-confirm.ts +133 -0
  191. package/src/cli/internal-dispatch.ts +35 -0
  192. package/src/cli/launcher-context.ts +77 -0
  193. package/src/cli/models-runtime.ts +224 -0
  194. package/src/cli/models.ts +340 -0
  195. package/src/cli/observe.ts +170 -0
  196. package/src/cli/opencode.ts +587 -0
  197. package/src/cli/provider-runtime.ts +179 -0
  198. package/src/cli/provider.ts +476 -0
  199. package/src/cli/ready.ts +301 -0
  200. package/src/cli/route-policy.ts +92 -0
  201. package/src/cli/runtime-api.ts +328 -0
  202. package/src/cli/star-prompt.ts +211 -0
  203. package/src/cli/status-oauth.ts +78 -0
  204. package/src/cli/status.ts +321 -0
  205. package/src/cli/system-command.ts +196 -0
  206. package/src/cli/system-restart-client.ts +146 -0
  207. package/src/cli/tray-proxy.ts +205 -0
  208. package/src/cli/v2.ts +200 -0
  209. package/src/cli.ts +10 -0
  210. package/src/clients/config-export.ts +1109 -0
  211. package/src/codex/account-id.ts +34 -0
  212. package/src/codex/account-label.ts +34 -0
  213. package/src/codex/account-lifecycle.ts +172 -0
  214. package/src/codex/account-namespace-match.ts +63 -0
  215. package/src/codex/account-namespaces.ts +195 -0
  216. package/src/codex/account-pause.ts +20 -0
  217. package/src/codex/account-priority.ts +83 -0
  218. package/src/codex/account-runtime-state.ts +31 -0
  219. package/src/codex/account-store.ts +517 -0
  220. package/src/codex/account-usability.ts +40 -0
  221. package/src/codex/admission.ts +263 -0
  222. package/src/codex/app-server-processes.ts +799 -0
  223. package/src/codex/auth-api.ts +2098 -0
  224. package/src/codex/auth-collision.ts +107 -0
  225. package/src/codex/auth-context.ts +480 -0
  226. package/src/codex/autostart-health.ts +156 -0
  227. package/src/codex/catalog/account-models.ts +67 -0
  228. package/src/codex/catalog/aggregation.ts +471 -0
  229. package/src/codex/catalog/bundled.ts +533 -0
  230. package/src/codex/catalog/effort.ts +432 -0
  231. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  232. package/src/codex/catalog/kinds.ts +2 -0
  233. package/src/codex/catalog/metadata.ts +287 -0
  234. package/src/codex/catalog/native-models.ts +7 -0
  235. package/src/codex/catalog/parsing.ts +503 -0
  236. package/src/codex/catalog/provider-fetch.ts +2267 -0
  237. package/src/codex/catalog/sync.ts +1606 -0
  238. package/src/codex/catalog-admission.ts +197 -0
  239. package/src/codex/catalog-refresh-status.ts +87 -0
  240. package/src/codex/catalog-write-serialization.ts +242 -0
  241. package/src/codex/catalog.ts +15 -0
  242. package/src/codex/codex-write-lock.ts +384 -0
  243. package/src/codex/convergence-types.ts +593 -0
  244. package/src/codex/convergence.ts +580 -0
  245. package/src/codex/custom-model-catalog-migration.ts +176 -0
  246. package/src/codex/data/upstream-models.json +830 -0
  247. package/src/codex/desired-state.ts +230 -0
  248. package/src/codex/desktop-client-processes.ts +521 -0
  249. package/src/codex/exec-invocation.ts +22 -0
  250. package/src/codex/features.ts +1091 -0
  251. package/src/codex/generation.ts +202 -0
  252. package/src/codex/history-job.ts +347 -0
  253. package/src/codex/history-lock.ts +242 -0
  254. package/src/codex/history-migration-guardian.ts +115 -0
  255. package/src/codex/history-provider.ts +1075 -0
  256. package/src/codex/history-transition.ts +105 -0
  257. package/src/codex/history-worker.ts +204 -0
  258. package/src/codex/home.ts +206 -0
  259. package/src/codex/inject-coordination.ts +257 -0
  260. package/src/codex/inject.ts +1857 -0
  261. package/src/codex/injected-marker.ts +79 -0
  262. package/src/codex/integration-record.ts +266 -0
  263. package/src/codex/internal/catalog-writer.ts +203 -0
  264. package/src/codex/internal/history-writer.ts +105 -0
  265. package/src/codex/journal.ts +172 -0
  266. package/src/codex/main-account-cache.ts +56 -0
  267. package/src/codex/main-account.ts +40 -0
  268. package/src/codex/management-convergence.ts +114 -0
  269. package/src/codex/model-cache.ts +267 -0
  270. package/src/codex/native-main-admission.ts +47 -0
  271. package/src/codex/native-main-auth-temp.ts +187 -0
  272. package/src/codex/native-main-claim.ts +167 -0
  273. package/src/codex/native-main-lock-file.ts +162 -0
  274. package/src/codex/native-main-owner.ts +329 -0
  275. package/src/codex/native-profile-api.ts +247 -0
  276. package/src/codex/native-profile-manager.ts +1531 -0
  277. package/src/codex/native-profile-processes.ts +121 -0
  278. package/src/codex/native-profile-recovery.ts +99 -0
  279. package/src/codex/native-profile-stage-store.ts +387 -0
  280. package/src/codex/native-profile-startup.ts +348 -0
  281. package/src/codex/native-profile-store.ts +855 -0
  282. package/src/codex/native-profile-types.ts +120 -0
  283. package/src/codex/native-residue.ts +691 -0
  284. package/src/codex/paths.ts +78 -0
  285. package/src/codex/plugins-doctor.ts +242 -0
  286. package/src/codex/pool-rotation.ts +295 -0
  287. package/src/codex/project-config-warnings.ts +426 -0
  288. package/src/codex/prompt-journal.ts +311 -0
  289. package/src/codex/prompt-layers.ts +967 -0
  290. package/src/codex/prompt-lock.ts +143 -0
  291. package/src/codex/provider-adoption.ts +242 -0
  292. package/src/codex/quota-rejection.ts +224 -0
  293. package/src/codex/quota.ts +494 -0
  294. package/src/codex/refresh.ts +60 -0
  295. package/src/codex/routing.ts +1855 -0
  296. package/src/codex/runtime.ts +659 -0
  297. package/src/codex/shim.ts +1215 -0
  298. package/src/codex/subagent-defaults.ts +557 -0
  299. package/src/codex/subagent-model-fallback.ts +560 -0
  300. package/src/codex/sync.ts +238 -0
  301. package/src/codex/transition-state.ts +612 -0
  302. package/src/codex/upstream-host-health.ts +368 -0
  303. package/src/codex/user-identity.ts +374 -0
  304. package/src/codex/warmup.ts +192 -0
  305. package/src/codex/websocket-registry.ts +100 -0
  306. package/src/codex/write-coordination.ts +114 -0
  307. package/src/combos/failover.ts +140 -0
  308. package/src/combos/index.ts +44 -0
  309. package/src/combos/request.ts +64 -0
  310. package/src/combos/resolve.ts +232 -0
  311. package/src/combos/types.ts +392 -0
  312. package/src/config.ts +3270 -0
  313. package/src/generated/model-metadata.ts +144 -0
  314. package/src/github/star-state.ts +203 -0
  315. package/src/grok/inject.ts +540 -0
  316. package/src/grok/inspect.ts +45 -0
  317. package/src/grok/status.ts +127 -0
  318. package/src/grok/sync.ts +66 -0
  319. package/src/images/artifacts.ts +516 -0
  320. package/src/images/fulfill-video.ts +163 -0
  321. package/src/images/fulfill.ts +149 -0
  322. package/src/images/index.ts +4 -0
  323. package/src/images/loop.ts +922 -0
  324. package/src/images/plan.ts +133 -0
  325. package/src/images/synthetic-tool.ts +133 -0
  326. package/src/images/types.ts +41 -0
  327. package/src/images/xai-client.ts +141 -0
  328. package/src/images/xai-video-client.ts +163 -0
  329. package/src/index.ts +22 -0
  330. package/src/integrations/config-io.ts +151 -0
  331. package/src/integrations/journal.ts +315 -0
  332. package/src/integrations/merge.ts +135 -0
  333. package/src/integrations/native/ownership-preflight.ts +202 -0
  334. package/src/integrations/ownership.ts +111 -0
  335. package/src/integrations/registry.ts +108 -0
  336. package/src/integrations/serialize.ts +235 -0
  337. package/src/integrations/state.ts +290 -0
  338. package/src/integrations/store.ts +103 -0
  339. package/src/integrations/writer.ts +492 -0
  340. package/src/lib/abort.ts +146 -0
  341. package/src/lib/admin-secrets.ts +25 -0
  342. package/src/lib/admission.ts +83 -0
  343. package/src/lib/app-owned-memory-stores.ts +173 -0
  344. package/src/lib/app-owned-memory.ts +265 -0
  345. package/src/lib/bounded-body.ts +242 -0
  346. package/src/lib/bun-binary-validator.d.mts +3 -0
  347. package/src/lib/bun-binary-validator.mjs +18 -0
  348. package/src/lib/bun-runtime.ts +184 -0
  349. package/src/lib/bun-stream-caps.ts +127 -0
  350. package/src/lib/config-ownership.ts +438 -0
  351. package/src/lib/crash-guard.ts +344 -0
  352. package/src/lib/debug-log-buffer.ts +83 -0
  353. package/src/lib/debug-settings.ts +108 -0
  354. package/src/lib/debug.ts +31 -0
  355. package/src/lib/destination-policy.ts +316 -0
  356. package/src/lib/errors.ts +364 -0
  357. package/src/lib/eventstream-decoder.ts +253 -0
  358. package/src/lib/gcp-adc.ts +341 -0
  359. package/src/lib/injection-debug-log.ts +58 -0
  360. package/src/lib/local-management-attestation.ts +51 -0
  361. package/src/lib/open-url.ts +25 -0
  362. package/src/lib/pinned-http.ts +182 -0
  363. package/src/lib/privacy.ts +20 -0
  364. package/src/lib/process-control.ts +168 -0
  365. package/src/lib/provider-environment.ts +470 -0
  366. package/src/lib/provider-outbound.ts +203 -0
  367. package/src/lib/provider-url.ts +14 -0
  368. package/src/lib/proxy-env.ts +18 -0
  369. package/src/lib/redact.ts +510 -0
  370. package/src/lib/remodex-home.ts +616 -0
  371. package/src/lib/retry-after.ts +55 -0
  372. package/src/lib/service-secrets.ts +178 -0
  373. package/src/lib/shadow-call.ts +54 -0
  374. package/src/lib/sidecar-tracker.ts +52 -0
  375. package/src/lib/sse-decoder.ts +364 -0
  376. package/src/lib/state-store-registrations.ts +109 -0
  377. package/src/lib/state-store-sweeper.ts +184 -0
  378. package/src/lib/system-restart-contract.ts +73 -0
  379. package/src/lib/test-home-guard.ts +98 -0
  380. package/src/lib/token-estimate.ts +69 -0
  381. package/src/lib/translator-budget.ts +366 -0
  382. package/src/lib/upstream-reachability.ts +91 -0
  383. package/src/lib/upstream-retry.ts +508 -0
  384. package/src/lib/win-exec.ts +115 -0
  385. package/src/lib/win-paths.ts +68 -0
  386. package/src/lib/windows-elevation.ts +705 -0
  387. package/src/lib/windows-secret-acl.ts +817 -0
  388. package/src/lib/windows-user-principal.ts +283 -0
  389. package/src/lib/winsw.ts +402 -0
  390. package/src/model-sources.ts +73 -0
  391. package/src/oauth/anthropic-routing.ts +594 -0
  392. package/src/oauth/anthropic.ts +177 -0
  393. package/src/oauth/callback-server.ts +294 -0
  394. package/src/oauth/chatgpt.ts +150 -0
  395. package/src/oauth/command-code.ts +239 -0
  396. package/src/oauth/cursor.ts +231 -0
  397. package/src/oauth/github-copilot.ts +428 -0
  398. package/src/oauth/google-antigravity.ts +230 -0
  399. package/src/oauth/health.ts +443 -0
  400. package/src/oauth/index.ts +1280 -0
  401. package/src/oauth/key-providers.ts +128 -0
  402. package/src/oauth/kimi.ts +213 -0
  403. package/src/oauth/kiro-credentials.ts +726 -0
  404. package/src/oauth/kiro.ts +621 -0
  405. package/src/oauth/local-token-detect.ts +121 -0
  406. package/src/oauth/log.ts +48 -0
  407. package/src/oauth/login-cli.ts +163 -0
  408. package/src/oauth/pkce.ts +15 -0
  409. package/src/oauth/store.ts +655 -0
  410. package/src/oauth/token-guardian.ts +309 -0
  411. package/src/oauth/types.ts +62 -0
  412. package/src/oauth/xai.ts +241 -0
  413. package/src/providers/alibaba-region-backup.ts +75 -0
  414. package/src/providers/alibaba-region-migration.ts +156 -0
  415. package/src/providers/alibaba-region-startup.ts +36 -0
  416. package/src/providers/antigravity-models.ts +317 -0
  417. package/src/providers/api-keys.ts +140 -0
  418. package/src/providers/base-url-choices.ts +64 -0
  419. package/src/providers/codex-capacity.ts +288 -0
  420. package/src/providers/command-code-efforts.ts +85 -0
  421. package/src/providers/context-cap.ts +73 -0
  422. package/src/providers/derive.ts +451 -0
  423. package/src/providers/free-directory.ts +187 -0
  424. package/src/providers/github-copilot-transport.ts +56 -0
  425. package/src/providers/google-vertex-location.ts +14 -0
  426. package/src/providers/key-failover.ts +271 -0
  427. package/src/providers/kiro-models.ts +67 -0
  428. package/src/providers/label.ts +19 -0
  429. package/src/providers/model-discovery-limits.ts +16 -0
  430. package/src/providers/model-discovery.ts +361 -0
  431. package/src/providers/openai-sidecar.ts +235 -0
  432. package/src/providers/openai-tier-startup.ts +27 -0
  433. package/src/providers/openai-tiers.ts +301 -0
  434. package/src/providers/openai-virtual-models.ts +83 -0
  435. package/src/providers/openrouter-routing.ts +102 -0
  436. package/src/providers/provider-id-rewrite.ts +179 -0
  437. package/src/providers/quota.ts +1942 -0
  438. package/src/providers/reasoning-capabilities.ts +336 -0
  439. package/src/providers/registry.ts +2375 -0
  440. package/src/providers/slug-codec.ts +74 -0
  441. package/src/providers/xai-transport.ts +149 -0
  442. package/src/reasoning-effort.ts +243 -0
  443. package/src/responses/compaction.ts +124 -0
  444. package/src/responses/hosted-tool-policy.ts +9 -0
  445. package/src/responses/parser.ts +714 -0
  446. package/src/responses/reasoning-envelope.ts +60 -0
  447. package/src/responses/reasoning-replay-cache.ts +106 -0
  448. package/src/responses/schema.ts +159 -0
  449. package/src/responses/spill-store.ts +431 -0
  450. package/src/responses/state.ts +1039 -0
  451. package/src/responses/tool-groups.ts +19 -0
  452. package/src/router.ts +802 -0
  453. package/src/routing/analytics.ts +377 -0
  454. package/src/routing/capability.ts +205 -0
  455. package/src/routing/cost.ts +77 -0
  456. package/src/routing/evaluator.ts +444 -0
  457. package/src/routing/health.ts +401 -0
  458. package/src/routing/history/cursor.ts +43 -0
  459. package/src/routing/history/indexer.ts +605 -0
  460. package/src/routing/history/schema.ts +72 -0
  461. package/src/routing/profile-namespace.ts +15 -0
  462. package/src/routing/profile.ts +424 -0
  463. package/src/routing/quota.ts +145 -0
  464. package/src/routing/request-evidence.ts +45 -0
  465. package/src/routing/trace.ts +686 -0
  466. package/src/server/adapter-resolve.ts +83 -0
  467. package/src/server/auth-cors.ts +606 -0
  468. package/src/server/chat-completions.ts +379 -0
  469. package/src/server/claude-messages.ts +980 -0
  470. package/src/server/effort-policy.ts +251 -0
  471. package/src/server/github-copilot-responses-repair.ts +338 -0
  472. package/src/server/gui-static.ts +152 -0
  473. package/src/server/image-retry.ts +42 -0
  474. package/src/server/images.ts +485 -0
  475. package/src/server/index.ts +1633 -0
  476. package/src/server/lifecycle.ts +482 -0
  477. package/src/server/live.ts +609 -0
  478. package/src/server/management/agent-settings-routes.ts +1180 -0
  479. package/src/server/management/android-remote-routes.ts +390 -0
  480. package/src/server/management/api-access.ts +141 -0
  481. package/src/server/management/api-key-usage.ts +167 -0
  482. package/src/server/management/body.ts +35 -0
  483. package/src/server/management/combo-routes.ts +244 -0
  484. package/src/server/management/config-routes.ts +602 -0
  485. package/src/server/management/context.ts +88 -0
  486. package/src/server/management/integration-routes.ts +538 -0
  487. package/src/server/management/logs-usage-routes.ts +516 -0
  488. package/src/server/management/model-routes.ts +519 -0
  489. package/src/server/management/model-rows.ts +143 -0
  490. package/src/server/management/native-integration-routes.ts +781 -0
  491. package/src/server/management/oauth-account-routes.ts +573 -0
  492. package/src/server/management/provider-routes.ts +781 -0
  493. package/src/server/management/request-history-routes.ts +191 -0
  494. package/src/server/management/routing-analytics-routes.ts +74 -0
  495. package/src/server/management/routing-profile-routes.ts +384 -0
  496. package/src/server/management/shared.ts +277 -0
  497. package/src/server/management/sidebar-routes.ts +106 -0
  498. package/src/server/management/sync-response.ts +69 -0
  499. package/src/server/management/system-restart.ts +433 -0
  500. package/src/server/management/system-routes.ts +141 -0
  501. package/src/server/management/usage-summary-cache.ts +86 -0
  502. package/src/server/management-api.ts +269 -0
  503. package/src/server/management-auth.ts +353 -0
  504. package/src/server/memory-watchdog.ts +156 -0
  505. package/src/server/port-reclaim.ts +307 -0
  506. package/src/server/ports.ts +156 -0
  507. package/src/server/proxy-liveness.ts +326 -0
  508. package/src/server/proxy-stop.ts +92 -0
  509. package/src/server/readiness.ts +99 -0
  510. package/src/server/relay-eager.ts +353 -0
  511. package/src/server/relay.ts +1179 -0
  512. package/src/server/request-decompress.ts +132 -0
  513. package/src/server/request-log-conversation.ts +168 -0
  514. package/src/server/request-log.ts +1072 -0
  515. package/src/server/responses/collaboration.ts +409 -0
  516. package/src/server/responses/compact.ts +710 -0
  517. package/src/server/responses/core.ts +3561 -0
  518. package/src/server/responses/encrypted-payload.ts +308 -0
  519. package/src/server/responses/fetch-helpers.ts +171 -0
  520. package/src/server/responses/passthrough-error.ts +78 -0
  521. package/src/server/responses/policy-fallback.ts +152 -0
  522. package/src/server/responses/terminal-guard.ts +230 -0
  523. package/src/server/responses/upstream-error.ts +48 -0
  524. package/src/server/responses-image-gen-repair.ts +132 -0
  525. package/src/server/responses-item-id-repair.ts +272 -0
  526. package/src/server/responses-json-events.ts +52 -0
  527. package/src/server/responses-model-rewrite.ts +29 -0
  528. package/src/server/responses-snapshot-repair.ts +621 -0
  529. package/src/server/responses.ts +10 -0
  530. package/src/server/search.ts +181 -0
  531. package/src/server/sse-frame-buffer.ts +292 -0
  532. package/src/server/sse-payload-rewrite.ts +263 -0
  533. package/src/server/startup-action-control.ts +308 -0
  534. package/src/server/startup-health-cache.ts +119 -0
  535. package/src/server/system-env.ts +418 -0
  536. package/src/server/windows-tcp-drop.ts +184 -0
  537. package/src/server/windows-tray-control.ts +41 -0
  538. package/src/server/ws-bridge.ts +470 -0
  539. package/src/service-manager-probe.ts +824 -0
  540. package/src/service.ts +3011 -0
  541. package/src/stall-timeout.ts +20 -0
  542. package/src/storage/cleanup-job.ts +57 -0
  543. package/src/storage/cleanup.ts +3085 -0
  544. package/src/storage/policy-job.ts +457 -0
  545. package/src/storage/policy-scheduler.ts +40 -0
  546. package/src/storage/policy-worker.ts +59 -0
  547. package/src/storage/policy.ts +527 -0
  548. package/src/storage/restore-job.ts +299 -0
  549. package/src/storage/restore-worker.ts +58 -0
  550. package/src/storage/scanner.ts +238 -0
  551. package/src/storage/storage-mutation-coordinator.ts +139 -0
  552. package/src/storage/worker-lifecycle.ts +215 -0
  553. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  554. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  555. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  556. package/src/tray/assets/opencodex-tray.png +0 -0
  557. package/src/tray/windows-tray.ps1 +364 -0
  558. package/src/tray/windows.ts +738 -0
  559. package/src/types.ts +1531 -0
  560. package/src/update/badge.ts +72 -0
  561. package/src/update/desktop-release.ts +1620 -0
  562. package/src/update/index.ts +402 -0
  563. package/src/update/job.ts +1906 -0
  564. package/src/update/notify.ts +261 -0
  565. package/src/update/npm-cache-preflight.d.mts +47 -0
  566. package/src/update/npm-cache-preflight.mjs +201 -0
  567. package/src/update/npm-invocation.d.mts +23 -0
  568. package/src/update/npm-invocation.mjs +94 -0
  569. package/src/update/tray-update-plan.d.mts +18 -0
  570. package/src/update/tray-update-plan.mjs +38 -0
  571. package/src/usage/cost.ts +0 -0
  572. package/src/usage/debug.ts +97 -0
  573. package/src/usage/expected-prices.ts +283 -0
  574. package/src/usage/log.ts +695 -0
  575. package/src/usage/summary.ts +585 -0
  576. package/src/usage/totals.ts +14 -0
  577. package/src/vision/anthropic-describe.ts +185 -0
  578. package/src/vision/describe.ts +127 -0
  579. package/src/vision/index.ts +558 -0
  580. package/src/vision/reasoning.ts +55 -0
  581. package/src/web-search/anthropic-executor.ts +189 -0
  582. package/src/web-search/executor.ts +105 -0
  583. package/src/web-search/format-result.ts +89 -0
  584. package/src/web-search/index.ts +196 -0
  585. package/src/web-search/loop.ts +791 -0
  586. package/src/web-search/parse.ts +235 -0
  587. package/src/web-search/progress-stream.ts +342 -0
  588. package/src/web-search/synthetic-tool.ts +47 -0
@@ -0,0 +1,277 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import type { CatalogModel } from "../../codex/catalog";
4
+ import { catalogModelSlug, invalidateCodexModelsCache, nativeModelRows, uniqueCatalogModelsForPublicList } from "../../codex/catalog";
5
+ import {
6
+ DEFAULT_SUBAGENT_MODELS,
7
+ codexAutoStartEnabled,
8
+ hasOwnProvider,
9
+ isValidProviderName,
10
+ multiAgentGuidanceEnabled,
11
+ providerBaseUrlConfigError,
12
+ providerHeadersConfigError,
13
+ saveConfigPreservingClaudeCode,
14
+ } from "../../config";
15
+ import {
16
+ clearLoginState,
17
+ getLoginStatus,
18
+ isPublicOAuthProvider,
19
+ listOAuthProviders,
20
+ startLoginFlow,
21
+ submitManualLoginCode,
22
+ upsertOAuthProvider,
23
+ } from "../../oauth";
24
+ import { removeCredential } from "../../oauth/store";
25
+ import { providerDestinationResolvedError } from "../../lib/destination-policy";
26
+ import { enrichProviderFromCatalog, listKeyLoginProviders } from "../../oauth/key-providers";
27
+ import { deriveProviderPresets } from "../../providers/derive";
28
+ import { providerCodexAccountMode } from "../../providers/registry";
29
+ import { routedSlug, slugEquals } from "../../providers/slug-codec";
30
+ import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../../providers/quota";
31
+ import { isCanonicalOpenAiForwardProvider } from "../../providers/openai-tiers";
32
+ import { clearThreadAccountMap } from "../../codex/routing";
33
+ import { primeCodexPoolQuotas } from "../../codex/auth-api";
34
+ import { DEFAULT_PROVIDER_CONTEXT_CAP, globalContextCapValue, providerContextCap, providerContextCaps, setAllProviderContextCaps, setGlobalContextCapValue, setProviderContextCap } from "../../providers/context-cap";
35
+ import { resolveCodexHomeDir } from "../../codex/home";
36
+ import { readUsageEntries } from "../../usage/log";
37
+ import { getUsageDebugLogEntries } from "../../usage/debug";
38
+ import { parseRange, parseUsageSurface, summarizeUsage } from "../../usage/summary";
39
+ import { stripCodexRuntimeProviderFields } from "../../codex/auth-context";
40
+ import { getProviderRegistryEntry, providerMatchesRegistryTransport } from "../../providers/registry";
41
+ import { getDebugLogEntries } from "../../lib/debug-log-buffer";
42
+ import { getInjectionDebugLogEntries } from "../../lib/injection-debug-log";
43
+ import {
44
+ clearDebugSettings,
45
+ clearDebugSetting,
46
+ getDebugSettings,
47
+ setDebugSettings,
48
+ type DebugFlag,
49
+ } from "../../lib/debug-settings";
50
+ import type { OcxClaudeCodeConfig, OcxClaudeDesktopProfile, OcxConfig, OcxCustomModel, OcxProviderConfig } from "../../types";
51
+ import type { DesktopProfileModel } from "../../claude/desktop-profile";
52
+ import { drainAndShutdown } from "../lifecycle";
53
+ import { filterRequestLogs, getRequestLogEntries, type RequestLogEntry } from "../request-log";
54
+ import { estimateComboCost, estimateRequestCost, serviceTierContext, normalizeCostTokens, tokensPerSecond } from "../../usage/cost";
55
+ import type { PersistedUsageAttempt } from "../../usage/log";
56
+ import { isAllowedRequestOrigin, jsonResponse, providerManagementConfigError, publicProviderBaseUrl, safeConfigDTO } from "../auth-cors";
57
+ import { applySystemEnvToggle } from "../system-env";
58
+
59
+
60
+ export function isPlainRecord(v: unknown): v is Record<string, unknown> {
61
+ return typeof v === "object" && v !== null && !Array.isArray(v);
62
+ }
63
+
64
+ export function parseDebugLogQuery(url: URL): { after: number; limit: number } {
65
+ const after = Number(url.searchParams.get("after") ?? url.searchParams.get("since") ?? "0");
66
+ const limit = Number(url.searchParams.get("limit") ?? "500");
67
+ return {
68
+ after: Number.isFinite(after) && after > 0 ? after : 0,
69
+ limit: Number.isFinite(limit) && limit > 0 ? Math.min(limit, 2000) : 500,
70
+ };
71
+ }
72
+
73
+ // ---- /api/logs display metrics (devlog/_plan/260720_toks_speed_price_columns/020) ----
74
+ // Derived at response time only; NEVER persisted to the request log or usage.jsonl.
75
+
76
+ export type MetricUnavailableReason =
77
+ | "usage_missing" | "usage_unsupported" | "output_missing" | "invalid_duration"
78
+ | "price_unmatched" | "invalid_cache_breakdown"
79
+ | "invalid_usage" | "combo_attempt_unavailable";
80
+
81
+ export type TokPerSecondResult =
82
+ | { kind: "value"; value: number; estimated: boolean }
83
+ | { kind: "unavailable"; reason: MetricUnavailableReason };
84
+
85
+ export type CostEstimateReason = "usage_estimated" | "cache_detail_missing" | "expected_price_overlay";
86
+
87
+ export type CostResult =
88
+ | { kind: "value"; estimate: NonNullable<ReturnType<typeof estimateRequestCost>>; estimateReasons: CostEstimateReason[] }
89
+ | { kind: "unavailable"; reason: MetricUnavailableReason };
90
+
91
+ export type MetricSource = Pick<RequestLogEntry, "provider" | "model" | "durationMs" | "usageStatus" | "usage" | "requestedServiceTier" | "configuredServiceTier" | "responseServiceTier"> & {
92
+ attempts?: readonly PersistedUsageAttempt[];
93
+ };
94
+
95
+ export function tokPerSecondResult(entry: Pick<MetricSource, "durationMs" | "usageStatus" | "usage">): TokPerSecondResult {
96
+ if (!entry.usage) return { kind: "unavailable", reason: "usage_missing" };
97
+ if (entry.usageStatus === "unsupported") return { kind: "unavailable", reason: "usage_unsupported" };
98
+ const value = tokensPerSecond(entry.usage.outputTokens, entry.durationMs);
99
+ if (value === null) {
100
+ return {
101
+ kind: "unavailable",
102
+ reason: entry.usage.outputTokens <= 0 ? "output_missing" : "invalid_duration",
103
+ };
104
+ }
105
+ return { kind: "value", value, estimated: entry.usageStatus === "estimated" || entry.usage.estimated === true };
106
+ }
107
+
108
+ export function unavailableCostReason(entry: MetricSource): MetricUnavailableReason {
109
+ // Normalizer-first classification: the landed normalizer recovers legacy
110
+ // cachedInputTokens=read+write rows via retry, so a raw read+write>input
111
+ // pre-check would misclassify recoverable rows (020 audit blocker #2).
112
+ if (!entry.usage && !entry.attempts?.length) return "usage_missing";
113
+ if (entry.usageStatus === "unsupported") return "usage_unsupported";
114
+ if (entry.attempts?.length) return "combo_attempt_unavailable";
115
+ if (!entry.usage) return "usage_missing";
116
+ if (!normalizeCostTokens(entry.usage)) {
117
+ const effectiveRead = entry.usage.cacheReadInputTokens ?? entry.usage.cachedInputTokens ?? 0;
118
+ const effectiveWrite = entry.usage.cacheCreationInputTokens ?? 0;
119
+ const finite = [entry.usage.inputTokens, entry.usage.outputTokens, effectiveRead, effectiveWrite]
120
+ .every(v => Number.isFinite(v) && v >= 0);
121
+ return finite ? "invalid_cache_breakdown" : "invalid_usage";
122
+ }
123
+ return "price_unmatched";
124
+ }
125
+
126
+ export function costResult(entry: MetricSource): CostResult {
127
+ const tier = serviceTierContext(entry);
128
+ const estimate = entry.attempts?.length
129
+ ? estimateComboCost(entry.attempts, undefined, tier)
130
+ : estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
131
+ if (!estimate) return { kind: "unavailable", reason: unavailableCostReason(entry) };
132
+ const estimateReasons = [
133
+ entry.usageStatus === "estimated" || entry.usage?.estimated ? "usage_estimated" as const : undefined,
134
+ entry.usage && entry.usage.cachedInputTokens === undefined
135
+ && entry.usage.cacheReadInputTokens === undefined
136
+ && entry.usage.cacheCreationInputTokens === undefined ? "cache_detail_missing" as const : undefined,
137
+ estimate.price?.source === "expected" || estimate.attempts?.some(a => a.price.source === "expected")
138
+ ? "expected_price_overlay" as const : undefined,
139
+ ].filter((reason): reason is CostEstimateReason => reason !== undefined);
140
+ return { kind: "value", estimate, estimateReasons };
141
+ }
142
+
143
+ export function requestLogDto(entry: RequestLogEntry): Record<string, unknown> {
144
+ return {
145
+ ...entry,
146
+ displayMetrics: {
147
+ tokPerSecond: tokPerSecondResult(entry),
148
+ cost: costResult(entry),
149
+ },
150
+ ...(entry.attempts?.length
151
+ ? {
152
+ attempts: entry.attempts.map(attempt => ({
153
+ ...attempt,
154
+ displayMetrics: {
155
+ tokPerSecond: tokPerSecondResult(attempt),
156
+ cost: costResult({ ...attempt, attempts: undefined, requestedServiceTier: entry.requestedServiceTier, configuredServiceTier: entry.configuredServiceTier, responseServiceTier: entry.responseServiceTier }),
157
+ },
158
+ })),
159
+ }
160
+ : {}),
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Live routed-provider models for the proxy's /api/* and /v1/models endpoints. Delegates to the
166
+ * canonical, TTL-cached `gatherRoutedModels` (single source of truth) — so the GUI/codex endpoints
167
+ * share the same fetch, the same per-provider cache (dedups Codex's frequent /v1/models polling),
168
+ * and the same stale fallback when a provider blips, instead of a parallel uncached copy.
169
+ */
170
+ export async function fetchAllModels(config: OcxConfig): Promise<CatalogModel[]> {
171
+ const { gatherRoutedModels } = await import("../../codex/catalog");
172
+ return gatherRoutedModels(config);
173
+ }
174
+
175
+ export interface GrokCandidateModel {
176
+ id: string;
177
+ contextWindow?: number;
178
+ native: boolean;
179
+ }
180
+
181
+ /**
182
+ * The model list `syncGrokConfig` would inject, BEFORE the user's exclusions. The Grok
183
+ * page needs this to show a switch for a model the user has already excluded — such a
184
+ * model is absent from the fence, so readGrokStatus alone could never list it. Built
185
+ * from the same two sources as the sync so the two can never disagree.
186
+ */
187
+ export async function fetchGrokCandidateModels(config: OcxConfig): Promise<GrokCandidateModel[]> {
188
+ const { filterCatalogVisibleModels, nativeOpenAiContextWindow, visibleNativeSlugs } = await import("../../codex/catalog");
189
+ const routed = filterCatalogVisibleModels(await fetchAllModels(config), config);
190
+ return [
191
+ ...visibleNativeSlugs(config).map(id => {
192
+ const contextWindow = nativeOpenAiContextWindow(id);
193
+ return { id, native: true, ...(contextWindow !== undefined ? { contextWindow } : {}) };
194
+ }),
195
+ ...routed.map(m => ({
196
+ id: m.alias ?? `${m.provider}/${m.id}`,
197
+ native: false,
198
+ ...(m.contextWindow !== undefined ? { contextWindow: m.contextWindow } : {}),
199
+ })),
200
+ ];
201
+ }
202
+
203
+ export function stripRegistryOnlyStaticHeaders(name: string, provider: OcxProviderConfig): OcxProviderConfig {
204
+ const entry = providerMatchesRegistryTransport(name, provider) ? getProviderRegistryEntry(name) : undefined;
205
+ if (!entry?.staticHeaders || !provider.headers) return provider;
206
+ const headerEntries = Object.entries(provider.headers);
207
+ const staticEntries = Object.entries(entry.staticHeaders);
208
+ if (headerEntries.length !== staticEntries.length) return provider;
209
+ const matchesRegistryStaticHeaders = staticEntries.every(([key, value]) => provider.headers?.[key] === value);
210
+ if (!matchesRegistryStaticHeaders) return provider;
211
+ const { headers: _headers, ...rest } = provider;
212
+ return rest;
213
+ }
214
+
215
+ /** Shared Desktop profile DTO builder for the management API and CLI. */
216
+ export async function buildClaudeDesktopState(config: OcxConfig, stored?: OcxClaudeDesktopProfile) {
217
+ const { filterCatalogVisibleModels, nativeOpenAiContextWindow, desktopVisibleNativeSlugs } = await import("../../codex/catalog");
218
+ const { DESKTOP_SUPPORTS_1M_THRESHOLD } = await import("../../claude/desktop-3p");
219
+ const { reconcileDesktopProfile, renderDesktopProfile } = await import("../../claude/desktop-profile");
220
+ const routed = filterCatalogVisibleModels(await fetchAllModels(config), config);
221
+ const profileModels: DesktopProfileModel[] = [
222
+ // Native rows carry their real context window from the same accessor the Grok sync
223
+ // uses — otherwise Sol's 372k and gpt-5.5's 272k render as blank on Desktop.
224
+ ...desktopVisibleNativeSlugs(config).map(id => {
225
+ const contextWindow = nativeOpenAiContextWindow(id);
226
+ return { route: `native/${id}`, label: `${id} (native)`,
227
+ ...(contextWindow !== undefined ? { contextWindow } : {}) };
228
+ }),
229
+ ...routed.map(model => ({
230
+ route: `${model.provider}/${model.id}`,
231
+ label: `${model.id} (${model.provider})`,
232
+ ...(typeof model.contextWindow === "number" ? { contextWindow: model.contextWindow } : {}),
233
+ })),
234
+ ];
235
+ const profile = reconcileDesktopProfile(stored ?? config.claudeCode?.desktopProfile, profileModels);
236
+ if (config.claudeCode?.desktopNativeModels === false) {
237
+ for (const route of Object.keys(profile.assignments)) {
238
+ if (route.startsWith("native/")) delete profile.assignments[route];
239
+ }
240
+ for (const family of ["opus", "fable", "sonnet", "haiku"] as const) {
241
+ const current = profile.defaults[family];
242
+ if (current?.startsWith("native/")) {
243
+ profile.defaults[family] = Object.keys(profile.assignments)
244
+ .filter(route => profile.assignments[route]?.family === family)
245
+ .sort()[0] ?? null;
246
+ }
247
+ }
248
+ }
249
+ const available = new Set(profileModels.map(model => model.route));
250
+ const modelByRoute = new Map(profileModels.map(model => [model.route, model]));
251
+ // Effort support: routed models with a non-empty reasoningEfforts ladder support effort;
252
+ // native models always support it (Anthropic native effort).
253
+ const effortByRoute = new Map<string, boolean>();
254
+ for (const m of routed) {
255
+ effortByRoute.set(`${m.provider}/${m.id}`, Array.isArray(m.reasoningEfforts) && m.reasoningEfforts.length > 0);
256
+ }
257
+ for (const id of desktopVisibleNativeSlugs(config)) {
258
+ effortByRoute.set(`native/${id}`, true);
259
+ }
260
+ const models = Object.keys(profile.assignments).sort().map(route => ({
261
+ route,
262
+ label: modelByRoute.get(route)?.label ?? route,
263
+ available: available.has(route),
264
+ ...(modelByRoute.get(route)?.contextWindow ? { contextWindow: modelByRoute.get(route)!.contextWindow } : {}),
265
+ effortSupported: effortByRoute.get(route) ?? false,
266
+ // Read-only view of the 1M capability the written Desktop config already emits,
267
+ // derived from the SAME threshold so the dashboard chip can never disagree.
268
+ supports1m: (modelByRoute.get(route)?.contextWindow ?? 0) >= DESKTOP_SUPPORTS_1M_THRESHOLD,
269
+ assignment: profile.assignments[route]!,
270
+ }));
271
+ return {
272
+ profile,
273
+ models,
274
+ rendered: renderDesktopProfile(profile, profileModels),
275
+ port: config.port,
276
+ };
277
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * /api/github/star and /api/update/badge — the two cheap polls behind the
3
+ * sidebar's GitHub star and update controls.
4
+ *
5
+ * Both ride the standard management gate (auth + origin check happen before
6
+ * dispatch), and both are scalar-only: a star state enum, a repo slug, version
7
+ * strings, and a fixed error code. No GitHub token, account login, or raw `gh`/npm
8
+ * output is ever serialized here — starring runs through the user's own `gh` CLI and
9
+ * this surface only learns the yes/no answer. `gh` writes the authenticated account
10
+ * name to stderr, so that output is discarded at the source rather than forwarded.
11
+ *
12
+ * The star POST additionally requires a dashboard session. Management auth proves
13
+ * the caller reached the admin token, not that a person chose to star: a coding
14
+ * agent runs on the user's machine and can read that token from disk, so the CLI's
15
+ * "ask the user" deferral would be bypassable with one `curl` here.
16
+ *
17
+ * The requirement is unconditional, and that is the point. It used to apply only
18
+ * when `isAgentDriven()` was true — but that function reads the SERVER's
19
+ * environment, not the caller's, so a proxy already running as a service (no agent
20
+ * markers, the normal remote setup) accepted a raw-token star from anyone who could
21
+ * read the token, which includes every agent on the machine. The provenance of the
22
+ * HTTP caller is not knowable from the server's env; only the credential is. So the
23
+ * mutation asks for a GUI session this process minted for a browser, which the auth
24
+ * gate accepts only after matching origin and the per-session CSRF token.
25
+ */
26
+ import { jsonResponse } from "../auth-cors";
27
+ import { agentDrivenMarkers } from "../../cli/agent-driven";
28
+ import type { ManagementContext } from "./context";
29
+
30
+ /**
31
+ * True only when a minted GUI session authorized this request.
32
+ *
33
+ * The previous version of this check looked for an `Origin` plus the CSRF headers
34
+ * and reasoned that the auth gate had already validated them. It had not: the gate
35
+ * accepts a raw admin token BEFORE it ever consults the session table, so a caller
36
+ * holding that token (any process running as the user, a coding agent included)
37
+ * could add three nonempty headers of its choosing and satisfy this check without
38
+ * a browser ever being involved. The credential itself is the only part of the
39
+ * request an agent cannot fabricate, so that is what this now reads.
40
+ */
41
+ function hasBrowserSessionEvidence(ctx: ManagementContext): boolean {
42
+ return ctx.principal === "gui-session";
43
+ }
44
+
45
+ // Known edge, deliberately fail-closed: a non-loopback operator dashboard that signs
46
+ // in with the raw admin token instead of a minted GUI session gets its click refused,
47
+ // and the response names the one-line `gh` command to run by hand. That is the
48
+ // correct trade — an endpoint reachable with a readable token cannot establish that
49
+ // a human chose to spend their own GitHub identity.
50
+ //
51
+ // The honest limit of this guard: a local process running AS THE USER can mint its
52
+ // own GUI session (the dashboard bootstrap is served to any loopback GET) and can
53
+ // equally just run `gh api -X PUT /user/starred/...` itself, which needs no proxy at
54
+ // all. No check inside this process can distinguish that caller from the browser,
55
+ // because both hold every local credential. So this endpoint is not a technical
56
+ // barrier against a determined local agent — it removes the CASUAL path (an agent
57
+ // that would have POSTed here because the endpoint existed) and makes the refusal
58
+ // legible. The actual boundary is normative and lives in AGENTS.md: an agent must
59
+ // not spend the user's identity, whichever mechanism is at hand.
60
+
61
+ export async function handleSidebarRoutes(ctx: ManagementContext): Promise<Response | null> {
62
+ const { req, url } = ctx;
63
+
64
+ if (url.pathname === "/api/github/star" && req.method === "GET") {
65
+ const { getStarStatus } = await import("../../github/star-state");
66
+ return jsonResponse(await getStarStatus());
67
+ }
68
+
69
+ if (url.pathname === "/api/github/star" && req.method === "POST") {
70
+ const { STAR_REPO, STAR_REPO_URL, starRepository } = await import("../../github/star-state");
71
+ // Starring uses the user's GitHub identity, so consent must come from the
72
+ // account owner. Only a minted dashboard session evidences that; a caller
73
+ // holding the admin token must relay the question instead of answering it
74
+ // with an HTTP call.
75
+ if (!hasBrowserSessionEvidence(ctx)) {
76
+ const markers = agentDrivenMarkers().slice(0, 3);
77
+ return jsonResponse({
78
+ ok: false,
79
+ state: "not-starred",
80
+ repo: STAR_REPO,
81
+ url: STAR_REPO_URL,
82
+ code: "agent_consent_required",
83
+ message:
84
+ `Refused: this request carries no dashboard session`
85
+ + `${markers.length ? ` (agent session detected: ${markers.join(", ")})` : ""}. `
86
+ + `Starring writes to the user's own GitHub account, so ask the user `
87
+ + `directly as a required Yes/No choice — not a soft aside, and no answer is not a No, so re-ask `
88
+ + `it unchanged while it is open — and only if they say yes run: `
89
+ + `gh api -X PUT /user/starred/${STAR_REPO}`,
90
+ }, 403);
91
+ }
92
+ const result = await starRepository();
93
+ return jsonResponse({
94
+ ...result.status,
95
+ ok: result.ok,
96
+ ...(result.code ? { code: result.code } : {}),
97
+ });
98
+ }
99
+
100
+ if (url.pathname === "/api/update/badge" && req.method === "GET") {
101
+ const { readUpdateBadge } = await import("../../update/badge");
102
+ return jsonResponse(readUpdateBadge());
103
+ }
104
+
105
+ return null;
106
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The single HTTP projection of ConvergeOutcome.
3
+ *
4
+ * Three phase documents once mapped /api/sync independently and one silently
5
+ * dropped Retry-After. Keeping the exhaustive switch here makes a new domain
6
+ * outcome a compile error until its management contract is chosen explicitly.
7
+ */
8
+ import type { ConvergeOutcome } from "../../codex/convergence-types";
9
+ import { jsonResponse } from "../auth-cors";
10
+
11
+ export function toSyncResponse(outcome: ConvergeOutcome): Response {
12
+ switch (outcome.kind) {
13
+ case "catalog-only":
14
+ return jsonResponse({
15
+ ok: true,
16
+ changed: outcome.changed,
17
+ observed: outcome.observed,
18
+ catalogRefresh: outcome.catalogRefresh,
19
+ history: outcome.history,
20
+ });
21
+ case "converged":
22
+ return jsonResponse({
23
+ ok: true,
24
+ changed: outcome.changed,
25
+ observed: outcome.observed,
26
+ catalogRefresh: outcome.catalogRefresh,
27
+ history: outcome.history,
28
+ });
29
+ case "skipped":
30
+ return jsonResponse({
31
+ ok: true,
32
+ changed: false,
33
+ observed: outcome.observed,
34
+ catalogRefresh: outcome.catalogRefresh,
35
+ history: outcome.history,
36
+ });
37
+ case "refused":
38
+ return jsonResponse({
39
+ ok: false,
40
+ authority: outcome.authority,
41
+ message: outcome.message,
42
+ observed: outcome.observed,
43
+ }, 409);
44
+ case "busy": {
45
+ const response = jsonResponse({
46
+ ok: false,
47
+ surface: outcome.surface,
48
+ retryAfterMs: outcome.retryAfterMs,
49
+ }, 503);
50
+ response.headers.set("Retry-After", String(Math.ceil(outcome.retryAfterMs / 1_000)));
51
+ return response;
52
+ }
53
+ case "deferred":
54
+ return jsonResponse({
55
+ ok: true,
56
+ changed: outcome.changed,
57
+ unresolved: outcome.unresolved,
58
+ observed: outcome.observed,
59
+ catalogRefresh: outcome.catalogRefresh,
60
+ history: outcome.history,
61
+ });
62
+ case "failed":
63
+ return jsonResponse({ error: outcome.message, surface: outcome.surface }, 500);
64
+ default: {
65
+ const exhaustive: never = outcome;
66
+ return exhaustive;
67
+ }
68
+ }
69
+ }