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,220 @@
1
+ const DEFAULT_REMAINING_PERCENT_THRESHOLD = 5;
2
+ const DEFAULT_MAX_DEFERRAL_MS = 2 * 60 * 60_000;
3
+ /**
4
+ * Clamp a number to the inclusive integer range [min, max] after flooring.
5
+ *
6
+ * @param value - The input number to be floored and clamped
7
+ * @param min - The inclusive lower bound
8
+ * @param max - The inclusive upper bound
9
+ * @returns The integer result equal to `Math.floor(value)` constrained to the range between `min` and `max`
10
+ */
11
+ function clampInt(value, min, max) {
12
+ return Math.max(min, Math.min(max, Math.floor(value)));
13
+ }
14
+ /**
15
+ * Parses a header value as a finite number and returns it when valid.
16
+ *
17
+ * This function is pure: it has no concurrency or filesystem side effects, does not access the Windows filesystem, and does not perform any token redaction.
18
+ *
19
+ * @param headers - The Headers object to read the header from
20
+ * @param name - The name of the header to parse
21
+ * @returns The parsed finite number from the header, or `undefined` if the header is absent or not a finite number
22
+ */
23
+ function parseFiniteNumberHeader(headers, name) {
24
+ const raw = headers.get(name);
25
+ if (!raw)
26
+ return undefined;
27
+ const parsed = Number(raw);
28
+ return Number.isFinite(parsed) ? parsed : undefined;
29
+ }
30
+ /**
31
+ * Parse an HTTP header value as a base-10 integer.
32
+ *
33
+ * @param headers - The Headers object to read the value from.
34
+ * @param name - The header name to parse.
35
+ * @returns The parsed integer if the header exists and is a finite base-10 integer, `undefined` otherwise.
36
+ */
37
+ function parseFiniteIntHeader(headers, name) {
38
+ const raw = headers.get(name);
39
+ if (!raw)
40
+ return undefined;
41
+ const parsed = Number.parseInt(raw, 10);
42
+ return Number.isFinite(parsed) ? parsed : undefined;
43
+ }
44
+ /**
45
+ * Parse a reset timestamp header for the given prefix and normalize it to milliseconds since the epoch.
46
+ *
47
+ * Interprets `<prefix>-reset-after-seconds` as a relative seconds offset from now, and `<prefix>-reset-at` as
48
+ * either an absolute epoch seconds value or an HTTP-date; returns the corresponding millisecond timestamp or
49
+ * `undefined` when no valid value is present.
50
+ *
51
+ * Concurrency: callers should treat `headers` as an immutable snapshot. Behavior is independent of Windows
52
+ * filesystem semantics. Sensitive header values (tokens) are not logged or persisted by this function.
53
+ *
54
+ * @param headers - The Headers object to read values from.
55
+ * @param prefix - Header name prefix (for example `"x-rate-limit"` to read `"x-rate-limit-reset-at"` or `"x-rate-limit-reset-after-seconds"`).
56
+ * @returns The reset time in milliseconds since epoch, or `undefined` if no valid value is found.
57
+ */
58
+ function parseResetAtMs(headers, prefix, now) {
59
+ const resetAfterSeconds = parseFiniteIntHeader(headers, `${prefix}-reset-after-seconds`);
60
+ if (typeof resetAfterSeconds === "number" && resetAfterSeconds > 0) {
61
+ return now + resetAfterSeconds * 1000;
62
+ }
63
+ const resetAtRaw = headers.get(`${prefix}-reset-at`);
64
+ if (!resetAtRaw)
65
+ return undefined;
66
+ const trimmed = resetAtRaw.trim();
67
+ if (/^\d+$/.test(trimmed)) {
68
+ const parsedNumber = Number.parseInt(trimmed, 10);
69
+ if (Number.isFinite(parsedNumber) && parsedNumber > 0) {
70
+ return parsedNumber < 10_000_000_000 ? parsedNumber * 1000 : parsedNumber;
71
+ }
72
+ }
73
+ const parsedDate = Date.parse(trimmed);
74
+ return Number.isFinite(parsedDate) ? parsedDate : undefined;
75
+ }
76
+ /**
77
+ * Create a quota snapshot from HTTP headers when quota signals are present.
78
+ *
79
+ * Parses primary and secondary used-percent and reset timestamps and produces a snapshot; returns `null` if no quota signals are present.
80
+ *
81
+ * Concurrency: pure and safe for concurrent calls.
82
+ * Filesystem: does not access the filesystem (no Windows-specific behavior).
83
+ * Token handling: does not log or persist header values; callers should redact sensitive headers before logging or storing.
84
+ *
85
+ * @param headers - HTTP headers to read quota signals from; may contain sensitive values
86
+ * @param status - HTTP status code associated with the snapshot
87
+ * @param now - Millisecond epoch used as the snapshot's `updatedAt` timestamp
88
+ * @returns A QuotaSchedulerSnapshot built from available header values, or `null` when no signals are present
89
+ */
90
+ export function readQuotaSchedulerSnapshot(headers, status, now = Date.now()) {
91
+ const primaryPrefix = "x-codex-primary";
92
+ const secondaryPrefix = "x-codex-secondary";
93
+ const primaryUsed = parseFiniteNumberHeader(headers, `${primaryPrefix}-used-percent`);
94
+ const secondaryUsed = parseFiniteNumberHeader(headers, `${secondaryPrefix}-used-percent`);
95
+ const primaryResetAt = parseResetAtMs(headers, primaryPrefix, now);
96
+ const secondaryResetAt = parseResetAtMs(headers, secondaryPrefix, now);
97
+ const hasSignal = typeof primaryUsed === "number" ||
98
+ typeof secondaryUsed === "number" ||
99
+ typeof primaryResetAt === "number" ||
100
+ typeof secondaryResetAt === "number";
101
+ if (!hasSignal)
102
+ return null;
103
+ return {
104
+ status,
105
+ primary: { usedPercent: primaryUsed, resetAtMs: primaryResetAt },
106
+ secondary: { usedPercent: secondaryUsed, resetAtMs: secondaryResetAt },
107
+ updatedAt: now,
108
+ };
109
+ }
110
+ export class PreemptiveQuotaScheduler {
111
+ snapshots = new Map();
112
+ enabled;
113
+ primaryRemainingPercentThreshold;
114
+ secondaryRemainingPercentThreshold;
115
+ maxDeferralMs;
116
+ lastPruneAt = 0;
117
+ constructor(options = {}) {
118
+ this.enabled = true;
119
+ this.primaryRemainingPercentThreshold = DEFAULT_REMAINING_PERCENT_THRESHOLD;
120
+ this.secondaryRemainingPercentThreshold = DEFAULT_REMAINING_PERCENT_THRESHOLD;
121
+ this.maxDeferralMs = DEFAULT_MAX_DEFERRAL_MS;
122
+ this.configure(options);
123
+ }
124
+ configure(options = {}) {
125
+ if (typeof options.enabled === "boolean") {
126
+ this.enabled = options.enabled;
127
+ }
128
+ const legacyUsedPercentThreshold = options.usedPercentThreshold;
129
+ if (typeof legacyUsedPercentThreshold === "number" &&
130
+ Number.isFinite(legacyUsedPercentThreshold)) {
131
+ const clampedUsed = clampInt(legacyUsedPercentThreshold, 0, 100);
132
+ const derivedRemaining = clampInt(100 - clampedUsed, 0, 100);
133
+ this.primaryRemainingPercentThreshold = derivedRemaining;
134
+ this.secondaryRemainingPercentThreshold = derivedRemaining;
135
+ }
136
+ if (typeof options.remainingPercentThresholdPrimary === "number" &&
137
+ Number.isFinite(options.remainingPercentThresholdPrimary)) {
138
+ this.primaryRemainingPercentThreshold = clampInt(options.remainingPercentThresholdPrimary, 0, 100);
139
+ }
140
+ if (typeof options.remainingPercentThresholdSecondary === "number" &&
141
+ Number.isFinite(options.remainingPercentThresholdSecondary)) {
142
+ this.secondaryRemainingPercentThreshold = clampInt(options.remainingPercentThresholdSecondary, 0, 100);
143
+ }
144
+ if (typeof options.maxDeferralMs === "number" && Number.isFinite(options.maxDeferralMs)) {
145
+ this.maxDeferralMs = Math.max(1_000, Math.floor(options.maxDeferralMs));
146
+ }
147
+ }
148
+ maybePrune(now = Date.now()) {
149
+ if (now - this.lastPruneAt < 60_000)
150
+ return;
151
+ this.prune(now);
152
+ this.lastPruneAt = now;
153
+ }
154
+ update(key, snapshot) {
155
+ if (!key)
156
+ return;
157
+ this.maybePrune(snapshot.updatedAt || Date.now());
158
+ this.snapshots.set(key, snapshot);
159
+ }
160
+ markRateLimited(key, retryAfterMs, now = Date.now()) {
161
+ if (!key)
162
+ return;
163
+ const waitMs = Number.isFinite(retryAfterMs) ? Math.max(0, Math.floor(retryAfterMs)) : 0;
164
+ this.snapshots.set(key, {
165
+ status: 429,
166
+ primary: {
167
+ usedPercent: 100,
168
+ resetAtMs: now + waitMs,
169
+ },
170
+ secondary: {},
171
+ updatedAt: now,
172
+ });
173
+ }
174
+ getDeferral(key, now = Date.now()) {
175
+ this.maybePrune(now);
176
+ if (!this.enabled) {
177
+ return { defer: false, waitMs: 0 };
178
+ }
179
+ const snapshot = this.snapshots.get(key);
180
+ if (!snapshot)
181
+ return { defer: false, waitMs: 0 };
182
+ const waitCandidates = [snapshot.primary.resetAtMs, snapshot.secondary.resetAtMs]
183
+ .filter((value) => typeof value === "number" && Number.isFinite(value) && value > now)
184
+ .map((value) => value - now)
185
+ .filter((value) => value > 0);
186
+ const nearestWait = waitCandidates.length > 0 ? Math.min(...waitCandidates) : 0;
187
+ if (snapshot.status === 429 && nearestWait > 0) {
188
+ const bounded = Math.min(nearestWait, this.maxDeferralMs);
189
+ if (bounded > 0) {
190
+ return { defer: true, waitMs: bounded, reason: "rate-limit" };
191
+ }
192
+ }
193
+ const primaryNearExhausted = typeof snapshot.primary.usedPercent === "number" &&
194
+ Number.isFinite(snapshot.primary.usedPercent) &&
195
+ snapshot.primary.usedPercent >= 100 - this.primaryRemainingPercentThreshold;
196
+ const secondaryNearExhausted = typeof snapshot.secondary.usedPercent === "number" &&
197
+ Number.isFinite(snapshot.secondary.usedPercent) &&
198
+ snapshot.secondary.usedPercent >= 100 - this.secondaryRemainingPercentThreshold;
199
+ const nearExhausted = primaryNearExhausted || secondaryNearExhausted;
200
+ if (nearExhausted && nearestWait > 0) {
201
+ const bounded = Math.min(nearestWait, this.maxDeferralMs);
202
+ if (bounded > 0) {
203
+ return { defer: true, waitMs: bounded, reason: "quota-near-exhaustion" };
204
+ }
205
+ }
206
+ return { defer: false, waitMs: 0 };
207
+ }
208
+ prune(now = Date.now()) {
209
+ let removed = 0;
210
+ for (const [key, snapshot] of this.snapshots.entries()) {
211
+ const latestReset = Math.max(snapshot.primary.resetAtMs ?? 0, snapshot.secondary.resetAtMs ?? 0);
212
+ if (latestReset > 0 && latestReset <= now) {
213
+ this.snapshots.delete(key);
214
+ removed += 1;
215
+ }
216
+ }
217
+ return removed;
218
+ }
219
+ }
220
+ //# sourceMappingURL=preemptive-quota-scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preemptive-quota-scheduler.js","sourceRoot":"","sources":["../../lib/preemptive-quota-scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Proactive Token Refresh Module
3
+ *
4
+ * Refreshes OAuth tokens before they expire to prevent auth failures mid-request.
5
+ * Default buffer: 5 minutes before expiry (configurable via tokenRefreshSkewMs).
6
+ *
7
+ * This is a production hardening feature that:
8
+ * - Reduces mid-request auth failures
9
+ * - Improves user experience with seamless token rotation
10
+ * - Works alongside the existing reactive refresh in fetch-helpers
11
+ */
12
+ import type { ManagedAccount } from "./accounts.js";
13
+ import type { TokenResult } from "./types.js";
14
+ /** Default buffer before expiry to trigger proactive refresh (5 minutes) */
15
+ export declare const DEFAULT_PROACTIVE_BUFFER_MS: number;
16
+ /** Minimum buffer to prevent unnecessary refreshes (30 seconds) */
17
+ export declare const MIN_PROACTIVE_BUFFER_MS: number;
18
+ /**
19
+ * Result of a proactive refresh operation.
20
+ */
21
+ export interface ProactiveRefreshResult {
22
+ refreshed: boolean;
23
+ tokenResult?: TokenResult;
24
+ reason: "not_needed" | "no_refresh_token" | "success" | "failed";
25
+ }
26
+ /**
27
+ * Determines if an account's token should be proactively refreshed.
28
+ *
29
+ * @param account - The managed account to check
30
+ * @param bufferMs - Time buffer before expiry to trigger refresh (default: 5 minutes)
31
+ * @returns True if token is approaching expiry and should be refreshed
32
+ */
33
+ export declare function shouldRefreshProactively(account: ManagedAccount, bufferMs?: number): boolean;
34
+ /**
35
+ * Calculates milliseconds until an account's token expires.
36
+ *
37
+ * @param account - The managed account to check
38
+ * @returns Milliseconds until expiry, or Infinity if no expiry set
39
+ */
40
+ export declare function getTimeUntilExpiry(account: ManagedAccount): number;
41
+ /**
42
+ * Proactively refreshes an account's token if it's approaching expiry.
43
+ *
44
+ * @param account - The managed account to refresh
45
+ * @param bufferMs - Time buffer before expiry to trigger refresh
46
+ * @returns Result indicating whether refresh was performed and outcome
47
+ */
48
+ export declare function proactiveRefreshAccount(account: ManagedAccount, bufferMs?: number): Promise<ProactiveRefreshResult>;
49
+ /**
50
+ * Refreshes all accounts that are approaching token expiry.
51
+ *
52
+ * @param accounts - Array of managed accounts to check
53
+ * @param bufferMs - Time buffer before expiry to trigger refresh
54
+ * @returns Map of account index to refresh result
55
+ */
56
+ export declare function refreshExpiringAccounts(accounts: ManagedAccount[], bufferMs?: number): Promise<Map<number, ProactiveRefreshResult>>;
57
+ /**
58
+ * Updates a ManagedAccount with fresh token data from a successful refresh.
59
+ *
60
+ * @param account - The account to update
61
+ * @param result - Successful token refresh result
62
+ */
63
+ export declare function applyRefreshResult(account: ManagedAccount, result: Extract<TokenResult, {
64
+ type: "success";
65
+ }>): void;
66
+ //# sourceMappingURL=proactive-refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proactive-refresh.d.ts","sourceRoot":"","sources":["../../lib/proactive-refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,4EAA4E;AAC5E,eAAO,MAAM,2BAA2B,QAAgB,CAAC;AAEzD,mEAAmE;AACnE,eAAO,MAAM,uBAAuB,QAAY,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,EAAE,YAAY,GAAG,kBAAkB,GAAG,SAAS,GAAG,QAAQ,CAAC;CACjE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,cAAc,EACvB,QAAQ,GAAE,MAAoC,GAC5C,OAAO,CAoBT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAKlE;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,cAAc,EACvB,QAAQ,GAAE,MAAoC,GAC5C,OAAO,CAAC,sBAAsB,CAAC,CAoCjC;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC5C,QAAQ,EAAE,cAAc,EAAE,EAC1B,QAAQ,GAAE,MAAoC,GAC5C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CA0C9C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,GAC/C,IAAI,CAMN"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Proactive Token Refresh Module
3
+ *
4
+ * Refreshes OAuth tokens before they expire to prevent auth failures mid-request.
5
+ * Default buffer: 5 minutes before expiry (configurable via tokenRefreshSkewMs).
6
+ *
7
+ * This is a production hardening feature that:
8
+ * - Reduces mid-request auth failures
9
+ * - Improves user experience with seamless token rotation
10
+ * - Works alongside the existing reactive refresh in fetch-helpers
11
+ */
12
+ import { queuedRefresh } from "./refresh-queue.js";
13
+ import { createLogger } from "./logger.js";
14
+ const log = createLogger("proactive-refresh");
15
+ /** Default buffer before expiry to trigger proactive refresh (5 minutes) */
16
+ export const DEFAULT_PROACTIVE_BUFFER_MS = 5 * 60 * 1000;
17
+ /** Minimum buffer to prevent unnecessary refreshes (30 seconds) */
18
+ export const MIN_PROACTIVE_BUFFER_MS = 30 * 1000;
19
+ /**
20
+ * Determines if an account's token should be proactively refreshed.
21
+ *
22
+ * @param account - The managed account to check
23
+ * @param bufferMs - Time buffer before expiry to trigger refresh (default: 5 minutes)
24
+ * @returns True if token is approaching expiry and should be refreshed
25
+ */
26
+ export function shouldRefreshProactively(account, bufferMs = DEFAULT_PROACTIVE_BUFFER_MS) {
27
+ // No expiry set - can't determine if refresh is needed
28
+ if (account.expires === undefined) {
29
+ return false;
30
+ }
31
+ // No access token - definitely needs refresh
32
+ if (!account.access) {
33
+ return true;
34
+ }
35
+ // Clamp buffer to minimum
36
+ const safeBufferMs = Math.max(MIN_PROACTIVE_BUFFER_MS, bufferMs);
37
+ // Check if token expires within buffer window
38
+ const now = Date.now();
39
+ const expiresAt = account.expires;
40
+ const refreshThreshold = expiresAt - safeBufferMs;
41
+ return now >= refreshThreshold;
42
+ }
43
+ /**
44
+ * Calculates milliseconds until an account's token expires.
45
+ *
46
+ * @param account - The managed account to check
47
+ * @returns Milliseconds until expiry, or Infinity if no expiry set
48
+ */
49
+ export function getTimeUntilExpiry(account) {
50
+ if (account.expires === undefined) {
51
+ return Infinity;
52
+ }
53
+ return Math.max(0, account.expires - Date.now());
54
+ }
55
+ /**
56
+ * Proactively refreshes an account's token if it's approaching expiry.
57
+ *
58
+ * @param account - The managed account to refresh
59
+ * @param bufferMs - Time buffer before expiry to trigger refresh
60
+ * @returns Result indicating whether refresh was performed and outcome
61
+ */
62
+ export async function proactiveRefreshAccount(account, bufferMs = DEFAULT_PROACTIVE_BUFFER_MS) {
63
+ if (!shouldRefreshProactively(account, bufferMs)) {
64
+ return { refreshed: false, reason: "not_needed" };
65
+ }
66
+ if (!account.refreshToken) {
67
+ log.warn("Cannot proactively refresh account without refresh token", {
68
+ accountIndex: account.index,
69
+ });
70
+ return { refreshed: false, reason: "no_refresh_token" };
71
+ }
72
+ const timeUntilExpiry = getTimeUntilExpiry(account);
73
+ log.info("Proactively refreshing token", {
74
+ accountIndex: account.index,
75
+ email: account.email,
76
+ expiresInMs: timeUntilExpiry,
77
+ expiresInMinutes: Math.round(timeUntilExpiry / 60000),
78
+ });
79
+ const result = await queuedRefresh(account.refreshToken);
80
+ if (result.type === "success") {
81
+ log.info("Proactive refresh succeeded", {
82
+ accountIndex: account.index,
83
+ email: account.email,
84
+ });
85
+ return { refreshed: true, tokenResult: result, reason: "success" };
86
+ }
87
+ log.warn("Proactive refresh failed", {
88
+ accountIndex: account.index,
89
+ email: account.email,
90
+ failureReason: result.reason,
91
+ });
92
+ return { refreshed: true, tokenResult: result, reason: "failed" };
93
+ }
94
+ /**
95
+ * Refreshes all accounts that are approaching token expiry.
96
+ *
97
+ * @param accounts - Array of managed accounts to check
98
+ * @param bufferMs - Time buffer before expiry to trigger refresh
99
+ * @returns Map of account index to refresh result
100
+ */
101
+ export async function refreshExpiringAccounts(accounts, bufferMs = DEFAULT_PROACTIVE_BUFFER_MS) {
102
+ const results = new Map();
103
+ const accountsToRefresh = accounts.filter((a) => shouldRefreshProactively(a, bufferMs));
104
+ if (accountsToRefresh.length === 0) {
105
+ log.debug("No accounts need proactive refresh");
106
+ return results;
107
+ }
108
+ log.info(`Proactively refreshing ${accountsToRefresh.length} account(s)`);
109
+ // Refresh in parallel for efficiency
110
+ const refreshPromises = accountsToRefresh.map(async (account) => {
111
+ const result = await proactiveRefreshAccount(account, bufferMs);
112
+ return { index: account.index, result };
113
+ });
114
+ const outcomes = await Promise.all(refreshPromises);
115
+ for (const { index, result } of outcomes) {
116
+ results.set(index, result);
117
+ }
118
+ // Log summary
119
+ const succeeded = Array.from(results.values()).filter((r) => r.reason === "success").length;
120
+ const failed = Array.from(results.values()).filter((r) => r.reason === "failed").length;
121
+ if (succeeded > 0 || failed > 0) {
122
+ log.info("Proactive refresh complete", {
123
+ total: accountsToRefresh.length,
124
+ succeeded,
125
+ failed,
126
+ });
127
+ }
128
+ return results;
129
+ }
130
+ /**
131
+ * Updates a ManagedAccount with fresh token data from a successful refresh.
132
+ *
133
+ * @param account - The account to update
134
+ * @param result - Successful token refresh result
135
+ */
136
+ export function applyRefreshResult(account, result) {
137
+ account.access = result.access;
138
+ account.expires = result.expires;
139
+ if (result.refresh !== account.refreshToken) {
140
+ account.refreshToken = result.refresh;
141
+ }
142
+ }
143
+ //# sourceMappingURL=proactive-refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proactive-refresh.js","sourceRoot":"","sources":["../../lib/proactive-refresh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Codex-OpenCode Bridge Prompt
3
+ *
4
+ * This prompt bridges Codex CLI instructions to the OpenCode environment.
5
+ * It incorporates critical tool mappings, available tools list, substitution rules,
6
+ * and verification checklist to ensure proper tool usage.
7
+ *
8
+ * Token Count: ~450 tokens (~90% reduction vs full OpenCode prompt)
9
+ */
10
+ export declare const CODEX_OPENCODE_BRIDGE = "# Codex Running in OpenCode\n\nYou are running Codex through OpenCode, an open-source terminal coding assistant. OpenCode provides specific tools to help you work efficiently.\n\n## CRITICAL: Tool Usage\n\n<critical_rule priority=\"0\">\napply_patch/applyPatch are Codex names, but OpenCode tool names vary by version.\n- Inspect the actual tool list before editing.\n- If `edit` exists: use `edit` for precise in-place string replacements and hashline edits.\n- If `edit` is absent and `apply_patch` exists: use `apply_patch` for those precise/hashline edits in this plugin.\n- For diff-style or multi-line structural edits: use `patch` if available, otherwise use `apply_patch`.\n- In this plugin, `edit` / `apply_patch` also support hashline refs (`lineRef`, `endLineRef`, `operation`, `content`)\n</critical_rule>\n\n<critical_rule priority=\"0\">\nUPDATE_PLAN DOES NOT EXIST -> USE \"todowrite\" INSTEAD\n- NEVER use: update_plan, updatePlan, read_plan, readPlan\n- ALWAYS use: todowrite for task/plan updates, todoread to read plans\n- Before plan operations: Verify you're using \"todowrite\", NOT \"update_plan\"\n</critical_rule>\n\n## Available OpenCode Tools\n\n**File Operations:**\n- `write` - Create new files\n - Overwriting existing files requires a prior Read in this session; default to ASCII unless the file already uses Unicode.\n- `edit` - Modify existing files with string replacement (version-dependent)\n - Requires a prior Read in this session; preserve exact indentation; ensure `oldString` uniquely matches or use `replaceAll`; edit fails if ambiguous or missing.\n - Never pass unresolved template placeholders in `oldString` (e.g. `${TARGET_SNIPPET}`); `oldString` must be literal text copied from the current file.\n - For complex multi-line changes: break into multiple sequential edit calls, each with unique oldString context.\n- `apply_patch` - May be the edit/patch tool name in newer OpenCode builds (version-dependent)\n - In this plugin, `apply_patch` also accepts hashline edit args (`path`, `lineRef`, `endLineRef`, `operation`, `content`) when `edit` is not available.\n- `hashline_read` - Read file with hashline refs (`L<line>#<hash>`) for deterministic edits\n- `patch` - Apply diff-style patches for multi-line updates (version-dependent)\n- `read` - Read file contents\n\nNote: Tool naming is version-dependent. If `edit` is unavailable but `apply_patch` exists, use `apply_patch`.\n\nWhen available, prefer hashline workflow for reliability:\n1. Call `hashline_read` for target file and capture refs.\n2. Call `edit` or `apply_patch` with `lineRef` (and optional `endLineRef`) plus `operation` and `content`.\n3. Use legacy `oldString` / `newString` only when hashline refs are unavailable, and only with literal file text (no template placeholders).\n\n**Search/Discovery:**\n- `grep` - Search file contents (tool, not bash grep); use `include` to filter patterns; set `path` only when not searching workspace root; for cross-file match counts use bash with `rg`.\n- `glob` - Find files by pattern; defaults to workspace cwd unless `path` is set.\n- `list` - List directories (requires absolute paths)\n\n**Execution:**\n- `bash` - Run shell commands\n - No workdir parameter; do not include it in tool calls.\n - Always include a short description for the command.\n - Do not use cd; use absolute paths in commands.\n - Quote paths containing spaces with double quotes.\n - Chain multiple commands with ';' or '&&'; avoid newlines.\n - Use Grep/Glob tools for searches; only use bash with `rg` when you need counts or advanced features.\n - Do not use `ls`/`cat` in bash; use `list`/`read` tools instead.\n - For deletions (rm), verify by listing parent dir with `list`.\n\n**Network:**\n- `webfetch` - Fetch web content\n - Use fully-formed URLs (http/https; http auto-upgrades to https).\n - Always set `format` to one of: text | markdown | html; prefer markdown unless otherwise required.\n - Read-only; short cache window.\n\n**Task Management:**\n- `todowrite` - Manage tasks/plans (REPLACES update_plan)\n- `todoread` - Read current plan\n\n## Substitution Rules\n\nBase instruction says: You MUST use instead:\napply_patch -> patch (preferred if available), otherwise edit/apply_patch based on actual tool list\nupdate_plan -> todowrite\nread_plan -> todoread\n\n**Path Usage:** Use per-tool conventions to avoid conflicts:\n- Tool calls: `read`, `edit`, `write`, `list` require absolute paths.\n- Searches: `grep`/`glob` default to the workspace cwd; prefer relative include patterns; set `path` only when a different root is needed.\n- Presentation: In assistant messages, show workspace-relative paths; use absolute paths only inside tool calls.\n- Tool schema overrides general path preferences-do not convert required absolute paths to relative.\n\n## Verification Checklist\n\nBefore file/plan modifications:\n1. Am I using the actual available edit tool name (`edit`, `patch`, or `apply_patch`)?\n2. Am I using \"todowrite\" NOT \"update_plan\"?\n3. Is this tool in the approved list above?\n4. Am I following each tool's path requirements?\n\nIf ANY answer is NO -> STOP and correct before proceeding.\n\n## OpenCode Working Style\n\n**Communication:**\n- Send brief preambles (8-12 words) before tool calls, building on prior context\n- Provide progress updates during longer tasks\n\n**Execution:**\n- Keep working autonomously until query is fully resolved before yielding\n- Don't return to user with partial solutions\n\n**Code Approach:**\n- New projects: Be ambitious and creative\n- Existing codebases: Surgical precision - modify only what's requested unless explicitly instructed to do otherwise\n\n**Testing:**\n- If tests exist: Start specific to your changes, then broader validation\n\n## Advanced Tools\n\n**Task Tool (Sub-Agents):**\n- Use the Task tool (functions.task) to launch sub-agents\n- Check the Task tool description for current agent types and their capabilities\n- Useful for complex analysis, specialized workflows, or tasks requiring isolated context\n- The agent list is dynamically generated - refer to tool schema for available agents\n\n**Parallelization:**\n- When multiple independent tool calls are needed, use multi_tool_use.parallel to run them concurrently.\n- Reserve sequential calls for ordered or data-dependent steps.\n\n**MCP Tools:**\n- Model Context Protocol servers provide additional capabilities\n- MCP tools are prefixed: `mcp__<server-name>__<tool-name>`\n- Check your available tools for MCP integrations\n- Use when the tool's functionality matches your task needs\n\n## What Remains from Codex\n \nSandbox policies, approval mechanisms, final answer formatting, git commit protocols, and file reference formats all follow Codex instructions. In approval policy \"never\", never request escalations.\n\n## Approvals & Safety\n- Assume workspace-write filesystem, network enabled, approval on-failure unless explicitly stated otherwise.\n- When a command fails due to sandboxing or permissions, retry with escalated permissions if allowed by policy, including a one-line justification.\n- Treat destructive commands (e.g., `rm`, `git reset --hard`) as requiring explicit user request or approval.\n- Never run `git reset --hard`, `git checkout --`, or force deletes unless the user explicitly asked for that exact action.\n- `request_user_input` is Plan-mode only; do not call it in Default mode.\n- When uncertain, prefer non-destructive verification first (e.g., confirm file existence with `list`, then delete with `bash`).";
11
+ export interface CodexOpenCodeBridgeMeta {
12
+ estimatedTokens: number;
13
+ reductionVsCurrent: string;
14
+ reductionVsToolRemap: string;
15
+ protects: string[];
16
+ omits: string[];
17
+ }
18
+ export declare const CODEX_OPENCODE_BRIDGE_META: CodexOpenCodeBridgeMeta;
19
+ //# sourceMappingURL=codex-opencode-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-opencode-bridge.d.ts","sourceRoot":"","sources":["../../../lib/prompts/codex-opencode-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,qBAAqB,q8OA0ImG,CAAC;AAEtI,MAAM,WAAW,uBAAuB;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,eAAO,MAAM,0BAA0B,EAAE,uBAmBxC,CAAC"}