@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,79 @@
1
+ /**
2
+ * Ownership predicates for `~/.codex/config.toml`: does Remodex own the routing
3
+ * currently written there?
4
+ *
5
+ * These live in their own leaf module rather than in `inject.ts` because
6
+ * `journal.ts` needs them and `inject.ts` already imports `journal.ts`. Keeping
7
+ * them here breaks that cycle. `inject.ts` imports them back and re-exports the
8
+ * two public predicates, so external callers see no change.
9
+ */
10
+ /** Current marker written into Codex configuration. */
11
+ export const OCX_SECTION_MARKER = "# Auto-injected by Remodex";
12
+ /** Marker emitted by releases before the product rename; retained for upgrade/restore. */
13
+ export const LEGACY_OCX_SECTION_MARKER = "# Auto-injected by opencodex";
14
+
15
+ export function isOcxSectionMarker(line: string): boolean {
16
+ return line.includes(OCX_SECTION_MARKER) || line.includes(LEGACY_OCX_SECTION_MARKER);
17
+ }
18
+
19
+ export function isRootOpenaiBaseUrlLine(line: string): boolean {
20
+ return /^\s*openai_base_url\s*=/.test(line);
21
+ }
22
+
23
+ export function tomlStringPattern(key: string): RegExp {
24
+ const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
25
+ const keyToken = `(?:${escaped}|"${escaped}"|'${escaped}')`;
26
+ return new RegExp(`^\\s*${keyToken}\\s*=\\s*["']([^"']+)["']\\s*(?:#.*)?$`);
27
+ }
28
+
29
+ export function rootTomlString(content: string, key: string): string | null {
30
+ const lines = content.split("\n");
31
+ const firstTable = lines.findIndex(line => /^\s*\[/.test(line));
32
+ const rootLines = lines.slice(0, firstTable === -1 ? lines.length : firstTable);
33
+ const pattern = tomlStringPattern(key);
34
+ for (const line of rootLines) {
35
+ const match = pattern.exec(line);
36
+ if (match?.[1]) return match[1].trim();
37
+ }
38
+ return null;
39
+ }
40
+
41
+ export function providerTableStart(lines: string[], provider: string): number {
42
+ const escapedProvider = provider.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
43
+ const providerToken = `(?:${escapedProvider}|"${escapedProvider}"|'${escapedProvider}')`;
44
+ const header = new RegExp(`^\\s*\\[\\s*(?:model_providers|"model_providers"|'model_providers')\\s*\\.\\s*${providerToken}\\s*\\]\\s*(?:#.*)?$`);
45
+ return lines.findIndex(line => header.test(line));
46
+ }
47
+
48
+ export function providerTableString(content: string, provider: string, key: string): string | null {
49
+ const lines = content.split("\n");
50
+ const start = providerTableStart(lines, provider);
51
+ if (start === -1) return null;
52
+ const pattern = tomlStringPattern(key);
53
+ for (let index = start + 1; index < lines.length && !/^\s*\[/.test(lines[index]); index += 1) {
54
+ const match = pattern.exec(lines[index]);
55
+ if (match?.[1]) return match[1].trim();
56
+ }
57
+ return null;
58
+ }
59
+
60
+ export function hasInjectedOpenaiBaseUrl(content: string): boolean {
61
+ const lines = content.split("\n");
62
+ const firstTable = lines.findIndex(l => /^\s*\[/.test(l));
63
+ const rootEnd = firstTable === -1 ? lines.length : firstTable;
64
+ for (let i = 1; i < rootEnd; i++) {
65
+ if (isRootOpenaiBaseUrlLine(lines[i]!) && isOcxSectionMarker(lines[i - 1]!)) return true;
66
+ }
67
+ return false;
68
+ }
69
+
70
+ /**
71
+ * True when the active Codex config is owned by Remodex routing. Covers the
72
+ * loopback Design B root override and the legacy/non-loopback provider table.
73
+ * A user-owned `openai_base_url` is intentionally not classified as injected.
74
+ */
75
+ export function hasInjectedCodexRouting(content: string): boolean {
76
+ if (hasInjectedOpenaiBaseUrl(content)) return true;
77
+ return rootTomlString(content, "model_provider") === "opencodex"
78
+ && providerTableString(content, "opencodex", "base_url") !== null;
79
+ }
@@ -0,0 +1,266 @@
1
+ /**
2
+ * The sole reader/writer for integrations/codex.json.
3
+ *
4
+ * Provenance once disappeared when a corrupt record was treated as an empty one
5
+ * (005_disable_leaves_a_broken_file.md). Reads therefore validate the complete
6
+ * known shape, and updates refuse malformed bytes instead of manufacturing a new
7
+ * baseline over evidence we can no longer trust.
8
+ */
9
+ import { mkdirSync, readFileSync } from "node:fs";
10
+ import { dirname, join } from "node:path";
11
+ import { atomicWriteFile, getConfigDir, withConfigMutationLockSync } from "../config";
12
+ import type {
13
+ CodexArtifactId,
14
+ CodexIntegrationRecord,
15
+ CodexProvenanceEntry,
16
+ CodexProvenanceLedger,
17
+ } from "./convergence-types";
18
+
19
+ const RECORD_FILENAME = "codex.json";
20
+ const LEGACY_TRANSITION_KEYS = new Set([
21
+ "nativeGeneration",
22
+ "currentTxId",
23
+ "generation",
24
+ "history",
25
+ "historySchedule",
26
+ ]);
27
+
28
+ function recordPath(): string {
29
+ return join(getConfigDir(), "integrations", RECORD_FILENAME);
30
+ }
31
+
32
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
33
+ return typeof value === "object" && value !== null && !Array.isArray(value);
34
+ }
35
+
36
+ function isMissingPathError(error: unknown): boolean {
37
+ return error instanceof Error && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT";
38
+ }
39
+
40
+ function invalid(message: string) {
41
+ return { kind: "invalid" as const, message };
42
+ }
43
+
44
+ function validateArtifact(value: unknown): value is CodexArtifactId {
45
+ if (!isPlainRecord(value) || typeof value.kind !== "string") return false;
46
+ switch (value.kind) {
47
+ case "config":
48
+ case "generated-profile":
49
+ case "models-cache":
50
+ case "injection-journal":
51
+ return true;
52
+ case "active-catalog":
53
+ case "history-manifest":
54
+ case "history-rollout":
55
+ return typeof value.canonicalPath === "string"
56
+ && (value.kind === "active-catalog" || typeof value.stateDbId === "string");
57
+ case "catalog-backup":
58
+ return (value.form === "hashed" || value.form === "legacy")
59
+ && typeof value.canonicalPath === "string";
60
+ case "history-row":
61
+ case "history-manifest-entry":
62
+ return typeof value.stateDbId === "string" && typeof value.threadId === "string";
63
+ default:
64
+ return false;
65
+ }
66
+ }
67
+
68
+ function validateBaseline(value: unknown): boolean {
69
+ if (!isPlainRecord(value)) return false;
70
+ if (value.kind === "absent") return true;
71
+ return value.kind === "present"
72
+ && typeof value.sha256 === "string"
73
+ && typeof value.bytesBase64 === "string";
74
+ }
75
+
76
+ function validateEntry(value: unknown): value is CodexProvenanceEntry {
77
+ return isPlainRecord(value)
78
+ && validateArtifact(value.artifact)
79
+ && validateBaseline(value.baseline)
80
+ && (typeof value.postImage === "string" || value.postImage === null)
81
+ && typeof value.txId === "string"
82
+ && typeof value.at === "string";
83
+ }
84
+
85
+ function validateLedger(value: unknown): value is CodexProvenanceLedger {
86
+ return isPlainRecord(value)
87
+ && Array.isArray(value.entries)
88
+ && value.entries.every(validateEntry);
89
+ }
90
+
91
+ function validateRecord(value: unknown): value is CodexIntegrationRecord {
92
+ return isPlainRecord(value)
93
+ && value.version === 1
94
+ && !Object.keys(value).some(key => LEGACY_TRANSITION_KEYS.has(key))
95
+ && (value.provenance === undefined || validateLedger(value.provenance));
96
+ }
97
+
98
+ function readIntegrationRecordUnlocked() {
99
+ let raw: string;
100
+ try {
101
+ raw = readFileSync(recordPath(), "utf8");
102
+ } catch (error) {
103
+ if (isMissingPathError(error)) return { kind: "missing" as const, record: null };
104
+ return invalid(`Codex integration record is unreadable: ${error instanceof Error ? error.message : String(error)}`);
105
+ }
106
+
107
+ let parsed: unknown;
108
+ try {
109
+ parsed = JSON.parse(raw.replace(/^\uFEFF/, ""));
110
+ } catch {
111
+ return invalid("Codex integration record contains invalid JSON");
112
+ }
113
+ if (!validateRecord(parsed)) {
114
+ return invalid("Codex integration record has an unsupported or malformed v1 shape");
115
+ }
116
+ return { kind: "ready" as const, record: parsed };
117
+ }
118
+
119
+ export const readIntegrationRecord = readIntegrationRecordUnlocked;
120
+
121
+ function copyUnknown(
122
+ previous: Record<string, unknown>,
123
+ next: Record<string, unknown>,
124
+ knownKeys: ReadonlySet<string>,
125
+ ): Record<string, unknown> {
126
+ const merged: Record<string, unknown> = {};
127
+ for (const [key, value] of Object.entries(previous)) {
128
+ if (!knownKeys.has(key)) merged[key] = value;
129
+ }
130
+ return { ...merged, ...next };
131
+ }
132
+
133
+ function artifactKnownKeys(artifact: CodexArtifactId): ReadonlySet<string> {
134
+ switch (artifact.kind) {
135
+ case "config":
136
+ case "generated-profile":
137
+ case "models-cache":
138
+ case "injection-journal":
139
+ return new Set(["kind"]);
140
+ case "active-catalog":
141
+ return new Set(["kind", "canonicalPath"]);
142
+ case "catalog-backup":
143
+ return new Set(["kind", "form", "canonicalPath"]);
144
+ case "history-row":
145
+ case "history-manifest-entry":
146
+ return new Set(["kind", "stateDbId", "threadId"]);
147
+ case "history-manifest":
148
+ case "history-rollout":
149
+ return new Set(["kind", "stateDbId", "canonicalPath"]);
150
+ }
151
+ }
152
+
153
+ function mergeArtifact(previous: CodexArtifactId, next: CodexArtifactId): CodexArtifactId {
154
+ return copyUnknown(
155
+ previous as CodexArtifactId & Record<string, unknown>,
156
+ next as CodexArtifactId & Record<string, unknown>,
157
+ artifactKnownKeys(previous),
158
+ ) as CodexArtifactId;
159
+ }
160
+
161
+ function mergeBaseline(
162
+ previous: CodexProvenanceEntry["baseline"],
163
+ next: CodexProvenanceEntry["baseline"],
164
+ ): CodexProvenanceEntry["baseline"] {
165
+ const known = previous.kind === "present"
166
+ ? new Set(["kind", "sha256", "bytesBase64"])
167
+ : new Set(["kind"]);
168
+ return copyUnknown(previous, next, known) as CodexProvenanceEntry["baseline"];
169
+ }
170
+
171
+ function knownArtifactIdentity(artifact: CodexArtifactId): string {
172
+ switch (artifact.kind) {
173
+ case "config":
174
+ case "generated-profile":
175
+ case "models-cache":
176
+ case "injection-journal":
177
+ return artifact.kind;
178
+ case "active-catalog":
179
+ return `${artifact.kind}\0${artifact.canonicalPath}`;
180
+ case "catalog-backup":
181
+ return `${artifact.kind}\0${artifact.form}\0${artifact.canonicalPath}`;
182
+ case "history-row":
183
+ case "history-manifest-entry":
184
+ return `${artifact.kind}\0${artifact.stateDbId}\0${artifact.threadId}`;
185
+ case "history-manifest":
186
+ case "history-rollout":
187
+ return `${artifact.kind}\0${artifact.stateDbId}\0${artifact.canonicalPath}`;
188
+ }
189
+ }
190
+
191
+ function mergeEntry(previous: CodexProvenanceEntry, next: CodexProvenanceEntry): CodexProvenanceEntry {
192
+ const merged = copyUnknown(
193
+ previous,
194
+ next,
195
+ new Set(["artifact", "baseline", "postImage", "txId", "at"]),
196
+ );
197
+ return {
198
+ ...merged,
199
+ artifact: mergeArtifact(previous.artifact, next.artifact),
200
+ baseline: mergeBaseline(previous.baseline, next.baseline),
201
+ } as CodexProvenanceEntry;
202
+ }
203
+
204
+ function mergeLedger(previous: CodexProvenanceLedger, next: CodexProvenanceLedger): CodexProvenanceLedger {
205
+ const unused = new Set(previous.entries.map((_, index) => index));
206
+ const entries = next.entries.map((entry, nextIndex) => {
207
+ let previousIndex = previous.entries.findIndex((candidate, index) =>
208
+ unused.has(index)
209
+ && candidate.txId === entry.txId
210
+ && candidate.at === entry.at
211
+ && knownArtifactIdentity(candidate.artifact) === knownArtifactIdentity(entry.artifact));
212
+ if (previousIndex < 0 && unused.has(nextIndex)) previousIndex = nextIndex;
213
+ if (previousIndex < 0) return entry;
214
+ unused.delete(previousIndex);
215
+ return mergeEntry(previous.entries[previousIndex]!, entry);
216
+ });
217
+ return {
218
+ ...copyUnknown(previous, next, new Set(["entries"])),
219
+ entries,
220
+ } as CodexProvenanceLedger;
221
+ }
222
+
223
+ function preserveExtensions(
224
+ previous: CodexIntegrationRecord,
225
+ next: CodexIntegrationRecord,
226
+ ): CodexIntegrationRecord {
227
+ const merged = copyUnknown(previous, next, new Set(["version", "provenance"]));
228
+ if (previous.provenance && next.provenance) {
229
+ merged.provenance = mergeLedger(previous.provenance, next.provenance);
230
+ }
231
+ return merged as CodexIntegrationRecord;
232
+ }
233
+
234
+ /**
235
+ * Keep read, extension merge, and atomic replacement inside the config mutation
236
+ * coordinator. WP12 must call this function instead of recreating the incident's
237
+ * stale read/merge/write sequence at its own call site.
238
+ */
239
+ export const updateIntegrationRecord = (
240
+ mutate: (record: CodexIntegrationRecord) => CodexIntegrationRecord,
241
+ ) => {
242
+ try {
243
+ return withConfigMutationLockSync(() => {
244
+ const read = readIntegrationRecordUnlocked();
245
+ if (read.kind === "invalid") return read;
246
+ const previous: CodexIntegrationRecord = read.kind === "ready" ? read.record : { version: 1 };
247
+ const proposed = mutate(previous);
248
+ if (!validateRecord(proposed)) {
249
+ return { kind: "invalid", message: "Codex integration record update produced a malformed v1 shape" };
250
+ }
251
+ const record = preserveExtensions(previous, proposed);
252
+ if (!validateRecord(record)) {
253
+ return { kind: "invalid", message: "Codex integration record extension merge produced a malformed v1 shape" };
254
+ }
255
+ const path = recordPath();
256
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
257
+ atomicWriteFile(path, `${JSON.stringify(record, null, 2)}\n`);
258
+ return { kind: "updated", record };
259
+ });
260
+ } catch (error) {
261
+ return {
262
+ kind: "invalid",
263
+ message: `Codex integration record update failed: ${error instanceof Error ? error.message : String(error)}`,
264
+ };
265
+ }
266
+ };
@@ -0,0 +1,203 @@
1
+ import { chmodSync, linkSync, mkdirSync, truncateSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+
4
+ import {
5
+ AtomicWriteResidualTempError,
6
+ AtomicWriteSecretResidualError,
7
+ atomicWriteFile,
8
+ resolveWriteTarget,
9
+ type AtomicWriteIO,
10
+ } from "../../config";
11
+ import {
12
+ assertCatalogWritePermit,
13
+ type CatalogWritePermit,
14
+ } from "../catalog-write-serialization";
15
+ import {
16
+ forgetEphemeralSecretPath,
17
+ hardenSecretPath,
18
+ } from "../../lib/windows-secret-acl";
19
+
20
+ export interface PreparedCatalogFileWrite {
21
+ readonly path: string;
22
+ readonly content: string;
23
+ }
24
+
25
+ export type CatalogBackupPublication = "written" | "preserved";
26
+
27
+ export interface CatalogBackupWriteIO {
28
+ readonly resolveTarget: (path: string) => string;
29
+ readonly write: (path: string, content: string) => void;
30
+ readonly harden: (path: string) => void;
31
+ /** Must fail with EEXIST rather than replacing an existing destination. */
32
+ readonly publishNoReplace: (source: string, destination: string) => void;
33
+ readonly truncate: (path: string) => void;
34
+ readonly unlink: (path: string) => void;
35
+ }
36
+
37
+ let backupTempSequence = 0;
38
+
39
+ function isMissingPathError(error: unknown): boolean {
40
+ return (error as NodeJS.ErrnoException | undefined)?.code === "ENOENT";
41
+ }
42
+
43
+ function isExistingPathError(error: unknown): boolean {
44
+ return (error as NodeJS.ErrnoException | undefined)?.code === "EEXIST";
45
+ }
46
+
47
+ function defaultBackupWriteIO(destinationPath: string): CatalogBackupWriteIO {
48
+ return {
49
+ resolveTarget: resolveWriteTarget,
50
+ write: (path, content) => writeFileSync(path, content, { encoding: "utf8", mode: 0o600 }),
51
+ harden: path => {
52
+ try { chmodSync(path, 0o600); } catch { /* platform may ignore chmod */ }
53
+ if (process.platform === "win32") {
54
+ hardenSecretPath(path, { required: true, timeoutMemoKey: destinationPath });
55
+ }
56
+ },
57
+ publishNoReplace: linkSync,
58
+ truncate: path => truncateSync(path, 0),
59
+ unlink: unlinkSync,
60
+ };
61
+ }
62
+
63
+ function removePublishedTemp(tempPath: string, io: CatalogBackupWriteIO): void {
64
+ try {
65
+ io.unlink(tempPath);
66
+ forgetEphemeralSecretPath(tempPath);
67
+ return;
68
+ } catch (firstError) {
69
+ if (isMissingPathError(firstError)) {
70
+ forgetEphemeralSecretPath(tempPath);
71
+ return;
72
+ }
73
+ try {
74
+ io.unlink(tempPath);
75
+ forgetEphemeralSecretPath(tempPath);
76
+ return;
77
+ } catch (retryError) {
78
+ if (isMissingPathError(retryError)) {
79
+ forgetEphemeralSecretPath(tempPath);
80
+ return;
81
+ }
82
+ throw new AtomicWriteResidualTempError(tempPath, true, { cause: retryError });
83
+ }
84
+ }
85
+ }
86
+
87
+ function scrubAndRemoveUnpublishedTemp(
88
+ tempPath: string,
89
+ hardened: boolean,
90
+ io: CatalogBackupWriteIO,
91
+ cause: unknown,
92
+ ): void {
93
+ let scrubbed = false;
94
+ try {
95
+ io.truncate(tempPath);
96
+ scrubbed = true;
97
+ } catch (error) {
98
+ if (isMissingPathError(error)) scrubbed = true;
99
+ else {
100
+ try {
101
+ io.write(tempPath, "");
102
+ scrubbed = true;
103
+ } catch { /* removal may still succeed */ }
104
+ }
105
+ }
106
+
107
+ let removed = false;
108
+ try {
109
+ io.unlink(tempPath);
110
+ removed = true;
111
+ } catch (error) {
112
+ if (isMissingPathError(error)) removed = true;
113
+ else {
114
+ try {
115
+ io.unlink(tempPath);
116
+ removed = true;
117
+ } catch (retryError) {
118
+ if (isMissingPathError(retryError)) removed = true;
119
+ }
120
+ }
121
+ }
122
+
123
+ if (!removed && !scrubbed) {
124
+ throw new AtomicWriteSecretResidualError(tempPath, { cause });
125
+ }
126
+ if (!removed && !hardened) {
127
+ try {
128
+ io.harden(tempPath);
129
+ hardened = true;
130
+ } catch { /* zero-byte residual is reported honestly */ }
131
+ }
132
+ if (removed) forgetEphemeralSecretPath(tempPath);
133
+ if (!removed) throw new AtomicWriteResidualTempError(tempPath, hardened, { cause });
134
+ }
135
+
136
+ function publishCatalogBackup(
137
+ prepared: PreparedCatalogFileWrite,
138
+ suppliedIo?: CatalogBackupWriteIO,
139
+ ): CatalogBackupPublication {
140
+ const io = suppliedIo ?? defaultBackupWriteIO(prepared.path);
141
+ const target = io.resolveTarget(prepared.path);
142
+ if (!suppliedIo) mkdirSync(dirname(target), { recursive: true, mode: 0o700 });
143
+ const tempPath = `${target}.ocx.${process.pid}.backup.${++backupTempSequence}.tmp`;
144
+ let hardened = false;
145
+
146
+ try {
147
+ io.write(tempPath, prepared.content);
148
+ io.harden(tempPath);
149
+ hardened = true;
150
+ io.publishNoReplace(tempPath, target);
151
+ } catch (error) {
152
+ scrubAndRemoveUnpublishedTemp(tempPath, hardened, io, error);
153
+ if (isExistingPathError(error)) return "preserved";
154
+ throw error;
155
+ }
156
+
157
+ removePublishedTemp(tempPath, io);
158
+ return "written";
159
+ }
160
+
161
+ /** Replace the active catalog with the caller's already-prepared bytes. */
162
+ export function replaceActiveCodexCatalog(
163
+ permit: CatalogWritePermit,
164
+ owningCodexHome: string,
165
+ prepared: PreparedCatalogFileWrite,
166
+ io?: AtomicWriteIO,
167
+ ): void {
168
+ assertCatalogWritePermit(permit, owningCodexHome);
169
+ atomicWriteFile(prepared.path, prepared.content, io);
170
+ }
171
+
172
+ /** Atomically publish the catalog-path-keyed immutable backup without clobbering. */
173
+ export function publishHashedCodexCatalogBackup(
174
+ permit: CatalogWritePermit,
175
+ owningCodexHome: string,
176
+ prepared: PreparedCatalogFileWrite,
177
+ io?: CatalogBackupWriteIO,
178
+ ): CatalogBackupPublication {
179
+ assertCatalogWritePermit(permit, owningCodexHome);
180
+ return publishCatalogBackup(prepared, io);
181
+ }
182
+
183
+ /** Atomically publish the legacy immutable backup without clobbering. */
184
+ export function publishLegacyCodexCatalogBackup(
185
+ permit: CatalogWritePermit,
186
+ owningCodexHome: string,
187
+ prepared: PreparedCatalogFileWrite,
188
+ io?: CatalogBackupWriteIO,
189
+ ): CatalogBackupPublication {
190
+ assertCatalogWritePermit(permit, owningCodexHome);
191
+ return publishCatalogBackup(prepared, io);
192
+ }
193
+
194
+ /** Replace Codex's models cache with the caller's already-prepared bytes. */
195
+ export function replaceCodexModelsCache(
196
+ permit: CatalogWritePermit,
197
+ owningCodexHome: string,
198
+ prepared: PreparedCatalogFileWrite,
199
+ io?: AtomicWriteIO,
200
+ ): void {
201
+ assertCatalogWritePermit(permit, owningCodexHome);
202
+ atomicWriteFile(prepared.path, prepared.content, io);
203
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The history mutation boundary. Every byte Codex history owns is written here,
3
+ * and only while H is held.
4
+ *
5
+ * This module exists because the mutations are spread across three surfaces that
6
+ * do not share a transaction: SQLite rows, the backup manifest, and the rollout
7
+ * files. `syncCodexHistoryProvider` writes the manifest BEFORE its database
8
+ * transaction and patches rollouts inside it; restore writes rollouts, then the
9
+ * database, then the manifest, then ejects again
10
+ * (`src/codex/history-provider.ts:606-648,656-698`). A SQLite busy timeout
11
+ * serializes exactly one of those three, which is why an opposite-direction
12
+ * process could overtake through the other two.
13
+ *
14
+ * The permit argument is not decoration and not a type-level claim. Each entry
15
+ * point asks the lock owner at RUNTIME whether the permit it was handed is still
16
+ * live for the state database about to be written, because a permit leaked past
17
+ * its callback type-checks perfectly. A writer reached without H therefore fails
18
+ * closed rather than racing.
19
+ *
20
+ * Reachability: `src/codex/history-worker.ts` is the only permitted production
21
+ * root. Readers and probes stay in `history-provider.ts`; nothing in the CLI, the
22
+ * server, the guardian, `inject.ts` or `sync.ts` may reach these symbols.
23
+ *
24
+ * Design record: devlog/_fin/260804_codex_write_substrate/020_history_isolation.md.
25
+ */
26
+ import { assertHistoryWritePermit, type HistoryWritePermit } from "../history-lock";
27
+ import {
28
+ migrateCodexLbHistoryToOpenai,
29
+ restoreLegacyOpenaiHistory,
30
+ restoreManagedOpenaiHistory,
31
+ syncCodexHistoryProvider,
32
+ type CodexHistoryProvider,
33
+ type CodexHistorySyncResult,
34
+ } from "../history-provider";
35
+
36
+ /**
37
+ * Everything a history mutation needs, with no ambient state.
38
+ *
39
+ * The paths are explicit because a Worker is a separate process: it does not
40
+ * inherit the module-load `CODEX_HOME` that `history-provider.ts` resolves at
41
+ * import time (`:16`, `:22`), so a request that relied on those constants would
42
+ * silently address the wrong home.
43
+ */
44
+ export interface HistoryWriteTarget {
45
+ /** Canonical, absolute; the same identity H was acquired for. */
46
+ readonly canonicalStateDbPath: string;
47
+ /** Canonical, absolute path of the backup manifest for that database. */
48
+ readonly canonicalBackupPath: string;
49
+ }
50
+
51
+ /** Apply Design-B native identity and then adopt legacy codex-lb task identities. */
52
+ export function writeManagedOpenaiHistoryMigration(
53
+ permit: HistoryWritePermit,
54
+ target: HistoryWriteTarget,
55
+ ): CodexHistorySyncResult {
56
+ assertHistoryWritePermit(permit, target.canonicalStateDbPath);
57
+ const native = restoreManagedOpenaiHistory(
58
+ target.canonicalStateDbPath,
59
+ target.canonicalBackupPath,
60
+ );
61
+ if (native.failed) return native;
62
+ const adopted = migrateCodexLbHistoryToOpenai(
63
+ target.canonicalStateDbPath,
64
+ target.canonicalBackupPath,
65
+ );
66
+ if (adopted.failed) return adopted;
67
+ return {
68
+ rows: native.rows + adopted.rows,
69
+ files: native.files + adopted.files,
70
+ ...(native.ejectedRows !== undefined ? { ejectedRows: native.ejectedRows } : {}),
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Apply Remodex routing to resumable history, or restore it to native.
76
+ *
77
+ * `provider` is the DURABLE operation's direction, resolved by the caller from
78
+ * the coordinator row — never a caller-supplied preference. The Worker passes
79
+ * what the row said, which is what stops a request from turning a restore into
80
+ * an apply.
81
+ */
82
+ export function writeHistoryProviderTransition(
83
+ permit: HistoryWritePermit,
84
+ target: HistoryWriteTarget,
85
+ provider: CodexHistoryProvider,
86
+ ): CodexHistorySyncResult {
87
+ assertHistoryWritePermit(permit, target.canonicalStateDbPath);
88
+ return syncCodexHistoryProvider(provider, target.canonicalStateDbPath, target.canonicalBackupPath);
89
+ }
90
+
91
+ /**
92
+ * Manifest-independent legacy ejection.
93
+ *
94
+ * Distinct from the generic restore above: it never reads, consumes, deletes or
95
+ * replaces the backup manifest. It does patch rollout metadata and returns a
96
+ * `files` count, so calling it "DB-only" would be wrong — the name says what it
97
+ * actually avoids.
98
+ */
99
+ export function writeLegacyOpenaiHistoryRecovery(
100
+ permit: HistoryWritePermit,
101
+ target: HistoryWriteTarget,
102
+ ): CodexHistorySyncResult {
103
+ assertHistoryWritePermit(permit, target.canonicalStateDbPath);
104
+ return restoreLegacyOpenaiHistory(target.canonicalStateDbPath);
105
+ }