codex-multi-auth 0.1.0

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 (327) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +162 -0
  3. package/assets/opencode-logo-ornate-dark.svg +18 -0
  4. package/assets/readme-hero.svg +31 -0
  5. package/config/README.md +87 -0
  6. package/config/minimal-opencode.json +13 -0
  7. package/config/opencode-legacy.json +571 -0
  8. package/config/opencode-modern.json +239 -0
  9. package/dist/index.d.ts +45 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +3160 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/accounts/rate-limits.d.ts +22 -0
  14. package/dist/lib/accounts/rate-limits.d.ts.map +1 -0
  15. package/dist/lib/accounts/rate-limits.js +63 -0
  16. package/dist/lib/accounts/rate-limits.js.map +1 -0
  17. package/dist/lib/accounts.d.ts +95 -0
  18. package/dist/lib/accounts.d.ts.map +1 -0
  19. package/dist/lib/accounts.js +668 -0
  20. package/dist/lib/accounts.js.map +1 -0
  21. package/dist/lib/audit.d.ts +45 -0
  22. package/dist/lib/audit.d.ts.map +1 -0
  23. package/dist/lib/audit.js +131 -0
  24. package/dist/lib/audit.js.map +1 -0
  25. package/dist/lib/auth/auth.d.ts +56 -0
  26. package/dist/lib/auth/auth.d.ts.map +1 -0
  27. package/dist/lib/auth/auth.js +214 -0
  28. package/dist/lib/auth/auth.js.map +1 -0
  29. package/dist/lib/auth/browser.d.ts +34 -0
  30. package/dist/lib/auth/browser.d.ts.map +1 -0
  31. package/dist/lib/auth/browser.js +185 -0
  32. package/dist/lib/auth/browser.js.map +1 -0
  33. package/dist/lib/auth/server.d.ts +24 -0
  34. package/dist/lib/auth/server.d.ts.map +1 -0
  35. package/dist/lib/auth/server.js +116 -0
  36. package/dist/lib/auth/server.js.map +1 -0
  37. package/dist/lib/auth/token-utils.d.ts +59 -0
  38. package/dist/lib/auth/token-utils.d.ts.map +1 -0
  39. package/dist/lib/auth/token-utils.js +331 -0
  40. package/dist/lib/auth/token-utils.js.map +1 -0
  41. package/dist/lib/auth-rate-limit.d.ts +20 -0
  42. package/dist/lib/auth-rate-limit.d.ts.map +1 -0
  43. package/dist/lib/auth-rate-limit.js +91 -0
  44. package/dist/lib/auth-rate-limit.js.map +1 -0
  45. package/dist/lib/auto-update-checker.d.ts +10 -0
  46. package/dist/lib/auto-update-checker.d.ts.map +1 -0
  47. package/dist/lib/auto-update-checker.js +216 -0
  48. package/dist/lib/auto-update-checker.js.map +1 -0
  49. package/dist/lib/capability-policy.d.ts +18 -0
  50. package/dist/lib/capability-policy.d.ts.map +1 -0
  51. package/dist/lib/capability-policy.js +150 -0
  52. package/dist/lib/capability-policy.js.map +1 -0
  53. package/dist/lib/circuit-breaker.d.ts +34 -0
  54. package/dist/lib/circuit-breaker.d.ts.map +1 -0
  55. package/dist/lib/circuit-breaker.js +124 -0
  56. package/dist/lib/circuit-breaker.js.map +1 -0
  57. package/dist/lib/cli.d.ts +64 -0
  58. package/dist/lib/cli.d.ts.map +1 -0
  59. package/dist/lib/cli.js +274 -0
  60. package/dist/lib/cli.js.map +1 -0
  61. package/dist/lib/codex-cli/observability.d.ts +22 -0
  62. package/dist/lib/codex-cli/observability.d.ts.map +1 -0
  63. package/dist/lib/codex-cli/observability.js +36 -0
  64. package/dist/lib/codex-cli/observability.js.map +1 -0
  65. package/dist/lib/codex-cli/state.d.ts +86 -0
  66. package/dist/lib/codex-cli/state.d.ts.map +1 -0
  67. package/dist/lib/codex-cli/state.js +470 -0
  68. package/dist/lib/codex-cli/state.js.map +1 -0
  69. package/dist/lib/codex-cli/sync.d.ts +27 -0
  70. package/dist/lib/codex-cli/sync.d.ts.map +1 -0
  71. package/dist/lib/codex-cli/sync.js +325 -0
  72. package/dist/lib/codex-cli/sync.js.map +1 -0
  73. package/dist/lib/codex-cli/writer.d.ts +12 -0
  74. package/dist/lib/codex-cli/writer.d.ts.map +1 -0
  75. package/dist/lib/codex-cli/writer.js +388 -0
  76. package/dist/lib/codex-cli/writer.js.map +1 -0
  77. package/dist/lib/codex-manager.d.ts +2 -0
  78. package/dist/lib/codex-manager.d.ts.map +1 -0
  79. package/dist/lib/codex-manager.js +4841 -0
  80. package/dist/lib/codex-manager.js.map +1 -0
  81. package/dist/lib/config.d.ts +269 -0
  82. package/dist/lib/config.d.ts.map +1 -0
  83. package/dist/lib/config.js +789 -0
  84. package/dist/lib/config.js.map +1 -0
  85. package/dist/lib/constants.d.ts +78 -0
  86. package/dist/lib/constants.d.ts.map +1 -0
  87. package/dist/lib/constants.js +78 -0
  88. package/dist/lib/constants.js.map +1 -0
  89. package/dist/lib/context-overflow.d.ts +27 -0
  90. package/dist/lib/context-overflow.d.ts.map +1 -0
  91. package/dist/lib/context-overflow.js +124 -0
  92. package/dist/lib/context-overflow.js.map +1 -0
  93. package/dist/lib/dashboard-settings.d.ts +90 -0
  94. package/dist/lib/dashboard-settings.d.ts.map +1 -0
  95. package/dist/lib/dashboard-settings.js +327 -0
  96. package/dist/lib/dashboard-settings.js.map +1 -0
  97. package/dist/lib/entitlement-cache.d.ts +41 -0
  98. package/dist/lib/entitlement-cache.d.ts.map +1 -0
  99. package/dist/lib/entitlement-cache.js +137 -0
  100. package/dist/lib/entitlement-cache.js.map +1 -0
  101. package/dist/lib/errors.d.ts +113 -0
  102. package/dist/lib/errors.d.ts.map +1 -0
  103. package/dist/lib/errors.js +103 -0
  104. package/dist/lib/errors.js.map +1 -0
  105. package/dist/lib/forecast.d.ts +42 -0
  106. package/dist/lib/forecast.d.ts.map +1 -0
  107. package/dist/lib/forecast.js +256 -0
  108. package/dist/lib/forecast.js.map +1 -0
  109. package/dist/lib/health.d.ts +33 -0
  110. package/dist/lib/health.d.ts.map +1 -0
  111. package/dist/lib/health.js +70 -0
  112. package/dist/lib/health.js.map +1 -0
  113. package/dist/lib/index.d.ts +32 -0
  114. package/dist/lib/index.d.ts.map +1 -0
  115. package/dist/lib/index.js +32 -0
  116. package/dist/lib/index.js.map +1 -0
  117. package/dist/lib/live-account-sync.d.ts +39 -0
  118. package/dist/lib/live-account-sync.d.ts.map +1 -0
  119. package/dist/lib/live-account-sync.js +196 -0
  120. package/dist/lib/live-account-sync.js.map +1 -0
  121. package/dist/lib/logger.d.ts +40 -0
  122. package/dist/lib/logger.d.ts.map +1 -0
  123. package/dist/lib/logger.js +364 -0
  124. package/dist/lib/logger.js.map +1 -0
  125. package/dist/lib/oauth-success.html +338 -0
  126. package/dist/lib/parallel-probe.d.ts +28 -0
  127. package/dist/lib/parallel-probe.d.ts.map +1 -0
  128. package/dist/lib/parallel-probe.js +97 -0
  129. package/dist/lib/parallel-probe.js.map +1 -0
  130. package/dist/lib/preemptive-quota-scheduler.d.ts +53 -0
  131. package/dist/lib/preemptive-quota-scheduler.d.ts.map +1 -0
  132. package/dist/lib/preemptive-quota-scheduler.js +220 -0
  133. package/dist/lib/preemptive-quota-scheduler.js.map +1 -0
  134. package/dist/lib/proactive-refresh.d.ts +66 -0
  135. package/dist/lib/proactive-refresh.d.ts.map +1 -0
  136. package/dist/lib/proactive-refresh.js +143 -0
  137. package/dist/lib/proactive-refresh.js.map +1 -0
  138. package/dist/lib/prompts/codex-opencode-bridge.d.ts +19 -0
  139. package/dist/lib/prompts/codex-opencode-bridge.d.ts.map +1 -0
  140. package/dist/lib/prompts/codex-opencode-bridge.js +169 -0
  141. package/dist/lib/prompts/codex-opencode-bridge.js.map +1 -0
  142. package/dist/lib/prompts/codex.d.ts +41 -0
  143. package/dist/lib/prompts/codex.d.ts.map +1 -0
  144. package/dist/lib/prompts/codex.js +383 -0
  145. package/dist/lib/prompts/codex.js.map +1 -0
  146. package/dist/lib/prompts/opencode-codex.d.ts +25 -0
  147. package/dist/lib/prompts/opencode-codex.d.ts.map +1 -0
  148. package/dist/lib/prompts/opencode-codex.js +270 -0
  149. package/dist/lib/prompts/opencode-codex.js.map +1 -0
  150. package/dist/lib/quota-cache.d.ts +68 -0
  151. package/dist/lib/quota-cache.d.ts.map +1 -0
  152. package/dist/lib/quota-cache.js +224 -0
  153. package/dist/lib/quota-cache.js.map +1 -0
  154. package/dist/lib/quota-probe.d.ts +49 -0
  155. package/dist/lib/quota-probe.d.ts.map +1 -0
  156. package/dist/lib/quota-probe.js +368 -0
  157. package/dist/lib/quota-probe.js.map +1 -0
  158. package/dist/lib/recovery/constants.d.ts +12 -0
  159. package/dist/lib/recovery/constants.d.ts.map +1 -0
  160. package/dist/lib/recovery/constants.js +31 -0
  161. package/dist/lib/recovery/constants.js.map +1 -0
  162. package/dist/lib/recovery/index.d.ts +12 -0
  163. package/dist/lib/recovery/index.d.ts.map +1 -0
  164. package/dist/lib/recovery/index.js +12 -0
  165. package/dist/lib/recovery/index.js.map +1 -0
  166. package/dist/lib/recovery/storage.d.ts +24 -0
  167. package/dist/lib/recovery/storage.d.ts.map +1 -0
  168. package/dist/lib/recovery/storage.js +362 -0
  169. package/dist/lib/recovery/storage.js.map +1 -0
  170. package/dist/lib/recovery/types.d.ts +116 -0
  171. package/dist/lib/recovery/types.d.ts.map +1 -0
  172. package/dist/lib/recovery/types.js +7 -0
  173. package/dist/lib/recovery/types.js.map +1 -0
  174. package/dist/lib/recovery.d.ts +31 -0
  175. package/dist/lib/recovery.d.ts.map +1 -0
  176. package/dist/lib/recovery.js +313 -0
  177. package/dist/lib/recovery.js.map +1 -0
  178. package/dist/lib/refresh-guardian.d.ts +31 -0
  179. package/dist/lib/refresh-guardian.d.ts.map +1 -0
  180. package/dist/lib/refresh-guardian.js +151 -0
  181. package/dist/lib/refresh-guardian.js.map +1 -0
  182. package/dist/lib/refresh-lease.d.ts +37 -0
  183. package/dist/lib/refresh-lease.d.ts.map +1 -0
  184. package/dist/lib/refresh-lease.js +335 -0
  185. package/dist/lib/refresh-lease.js.map +1 -0
  186. package/dist/lib/refresh-queue.d.ts +117 -0
  187. package/dist/lib/refresh-queue.d.ts.map +1 -0
  188. package/dist/lib/refresh-queue.js +297 -0
  189. package/dist/lib/refresh-queue.js.map +1 -0
  190. package/dist/lib/request/failure-policy.d.ts +42 -0
  191. package/dist/lib/request/failure-policy.d.ts.map +1 -0
  192. package/dist/lib/request/failure-policy.js +133 -0
  193. package/dist/lib/request/failure-policy.js.map +1 -0
  194. package/dist/lib/request/fetch-helpers.d.ts +152 -0
  195. package/dist/lib/request/fetch-helpers.d.ts.map +1 -0
  196. package/dist/lib/request/fetch-helpers.js +704 -0
  197. package/dist/lib/request/fetch-helpers.js.map +1 -0
  198. package/dist/lib/request/helpers/input-utils.d.ts +7 -0
  199. package/dist/lib/request/helpers/input-utils.d.ts.map +1 -0
  200. package/dist/lib/request/helpers/input-utils.js +214 -0
  201. package/dist/lib/request/helpers/input-utils.js.map +1 -0
  202. package/dist/lib/request/helpers/model-map.d.ts +28 -0
  203. package/dist/lib/request/helpers/model-map.d.ts.map +1 -0
  204. package/dist/lib/request/helpers/model-map.js +133 -0
  205. package/dist/lib/request/helpers/model-map.js.map +1 -0
  206. package/dist/lib/request/helpers/tool-utils.d.ts +29 -0
  207. package/dist/lib/request/helpers/tool-utils.d.ts.map +1 -0
  208. package/dist/lib/request/helpers/tool-utils.js +117 -0
  209. package/dist/lib/request/helpers/tool-utils.js.map +1 -0
  210. package/dist/lib/request/rate-limit-backoff.d.ts +17 -0
  211. package/dist/lib/request/rate-limit-backoff.d.ts.map +1 -0
  212. package/dist/lib/request/rate-limit-backoff.js +83 -0
  213. package/dist/lib/request/rate-limit-backoff.js.map +1 -0
  214. package/dist/lib/request/request-transformer.d.ts +107 -0
  215. package/dist/lib/request/request-transformer.d.ts.map +1 -0
  216. package/dist/lib/request/request-transformer.js +814 -0
  217. package/dist/lib/request/request-transformer.js.map +1 -0
  218. package/dist/lib/request/response-handler.d.ts +23 -0
  219. package/dist/lib/request/response-handler.d.ts.map +1 -0
  220. package/dist/lib/request/response-handler.js +155 -0
  221. package/dist/lib/request/response-handler.js.map +1 -0
  222. package/dist/lib/request/stream-failover.d.ts +21 -0
  223. package/dist/lib/request/stream-failover.d.ts.map +1 -0
  224. package/dist/lib/request/stream-failover.js +204 -0
  225. package/dist/lib/request/stream-failover.js.map +1 -0
  226. package/dist/lib/rotation.d.ts +146 -0
  227. package/dist/lib/rotation.d.ts.map +1 -0
  228. package/dist/lib/rotation.js +321 -0
  229. package/dist/lib/rotation.js.map +1 -0
  230. package/dist/lib/runtime-paths.d.ts +58 -0
  231. package/dist/lib/runtime-paths.d.ts.map +1 -0
  232. package/dist/lib/runtime-paths.js +164 -0
  233. package/dist/lib/runtime-paths.js.map +1 -0
  234. package/dist/lib/schemas.d.ts +435 -0
  235. package/dist/lib/schemas.d.ts.map +1 -0
  236. package/dist/lib/schemas.js +268 -0
  237. package/dist/lib/schemas.js.map +1 -0
  238. package/dist/lib/session-affinity.d.ts +23 -0
  239. package/dist/lib/session-affinity.d.ts.map +1 -0
  240. package/dist/lib/session-affinity.js +127 -0
  241. package/dist/lib/session-affinity.js.map +1 -0
  242. package/dist/lib/shutdown.d.ts +7 -0
  243. package/dist/lib/shutdown.d.ts.map +1 -0
  244. package/dist/lib/shutdown.js +43 -0
  245. package/dist/lib/shutdown.js.map +1 -0
  246. package/dist/lib/storage/migrations.d.ts +59 -0
  247. package/dist/lib/storage/migrations.d.ts.map +1 -0
  248. package/dist/lib/storage/migrations.js +41 -0
  249. package/dist/lib/storage/migrations.js.map +1 -0
  250. package/dist/lib/storage/paths.d.ts +51 -0
  251. package/dist/lib/storage/paths.d.ts.map +1 -0
  252. package/dist/lib/storage/paths.js +152 -0
  253. package/dist/lib/storage/paths.js.map +1 -0
  254. package/dist/lib/storage.d.ts +106 -0
  255. package/dist/lib/storage.d.ts.map +1 -0
  256. package/dist/lib/storage.js +896 -0
  257. package/dist/lib/storage.js.map +1 -0
  258. package/dist/lib/table-formatter.d.ts +32 -0
  259. package/dist/lib/table-formatter.d.ts.map +1 -0
  260. package/dist/lib/table-formatter.js +44 -0
  261. package/dist/lib/table-formatter.js.map +1 -0
  262. package/dist/lib/tools/hashline-tools.d.ts +51 -0
  263. package/dist/lib/tools/hashline-tools.d.ts.map +1 -0
  264. package/dist/lib/tools/hashline-tools.js +456 -0
  265. package/dist/lib/tools/hashline-tools.js.map +1 -0
  266. package/dist/lib/types.d.ts +130 -0
  267. package/dist/lib/types.d.ts.map +1 -0
  268. package/dist/lib/types.js +2 -0
  269. package/dist/lib/types.js.map +1 -0
  270. package/dist/lib/ui/ansi.d.ts +40 -0
  271. package/dist/lib/ui/ansi.d.ts.map +1 -0
  272. package/dist/lib/ui/ansi.js +68 -0
  273. package/dist/lib/ui/ansi.js.map +1 -0
  274. package/dist/lib/ui/auth-menu.d.ts +76 -0
  275. package/dist/lib/ui/auth-menu.d.ts.map +1 -0
  276. package/dist/lib/ui/auth-menu.js +590 -0
  277. package/dist/lib/ui/auth-menu.js.map +1 -0
  278. package/dist/lib/ui/confirm.d.ts +11 -0
  279. package/dist/lib/ui/confirm.d.ts.map +1 -0
  280. package/dist/lib/ui/confirm.js +29 -0
  281. package/dist/lib/ui/confirm.js.map +1 -0
  282. package/dist/lib/ui/copy.d.ts +123 -0
  283. package/dist/lib/ui/copy.d.ts.map +1 -0
  284. package/dist/lib/ui/copy.js +127 -0
  285. package/dist/lib/ui/copy.js.map +1 -0
  286. package/dist/lib/ui/format.d.ts +62 -0
  287. package/dist/lib/ui/format.d.ts.map +1 -0
  288. package/dist/lib/ui/format.js +205 -0
  289. package/dist/lib/ui/format.js.map +1 -0
  290. package/dist/lib/ui/runtime.d.ts +43 -0
  291. package/dist/lib/ui/runtime.d.ts.map +1 -0
  292. package/dist/lib/ui/runtime.js +69 -0
  293. package/dist/lib/ui/runtime.js.map +1 -0
  294. package/dist/lib/ui/select.d.ts +60 -0
  295. package/dist/lib/ui/select.d.ts.map +1 -0
  296. package/dist/lib/ui/select.js +467 -0
  297. package/dist/lib/ui/select.js.map +1 -0
  298. package/dist/lib/ui/theme.d.ts +56 -0
  299. package/dist/lib/ui/theme.d.ts.map +1 -0
  300. package/dist/lib/ui/theme.js +186 -0
  301. package/dist/lib/ui/theme.js.map +1 -0
  302. package/dist/lib/unified-settings.d.ts +71 -0
  303. package/dist/lib/unified-settings.d.ts.map +1 -0
  304. package/dist/lib/unified-settings.js +299 -0
  305. package/dist/lib/unified-settings.js.map +1 -0
  306. package/dist/lib/utils.d.ts +29 -0
  307. package/dist/lib/utils.d.ts.map +1 -0
  308. package/dist/lib/utils.js +54 -0
  309. package/dist/lib/utils.js.map +1 -0
  310. package/package.json +115 -0
  311. package/scripts/audit-dev-allowlist.js +128 -0
  312. package/scripts/bench-format/hashline-v2.mjs +642 -0
  313. package/scripts/bench-format/models.mjs +105 -0
  314. package/scripts/bench-format/opencode.mjs +205 -0
  315. package/scripts/bench-format/render.mjs +496 -0
  316. package/scripts/bench-format/stats.mjs +54 -0
  317. package/scripts/bench-format/tasks.mjs +151 -0
  318. package/scripts/benchmark-edit-formats.mjs +1161 -0
  319. package/scripts/benchmark-render-dashboard.mjs +49 -0
  320. package/scripts/codex-multi-auth.js +6 -0
  321. package/scripts/codex-routing.js +34 -0
  322. package/scripts/codex.js +122 -0
  323. package/scripts/copy-oauth-success.js +37 -0
  324. package/scripts/install-opencode-codex-auth.js +193 -0
  325. package/scripts/test-all-models.sh +7 -0
  326. package/scripts/test-model-matrix.js +424 -0
  327. package/scripts/validate-model-map.sh +7 -0
@@ -0,0 +1,270 @@
1
+ /**
2
+ * OpenCode Codex Prompt Fetcher
3
+ *
4
+ * Fetches and caches the codex.txt system prompt from OpenCode's GitHub repository.
5
+ * Uses ETag-based caching to efficiently track updates.
6
+ */
7
+ import { join } from "node:path";
8
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
9
+ import { logDebug } from "../logger.js";
10
+ import { getCodexCacheDir } from "../runtime-paths.js";
11
+ import { sleep } from "../utils.js";
12
+ const DEFAULT_OPENCODE_CODEX_URLS = [
13
+ "https://raw.githubusercontent.com/anomalyco/opencode/dev/packages/opencode/src/session/prompt/codex.txt",
14
+ "https://raw.githubusercontent.com/sst/opencode/dev/packages/opencode/src/session/prompt/codex.txt",
15
+ "https://raw.githubusercontent.com/anomalyco/opencode/main/packages/opencode/src/session/prompt/codex.txt",
16
+ "https://raw.githubusercontent.com/sst/opencode/main/packages/opencode/src/session/prompt/codex.txt",
17
+ "https://raw.githubusercontent.com/anomalyco/opencode/dev/packages/opencode/src/session/prompt/codex.md",
18
+ "https://raw.githubusercontent.com/sst/opencode/dev/packages/opencode/src/session/prompt/codex.md",
19
+ "https://raw.githubusercontent.com/anomalyco/opencode/main/packages/opencode/src/session/prompt/codex.md",
20
+ "https://raw.githubusercontent.com/sst/opencode/main/packages/opencode/src/session/prompt/codex.md",
21
+ ];
22
+ const CODEX_PROMPT_URL_OVERRIDE_ENV = "CODEX_PROMPT_SOURCE_URL";
23
+ const LEGACY_OPENCODE_CODEX_URL_OVERRIDE_ENV = "OPENCODE_CODEX_PROMPT_URL";
24
+ const CACHE_DIR = getCodexCacheDir();
25
+ const CACHE_FILE = join(CACHE_DIR, "opencode-codex.txt");
26
+ const CACHE_META_FILE = join(CACHE_DIR, "opencode-codex-meta.json");
27
+ const CACHE_TTL_MS = 15 * 60 * 1000;
28
+ const RETRYABLE_FS_ERROR_CODES = new Set(["EBUSY", "EPERM"]);
29
+ const WRITE_RETRY_ATTEMPTS = 5;
30
+ const WRITE_RETRY_BASE_DELAY_MS = 10;
31
+ let memoryCache = null;
32
+ let refreshPromise = null;
33
+ function isFresh(lastChecked) {
34
+ return Date.now() - lastChecked < CACHE_TTL_MS;
35
+ }
36
+ function redactSourceForLog(source) {
37
+ try {
38
+ const parsed = new URL(source);
39
+ return `${parsed.origin}${parsed.pathname}`;
40
+ }
41
+ catch {
42
+ return "<invalid-url>";
43
+ }
44
+ }
45
+ function parseSourceUrl(source) {
46
+ if (!source)
47
+ return undefined;
48
+ const trimmed = source.trim();
49
+ if (!trimmed)
50
+ return undefined;
51
+ try {
52
+ const parsed = new URL(trimmed);
53
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
54
+ logDebug("Ignoring OpenCode codex prompt source override due to protocol", {
55
+ source: redactSourceForLog(trimmed),
56
+ });
57
+ return undefined;
58
+ }
59
+ return trimmed;
60
+ }
61
+ catch {
62
+ logDebug("Ignoring invalid OpenCode codex prompt source override", {
63
+ source: redactSourceForLog(trimmed),
64
+ });
65
+ return undefined;
66
+ }
67
+ }
68
+ function sourceCacheKey(source) {
69
+ try {
70
+ const parsed = new URL(source);
71
+ return `${parsed.origin}${parsed.pathname}`;
72
+ }
73
+ catch {
74
+ return source.trim();
75
+ }
76
+ }
77
+ function isRetryableFsError(error) {
78
+ const code = error?.code;
79
+ return typeof code === "string" && RETRYABLE_FS_ERROR_CODES.has(code);
80
+ }
81
+ async function writeFileWithRetry(filePath, content) {
82
+ let lastError;
83
+ for (let attempt = 0; attempt < WRITE_RETRY_ATTEMPTS; attempt += 1) {
84
+ try {
85
+ await writeFile(filePath, content, "utf-8");
86
+ return;
87
+ }
88
+ catch (error) {
89
+ if (!isRetryableFsError(error) || attempt + 1 >= WRITE_RETRY_ATTEMPTS) {
90
+ throw error;
91
+ }
92
+ lastError = error;
93
+ await sleep(WRITE_RETRY_BASE_DELAY_MS * 2 ** attempt);
94
+ }
95
+ }
96
+ throw lastError instanceof Error ? lastError : new Error("Failed to write prompt cache file");
97
+ }
98
+ function resolvePromptSources() {
99
+ const sources = [];
100
+ const seen = new Set();
101
+ const add = (source) => {
102
+ const parsed = parseSourceUrl(source);
103
+ if (!parsed || seen.has(parsed))
104
+ return;
105
+ seen.add(parsed);
106
+ sources.push(parsed);
107
+ };
108
+ add(process.env[CODEX_PROMPT_URL_OVERRIDE_ENV]);
109
+ add(process.env[LEGACY_OPENCODE_CODEX_URL_OVERRIDE_ENV]);
110
+ for (const source of DEFAULT_OPENCODE_CODEX_URLS) {
111
+ add(source);
112
+ }
113
+ return sources;
114
+ }
115
+ async function readDiskCache() {
116
+ try {
117
+ const [content, metaContent] = await Promise.all([
118
+ readFile(CACHE_FILE, "utf-8"),
119
+ readFile(CACHE_META_FILE, "utf-8"),
120
+ ]);
121
+ const meta = JSON.parse(metaContent);
122
+ if (!meta.lastChecked) {
123
+ return null;
124
+ }
125
+ return { content, meta };
126
+ }
127
+ catch {
128
+ return null;
129
+ }
130
+ }
131
+ async function saveDiskCache(content, etag, sourceUrl) {
132
+ await mkdir(CACHE_DIR, { recursive: true });
133
+ const meta = {
134
+ etag,
135
+ lastFetch: new Date().toISOString(),
136
+ lastChecked: Date.now(),
137
+ sourceKey: sourceCacheKey(sourceUrl),
138
+ };
139
+ await Promise.all([
140
+ writeFileWithRetry(CACHE_FILE, content),
141
+ writeFileWithRetry(CACHE_META_FILE, JSON.stringify(meta, null, 2)),
142
+ ]);
143
+ return meta;
144
+ }
145
+ async function refreshPrompt(cachedMeta, cachedContent) {
146
+ const sources = resolvePromptSources();
147
+ let lastFailure = null;
148
+ for (const sourceUrl of sources) {
149
+ const headers = {};
150
+ const currentSourceKey = sourceCacheKey(sourceUrl);
151
+ const cachedSourceKey = cachedMeta?.sourceKey ??
152
+ (cachedMeta?.sourceUrl ? sourceCacheKey(cachedMeta.sourceUrl) : undefined);
153
+ const canUseConditionalRequest = !!cachedMeta?.etag &&
154
+ (!cachedSourceKey || cachedSourceKey === currentSourceKey);
155
+ if (canUseConditionalRequest) {
156
+ headers["If-None-Match"] = cachedMeta.etag;
157
+ }
158
+ let response;
159
+ try {
160
+ response = await fetch(sourceUrl, { headers });
161
+ }
162
+ catch (error) {
163
+ lastFailure = `${redactSourceForLog(sourceUrl)}: ${String(error)}`;
164
+ logDebug("OpenCode prompt source fetch failed", {
165
+ sourceUrl: redactSourceForLog(sourceUrl),
166
+ error: String(error),
167
+ });
168
+ continue;
169
+ }
170
+ if (response.status === 304 && cachedContent) {
171
+ const refreshedMeta = {
172
+ etag: cachedMeta?.etag ?? "",
173
+ lastFetch: cachedMeta?.lastFetch ?? new Date().toISOString(),
174
+ lastChecked: Date.now(),
175
+ sourceKey: currentSourceKey,
176
+ };
177
+ memoryCache = { content: cachedContent, meta: refreshedMeta };
178
+ await mkdir(CACHE_DIR, { recursive: true });
179
+ await writeFileWithRetry(CACHE_META_FILE, JSON.stringify(refreshedMeta, null, 2));
180
+ return cachedContent;
181
+ }
182
+ if (!response.ok) {
183
+ lastFailure = `${redactSourceForLog(sourceUrl)}: HTTP ${response.status}`;
184
+ logDebug("OpenCode prompt source returned non-OK response", {
185
+ sourceUrl: redactSourceForLog(sourceUrl),
186
+ status: response.status,
187
+ });
188
+ continue;
189
+ }
190
+ const content = await response.text();
191
+ const etag = response.headers.get("etag") || "";
192
+ const meta = await saveDiskCache(content, etag, sourceUrl);
193
+ memoryCache = { content, meta };
194
+ return content;
195
+ }
196
+ throw new Error(`Failed to fetch OpenCode codex prompt from all sources${lastFailure ? ` (${lastFailure})` : ""}`);
197
+ }
198
+ function scheduleRefresh(cachedMeta, cachedContent) {
199
+ if (refreshPromise)
200
+ return;
201
+ refreshPromise = refreshPrompt(cachedMeta, cachedContent)
202
+ .then(() => undefined)
203
+ .catch((error) => {
204
+ logDebug("OpenCode prompt background refresh failed", {
205
+ error: String(error),
206
+ });
207
+ })
208
+ .finally(() => {
209
+ refreshPromise = null;
210
+ });
211
+ }
212
+ /**
213
+ * Fetch OpenCode's codex.txt prompt with ETag-based caching
214
+ * Uses HTTP conditional requests to efficiently check for updates
215
+ *
216
+ * Rate limit protection: Only checks GitHub if cache is older than 15 minutes
217
+ * @returns The codex.txt content
218
+ */
219
+ export async function getOpenCodeCodexPrompt() {
220
+ if (memoryCache && isFresh(memoryCache.meta.lastChecked)) {
221
+ return memoryCache.content;
222
+ }
223
+ const diskCache = await readDiskCache();
224
+ if (diskCache) {
225
+ memoryCache = diskCache;
226
+ if (isFresh(diskCache.meta.lastChecked)) {
227
+ return diskCache.content;
228
+ }
229
+ // Serve stale content immediately and refresh in the background.
230
+ memoryCache = {
231
+ content: diskCache.content,
232
+ meta: { ...diskCache.meta, lastChecked: Date.now() },
233
+ };
234
+ scheduleRefresh(diskCache.meta, diskCache.content);
235
+ return diskCache.content;
236
+ }
237
+ try {
238
+ return await refreshPrompt(memoryCache?.meta ?? null, memoryCache?.content ?? null);
239
+ }
240
+ catch (error) {
241
+ const staleContent = memoryCache?.content;
242
+ if (staleContent) {
243
+ return staleContent;
244
+ }
245
+ throw new Error(`Failed to fetch OpenCode codex.txt and no cache available: ${error}`);
246
+ }
247
+ }
248
+ /**
249
+ * Get first N characters of the cached OpenCode prompt for verification
250
+ * @param chars Number of characters to get (default: 50)
251
+ * @returns First N characters or null if not cached
252
+ */
253
+ export async function getCachedPromptPrefix(chars = 50) {
254
+ try {
255
+ const content = await readFile(CACHE_FILE, "utf-8");
256
+ return content.substring(0, chars);
257
+ }
258
+ catch {
259
+ return null;
260
+ }
261
+ }
262
+ /**
263
+ * Prewarm the OpenCode prompt cache without blocking startup.
264
+ */
265
+ export function prewarmOpenCodeCodexPrompt() {
266
+ void getOpenCodeCodexPrompt().catch((error) => {
267
+ logDebug("OpenCode prompt prewarm failed", { error: String(error) });
268
+ });
269
+ }
270
+ //# sourceMappingURL=opencode-codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-codex.js","sourceRoot":"","sources":["../../../lib/prompts/opencode-codex.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,MAAM,2BAA2B,GAAG;IACnC,yGAAyG;IACzG,mGAAmG;IACnG,0GAA0G;IAC1G,oGAAoG;IACpG,wGAAwG;IACxG,kGAAkG;IAClG,yGAAyG;IACzG,mGAAmG;CAC1F,CAAC;AACX,MAAM,6BAA6B,GAAG,yBAAyB,CAAC;AAChE,MAAM,sCAAsC,GAAG,2BAA2B,CAAC;AAC3E,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;AACrC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AACzD,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,0BAA0B,CAAC,CAAC;AACpE,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACpC,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7D,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAerC,IAAI,WAAW,GAAyB,IAAI,CAAC;AAC7C,IAAI,cAAc,GAAyB,IAAI,CAAC;AAEhD,SAAS,OAAO,CAAC,WAAmB;IACnC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,YAAY,CAAC;AAChD,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACzC,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,eAAe,CAAC;IACxB,CAAC;AACF,CAAC;AAED,SAAS,cAAc,CAAC,MAA0B;IACjD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjE,QAAQ,CAAC,gEAAgE,EAAE;gBAC1E,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC;aACnC,CAAC,CAAC;YACH,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACR,QAAQ,CAAC,wDAAwD,EAAE;YAClE,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC;SACnC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACrC,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;AACF,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACzC,MAAM,IAAI,GAAI,KAA2C,EAAE,IAAI,CAAC;IAChE,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,QAAgB,EAAE,OAAe;IAClE,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,oBAAoB,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC;YACJ,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5C,OAAO;QACR,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,OAAO,GAAG,CAAC,IAAI,oBAAoB,EAAE,CAAC;gBACvE,MAAM,KAAK,CAAC;YACb,CAAC;YACD,SAAS,GAAG,KAAK,CAAC;YAClB,MAAM,KAAK,CAAC,yBAAyB,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC;QACvD,CAAC;IACF,CAAC;IACD,MAAM,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,oBAAoB;IAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,GAAG,GAAG,CAAC,MAA0B,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO;QACxC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAChD,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;IACzD,KAAK,MAAM,MAAM,IAAI,2BAA2B,EAAE,CAAC;QAClD,GAAG,CAAC,MAAM,CAAC,CAAC;IACb,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,aAAa;IAC3B,IAAI,CAAC;QACJ,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAChD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;YAC7B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;SAClC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAc,CAAC;QAClD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACb,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,KAAK,UAAU,aAAa,CAC3B,OAAe,EACf,IAAY,EACZ,SAAiB;IAEjB,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAc;QACvB,IAAI;QACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;QACvB,SAAS,EAAE,cAAc,CAAC,SAAS,CAAC;KACpC,CAAC;IACF,MAAM,OAAO,CAAC,GAAG,CAAC;QACjB,kBAAkB,CAAC,UAAU,EAAE,OAAO,CAAC;QACvC,kBAAkB,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;KAClE,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,aAAa,CAC3B,UAA4B,EAC5B,aAA4B;IAE5B,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;IACvC,IAAI,WAAW,GAAkB,IAAI,CAAC;IAEtC,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,MAAM,gBAAgB,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,eAAe,GAAG,UAAU,EAAE,SAAS;YAC5C,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5E,MAAM,wBAAwB,GAC7B,CAAC,CAAC,UAAU,EAAE,IAAI;YAClB,CAAC,CAAC,eAAe,IAAI,eAAe,KAAK,gBAAgB,CAAC,CAAC;QAC5D,IAAI,wBAAwB,EAAE,CAAC;YAC9B,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC;QAC5C,CAAC;QAED,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,WAAW,GAAG,GAAG,kBAAkB,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACnE,QAAQ,CAAC,qCAAqC,EAAE;gBAC/C,SAAS,EAAE,kBAAkB,CAAC,SAAS,CAAC;gBACxC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;aACpB,CAAC,CAAC;YACH,SAAS;QACV,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;YAC9C,MAAM,aAAa,GAAc;gBAChC,IAAI,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE;gBAC5B,SAAS,EAAE,UAAU,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5D,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;gBACvB,SAAS,EAAE,gBAAgB;aAC3B,CAAC;YACF,WAAW,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;YAC9D,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,MAAM,kBAAkB,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAClF,OAAO,aAAa,CAAC;QACtB,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAClB,WAAW,GAAG,GAAG,kBAAkB,CAAC,SAAS,CAAC,UAAU,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC1E,QAAQ,CAAC,iDAAiD,EAAE;gBAC3D,SAAS,EAAE,kBAAkB,CAAC,SAAS,CAAC;gBACxC,MAAM,EAAE,QAAQ,CAAC,MAAM;aACvB,CAAC,CAAC;YACH,SAAS;QACV,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3D,WAAW,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,MAAM,IAAI,KAAK,CACd,yDAAyD,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACjG,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,UAA4B,EAAE,aAA4B;IAClF,IAAI,cAAc;QAAE,OAAO;IAC3B,cAAc,GAAG,aAAa,CAAC,UAAU,EAAE,aAAa,CAAC;SACvD,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;SACrB,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAChB,QAAQ,CAAC,2CAA2C,EAAE;YACrD,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;SACpB,CAAC,CAAC;IACJ,CAAC,CAAC;SACD,OAAO,CAAC,GAAG,EAAE;QACb,cAAc,GAAG,IAAI,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC3C,IAAI,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1D,OAAO,WAAW,CAAC,OAAO,CAAC;IAC5B,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;IACxC,IAAI,SAAS,EAAE,CAAC;QACf,WAAW,GAAG,SAAS,CAAC;QACxB,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACzC,OAAO,SAAS,CAAC,OAAO,CAAC;QAC1B,CAAC;QACD,iEAAiE;QACjE,WAAW,GAAG;YACb,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,IAAI,EAAE,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;SACpD,CAAC;QACF,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,SAAS,CAAC,OAAO,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,MAAM,aAAa,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,EAAE,WAAW,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC;IACrF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,WAAW,EAAE,OAAO,CAAC;QAC1C,IAAI,YAAY,EAAE,CAAC;YAClB,OAAO,YAAY,CAAC;QACrB,CAAC;QACD,MAAM,IAAI,KAAK,CACd,8DAA8D,KAAK,EAAE,CACrE,CAAC;IACH,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAK,GAAG,EAAE;IACrD,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B;IACzC,KAAK,sBAAsB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAC7C,QAAQ,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,68 @@
1
+ export interface QuotaCacheWindow {
2
+ usedPercent?: number;
3
+ windowMinutes?: number;
4
+ resetAtMs?: number;
5
+ }
6
+ export interface QuotaCacheEntry {
7
+ updatedAt: number;
8
+ status: number;
9
+ model: string;
10
+ planType?: string;
11
+ primary: QuotaCacheWindow;
12
+ secondary: QuotaCacheWindow;
13
+ }
14
+ export interface QuotaCacheData {
15
+ byAccountId: Record<string, QuotaCacheEntry>;
16
+ byEmail: Record<string, QuotaCacheEntry>;
17
+ }
18
+ /**
19
+ * Get the absolute filesystem path to the quota-cache.json file.
20
+ *
21
+ * The resolved path points to quota-cache.json inside the Codex multi-auth directory.
22
+ * Callers must observe normal filesystem concurrency semantics (no internal locking is provided),
23
+ * and handle platform-specific path behavior (for example, on Windows the file may reside under %APPDATA%).
24
+ * The file can contain sensitive values; redact tokens or secrets before logging or exposing its contents.
25
+ *
26
+ * @returns The absolute path to the quota-cache.json file
27
+ */
28
+ export declare function getQuotaCachePath(): string;
29
+ /**
30
+ * Loads and returns the normalized quota cache from disk.
31
+ *
32
+ * Reads the JSON cache at the configured quota-cache path, validates and normalizes entries,
33
+ * and returns maps keyed by account ID and email. If the file is missing, invalid, or an I/O
34
+ * error occurs, returns empty maps and logs a warning.
35
+ *
36
+ * Notes:
37
+ * - Concurrency: callers should expect concurrent readers and writers; the function performs
38
+ * a best-effort read and does not perform file locking.
39
+ * - Windows: uses standard UTF-8 file reads; caller should ensure the quota-cache path is
40
+ * compatible with Windows path semantics when used on that platform.
41
+ * - Redaction: callers should avoid logging or exposing the file contents; any tokens or
42
+ * sensitive identifiers contained in the cache should be redacted before external reporting.
43
+ *
44
+ * @returns The quota cache as `{ byAccountId, byEmail }` with normalized entries; each map
45
+ * will be empty if the on-disk file is absent, malformed, or could not be read.
46
+ */
47
+ export declare function loadQuotaCache(): Promise<QuotaCacheData>;
48
+ /**
49
+ * Persist the quota cache to the on-disk JSON file used by the multi-auth runtime.
50
+ *
51
+ * Writes a versioned, pretty-printed JSON representation of `data` to the configured
52
+ * quota cache path. Failures are logged and do not throw, so callers should handle
53
+ * eventual consistency or retry as needed.
54
+ *
55
+ * Concurrency: concurrent writers may race and overwrite each other; callers should
56
+ * serialize writes if strong consistency is required.
57
+ *
58
+ * Filesystem notes: Windows path length, permissions, or antivirus locks may cause
59
+ * write failures; such errors are logged rather than thrown.
60
+ *
61
+ * Security: this function does not redact secrets or tokens — callers must ensure
62
+ * `data` contains no sensitive plaintext tokens before calling.
63
+ *
64
+ * @param data - The quota cache data (byAccountId and byEmail maps) to persist; callers
65
+ * should pass normalized QuotaCacheData.
66
+ */
67
+ export declare function saveQuotaCache(data: QuotaCacheData): Promise<void>;
68
+ //# sourceMappingURL=quota-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-cache.d.ts","sourceRoot":"","sources":["../../lib/quota-cache.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC9B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACzC;AAiHD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,CA4B9D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CxE"}
@@ -0,0 +1,224 @@
1
+ import { existsSync, promises as fs } from "node:fs";
2
+ import { basename, join } from "node:path";
3
+ import { logWarn } from "./logger.js";
4
+ import { getCodexMultiAuthDir } from "./runtime-paths.js";
5
+ import { isRecord, sleep } from "./utils.js";
6
+ const QUOTA_CACHE_PATH = join(getCodexMultiAuthDir(), "quota-cache.json");
7
+ const QUOTA_CACHE_LABEL = basename(QUOTA_CACHE_PATH);
8
+ const RETRYABLE_FS_CODES = new Set(["EBUSY", "EPERM"]);
9
+ function isRetryableFsError(error) {
10
+ const code = error?.code;
11
+ return typeof code === "string" && RETRYABLE_FS_CODES.has(code);
12
+ }
13
+ /**
14
+ * Normalizes an unknown value to a finite number.
15
+ *
16
+ * @param value - The value to normalize
17
+ * @returns The input as a finite number, or `undefined` if the value is not a finite number
18
+ */
19
+ function normalizeNumber(value) {
20
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
21
+ }
22
+ /**
23
+ * Produce a normalized QuotaCacheWindow from an arbitrary value.
24
+ *
25
+ * @param value - The raw input to normalize; if not an object, an empty window is returned.
26
+ * @returns A QuotaCacheWindow whose `usedPercent`, `windowMinutes`, and `resetAtMs` are finite numbers or `undefined` when missing/invalid.
27
+ */
28
+ function normalizeWindow(value) {
29
+ if (!isRecord(value))
30
+ return {};
31
+ return {
32
+ usedPercent: normalizeNumber(value.usedPercent),
33
+ windowMinutes: normalizeNumber(value.windowMinutes),
34
+ resetAtMs: normalizeNumber(value.resetAtMs),
35
+ };
36
+ }
37
+ /**
38
+ * Normalize and validate a raw parsed value into a quota cache entry.
39
+ *
40
+ * Produces a QuotaCacheEntry with a trimmed `model`, optional `planType`, and normalized
41
+ * `primary`/`secondary` windows when `updatedAt`, `status`, and `model` are present and valid;
42
+ * returns `null` for any invalid input. This helper is pure (no I/O), safe to call concurrently,
43
+ * and platform-agnostic (works with data read from files on Windows or POSIX). It does not perform
44
+ * token redaction — callers must redact sensitive fields before persisting or logging.
45
+ *
46
+ * @param value - The arbitrary input (typically parsed JSON) to validate and normalize
47
+ * @returns A normalized `QuotaCacheEntry` if validation succeeds, `null` otherwise
48
+ */
49
+ function normalizeEntry(value) {
50
+ if (!isRecord(value))
51
+ return null;
52
+ const updatedAt = normalizeNumber(value.updatedAt);
53
+ const status = normalizeNumber(value.status);
54
+ const model = typeof value.model === "string" ? value.model : "";
55
+ if (typeof updatedAt !== "number" ||
56
+ typeof status !== "number" ||
57
+ model.trim().length === 0) {
58
+ return null;
59
+ }
60
+ return {
61
+ updatedAt,
62
+ status,
63
+ model: model.trim(),
64
+ planType: typeof value.planType === "string" ? value.planType : undefined,
65
+ primary: normalizeWindow(value.primary),
66
+ secondary: normalizeWindow(value.secondary),
67
+ };
68
+ }
69
+ /**
70
+ * Convert a raw parsed value into a map of validated quota cache entries.
71
+ *
72
+ * @param value - Parsed JSON value (typically an object) containing raw entries keyed by identifier; non-objects, empty keys, or invalid entries are ignored.
73
+ * @returns A record mapping valid string keys to normalized `QuotaCacheEntry` objects; malformed entries are omitted.
74
+ *
75
+ * Note: This function is pure and performs no filesystem I/O. Callers are responsible for any filesystem concurrency or Windows-specific behavior when loading/saving the on-disk cache, and for redacting any sensitive tokens before logging or persisting.
76
+ */
77
+ function normalizeEntryMap(value) {
78
+ if (!isRecord(value))
79
+ return {};
80
+ const entries = {};
81
+ for (const [key, raw] of Object.entries(value)) {
82
+ if (typeof key !== "string" || key.trim().length === 0)
83
+ continue;
84
+ const normalized = normalizeEntry(raw);
85
+ if (!normalized)
86
+ continue;
87
+ entries[key] = normalized;
88
+ }
89
+ return entries;
90
+ }
91
+ async function readCacheFileWithRetry(path) {
92
+ let lastError;
93
+ for (let attempt = 0; attempt < 5; attempt += 1) {
94
+ try {
95
+ return await fs.readFile(path, "utf8");
96
+ }
97
+ catch (error) {
98
+ lastError = error;
99
+ if (!isRetryableFsError(error) || attempt >= 4) {
100
+ throw error;
101
+ }
102
+ await sleep(10 * 2 ** attempt);
103
+ }
104
+ }
105
+ throw lastError instanceof Error ? lastError : new Error("quota cache read retry exhausted");
106
+ }
107
+ /**
108
+ * Get the absolute filesystem path to the quota-cache.json file.
109
+ *
110
+ * The resolved path points to quota-cache.json inside the Codex multi-auth directory.
111
+ * Callers must observe normal filesystem concurrency semantics (no internal locking is provided),
112
+ * and handle platform-specific path behavior (for example, on Windows the file may reside under %APPDATA%).
113
+ * The file can contain sensitive values; redact tokens or secrets before logging or exposing its contents.
114
+ *
115
+ * @returns The absolute path to the quota-cache.json file
116
+ */
117
+ export function getQuotaCachePath() {
118
+ return QUOTA_CACHE_PATH;
119
+ }
120
+ /**
121
+ * Loads and returns the normalized quota cache from disk.
122
+ *
123
+ * Reads the JSON cache at the configured quota-cache path, validates and normalizes entries,
124
+ * and returns maps keyed by account ID and email. If the file is missing, invalid, or an I/O
125
+ * error occurs, returns empty maps and logs a warning.
126
+ *
127
+ * Notes:
128
+ * - Concurrency: callers should expect concurrent readers and writers; the function performs
129
+ * a best-effort read and does not perform file locking.
130
+ * - Windows: uses standard UTF-8 file reads; caller should ensure the quota-cache path is
131
+ * compatible with Windows path semantics when used on that platform.
132
+ * - Redaction: callers should avoid logging or exposing the file contents; any tokens or
133
+ * sensitive identifiers contained in the cache should be redacted before external reporting.
134
+ *
135
+ * @returns The quota cache as `{ byAccountId, byEmail }` with normalized entries; each map
136
+ * will be empty if the on-disk file is absent, malformed, or could not be read.
137
+ */
138
+ export async function loadQuotaCache() {
139
+ if (!existsSync(QUOTA_CACHE_PATH)) {
140
+ return { byAccountId: {}, byEmail: {} };
141
+ }
142
+ try {
143
+ const content = await readCacheFileWithRetry(QUOTA_CACHE_PATH);
144
+ const parsed = JSON.parse(content);
145
+ if (!isRecord(parsed)) {
146
+ return { byAccountId: {}, byEmail: {} };
147
+ }
148
+ if (parsed.version !== 1) {
149
+ logWarn(`Quota cache rejected due to version mismatch: ${String(parsed.version)}`);
150
+ return { byAccountId: {}, byEmail: {} };
151
+ }
152
+ return {
153
+ byAccountId: normalizeEntryMap(parsed.byAccountId),
154
+ byEmail: normalizeEntryMap(parsed.byEmail),
155
+ };
156
+ }
157
+ catch (error) {
158
+ logWarn(`Failed to load quota cache from ${QUOTA_CACHE_LABEL}: ${error instanceof Error ? error.message : String(error)}`);
159
+ return { byAccountId: {}, byEmail: {} };
160
+ }
161
+ }
162
+ /**
163
+ * Persist the quota cache to the on-disk JSON file used by the multi-auth runtime.
164
+ *
165
+ * Writes a versioned, pretty-printed JSON representation of `data` to the configured
166
+ * quota cache path. Failures are logged and do not throw, so callers should handle
167
+ * eventual consistency or retry as needed.
168
+ *
169
+ * Concurrency: concurrent writers may race and overwrite each other; callers should
170
+ * serialize writes if strong consistency is required.
171
+ *
172
+ * Filesystem notes: Windows path length, permissions, or antivirus locks may cause
173
+ * write failures; such errors are logged rather than thrown.
174
+ *
175
+ * Security: this function does not redact secrets or tokens — callers must ensure
176
+ * `data` contains no sensitive plaintext tokens before calling.
177
+ *
178
+ * @param data - The quota cache data (byAccountId and byEmail maps) to persist; callers
179
+ * should pass normalized QuotaCacheData.
180
+ */
181
+ export async function saveQuotaCache(data) {
182
+ const payload = {
183
+ version: 1,
184
+ byAccountId: data.byAccountId,
185
+ byEmail: data.byEmail,
186
+ };
187
+ try {
188
+ await fs.mkdir(getCodexMultiAuthDir(), { recursive: true });
189
+ const tempPath = `${QUOTA_CACHE_PATH}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
190
+ await fs.writeFile(tempPath, `${JSON.stringify(payload, null, 2)}\n`, {
191
+ encoding: "utf8",
192
+ mode: 0o600,
193
+ });
194
+ let renamed = false;
195
+ try {
196
+ for (let attempt = 0; attempt < 5; attempt += 1) {
197
+ try {
198
+ await fs.rename(tempPath, QUOTA_CACHE_PATH);
199
+ renamed = true;
200
+ break;
201
+ }
202
+ catch (error) {
203
+ if (!isRetryableFsError(error) || attempt >= 4)
204
+ throw error;
205
+ await sleep(10 * 2 ** attempt);
206
+ }
207
+ }
208
+ }
209
+ finally {
210
+ if (!renamed) {
211
+ try {
212
+ await fs.unlink(tempPath);
213
+ }
214
+ catch {
215
+ // Best effort temp cleanup.
216
+ }
217
+ }
218
+ }
219
+ }
220
+ catch (error) {
221
+ logWarn(`Failed to save quota cache to ${QUOTA_CACHE_LABEL}: ${error instanceof Error ? error.message : String(error)}`);
222
+ }
223
+ }
224
+ //# sourceMappingURL=quota-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-cache.js","sourceRoot":"","sources":["../../lib/quota-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ export interface CodexQuotaWindow {
2
+ usedPercent?: number;
3
+ windowMinutes?: number;
4
+ resetAtMs?: number;
5
+ }
6
+ export interface CodexQuotaSnapshot {
7
+ status: number;
8
+ planType?: string;
9
+ activeLimit?: number;
10
+ primary: CodexQuotaWindow;
11
+ secondary: CodexQuotaWindow;
12
+ model: string;
13
+ }
14
+ /**
15
+ * Produce a single-line human-readable summary of a Codex quota snapshot.
16
+ *
17
+ * This pure, deterministic formatter is safe for concurrent use, performs no
18
+ * filesystem side effects (including on Windows), and never exposes secret
19
+ * tokens or other sensitive values.
20
+ *
21
+ * @param snapshot - The quota snapshot to format
22
+ * @returns A concise, comma-separated summary describing primary and secondary windows, optional plan and active limit, and `rate-limited` when the status is 429
23
+ */
24
+ export declare function formatQuotaSnapshotLine(snapshot: CodexQuotaSnapshot): string;
25
+ export interface ProbeCodexQuotaOptions {
26
+ accountId: string;
27
+ accessToken: string;
28
+ model?: string;
29
+ fallbackModels?: readonly string[];
30
+ timeoutMs?: number;
31
+ }
32
+ /**
33
+ * Probe Codex models sequentially to obtain a quota snapshot for the specified account.
34
+ *
35
+ * Concurrency: models are probed one-at-a-time (no parallel requests).
36
+ * Filesystem: performs no filesystem access and makes no Windows filesystem calls.
37
+ * Security: `accessToken` is sent in request headers and is treated as sensitive; tokens are not persisted or written to disk.
38
+ *
39
+ * @param options - Probe options including:
40
+ * - accountId: account identifier used for Codex requests
41
+ * - accessToken: bearer token for authentication (sensitive)
42
+ * - model: optional preferred model name to probe first
43
+ * - fallbackModels: optional list of fallback model names to try
44
+ * - timeoutMs: optional per-model timeout in milliseconds (bounded between 1000 and 60000; default 15000)
45
+ * @returns The first CodexQuotaSnapshot parsed from response quota headers, augmented with the model that produced it.
46
+ * @throws If no candidate model produces a quota snapshot, throws the last encountered error or a generic failure error.
47
+ */
48
+ export declare function fetchCodexQuotaSnapshot(options: ProbeCodexQuotaOptions): Promise<CodexQuotaSnapshot>;
49
+ //# sourceMappingURL=quota-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-probe.d.ts","sourceRoot":"","sources":["../../lib/quota-probe.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACd;AAiQD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAa5E;AAED,MAAM,WAAW,sBAAsB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,sBAAsB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAsF7B"}