@bitkyc08/opencodex 2.7.43-preview.20260728 → 2.8.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 (173) hide show
  1. package/README.md +8 -1
  2. package/bin/ocx.mjs +47 -22
  3. package/gui/dist/assets/index-BDjpkcRN.js +67 -0
  4. package/gui/dist/assets/index-BHsKRFh9.css +1 -0
  5. package/gui/dist/index.html +2 -2
  6. package/package.json +1 -1
  7. package/src/AGENTS.md +28 -0
  8. package/src/adapters/anthropic.ts +15 -6
  9. package/src/adapters/cursor/discovery.ts +4 -1
  10. package/src/adapters/cursor/effort-map.ts +3 -0
  11. package/src/adapters/cursor/native-exec-shell.ts +18 -6
  12. package/src/adapters/cursor/protobuf-events.ts +24 -2
  13. package/src/adapters/cursor/protobuf-request.ts +1 -2
  14. package/src/adapters/cursor/tool-definitions.ts +68 -29
  15. package/src/adapters/google-wire-compiler.ts +4 -0
  16. package/src/adapters/google.ts +128 -2
  17. package/src/adapters/identity.ts +12 -2
  18. package/src/adapters/kiro.ts +64 -7
  19. package/src/adapters/mimo-free.ts +2 -0
  20. package/src/adapters/openai-responses.ts +246 -59
  21. package/src/claude/agents-inject.ts +5 -0
  22. package/src/claude/alias.ts +94 -14
  23. package/src/claude/inbound.ts +26 -9
  24. package/src/claude/outbound.ts +6 -3
  25. package/src/cli/account-auth.ts +1 -1
  26. package/src/cli/agent-driven.ts +37 -0
  27. package/src/cli/catalog-prewarm.ts +24 -0
  28. package/src/cli/claude.ts +35 -10
  29. package/src/cli/doctor.ts +71 -19
  30. package/src/cli/help.ts +42 -6
  31. package/src/cli/index.ts +93 -19
  32. package/src/cli/interactive-confirm.ts +133 -0
  33. package/src/cli/opencode.ts +701 -0
  34. package/src/cli/provider-runtime.ts +3 -0
  35. package/src/cli/provider.ts +31 -10
  36. package/src/cli/star-prompt.ts +79 -18
  37. package/src/cli/status.ts +47 -13
  38. package/src/cli/v2.ts +10 -1
  39. package/src/codex/account-id.ts +34 -0
  40. package/src/codex/account-lifecycle.ts +4 -1
  41. package/src/codex/account-namespace-match.ts +63 -0
  42. package/src/codex/account-namespaces.ts +149 -0
  43. package/src/codex/account-pause.ts +20 -0
  44. package/src/codex/account-store.ts +2 -0
  45. package/src/codex/account-usability.ts +6 -1
  46. package/src/codex/app-server-processes.ts +511 -0
  47. package/src/codex/auth-api.ts +293 -34
  48. package/src/codex/auth-collision.ts +2 -1
  49. package/src/codex/auth-context.ts +60 -17
  50. package/src/codex/catalog/bundled.ts +9 -2
  51. package/src/codex/catalog/parsing.ts +42 -2
  52. package/src/codex/catalog/provider-fetch.ts +264 -70
  53. package/src/codex/catalog/sync.ts +45 -8
  54. package/src/codex/catalog.ts +2 -2
  55. package/src/codex/features.ts +524 -5
  56. package/src/codex/history-provider.ts +145 -1
  57. package/src/codex/inject.ts +114 -14
  58. package/src/codex/main-account.ts +2 -8
  59. package/src/codex/pool-rotation.ts +186 -0
  60. package/src/codex/quota.ts +92 -2
  61. package/src/codex/routing.ts +695 -106
  62. package/src/codex/runtime.ts +10 -1
  63. package/src/codex/shim.ts +4 -1
  64. package/src/codex/subagent-defaults.ts +550 -0
  65. package/src/codex/subagent-model-fallback.ts +2 -0
  66. package/src/codex/sync.ts +3 -0
  67. package/src/config.ts +574 -25
  68. package/src/generated/jawcode-model-metadata.ts +12 -12
  69. package/src/github/star-state.ts +191 -0
  70. package/src/images/artifacts.ts +516 -0
  71. package/src/images/fulfill-video.ts +163 -0
  72. package/src/images/fulfill.ts +111 -0
  73. package/src/images/index.ts +4 -0
  74. package/src/images/loop.ts +789 -0
  75. package/src/images/plan.ts +133 -0
  76. package/src/images/synthetic-tool.ts +133 -0
  77. package/src/images/types.ts +41 -0
  78. package/src/images/xai-client.ts +141 -0
  79. package/src/images/xai-video-client.ts +163 -0
  80. package/src/lib/admin-secrets.ts +25 -0
  81. package/src/lib/bun-binary-validator.d.mts +3 -0
  82. package/src/lib/bun-binary-validator.mjs +18 -0
  83. package/src/lib/bun-runtime.ts +6 -20
  84. package/src/lib/config-ownership.ts +327 -0
  85. package/src/lib/crash-guard.ts +2 -0
  86. package/src/lib/destination-policy.ts +132 -7
  87. package/src/lib/pinned-http.ts +151 -0
  88. package/src/lib/process-control.ts +2 -2
  89. package/src/lib/provider-outbound.ts +167 -0
  90. package/src/lib/provider-url.ts +14 -0
  91. package/src/lib/proxy-env.ts +18 -0
  92. package/src/lib/shadow-call.ts +30 -0
  93. package/src/lib/test-home-guard.ts +90 -0
  94. package/src/lib/win-exec.ts +12 -2
  95. package/src/lib/windows-elevation.ts +81 -3
  96. package/src/lib/windows-secret-acl.ts +189 -12
  97. package/src/lib/winsw.ts +2 -0
  98. package/src/oauth/anthropic-routing.ts +570 -0
  99. package/src/oauth/health.ts +6 -0
  100. package/src/oauth/index.ts +310 -75
  101. package/src/oauth/key-providers.ts +38 -8
  102. package/src/oauth/kimi.ts +2 -0
  103. package/src/oauth/kiro-credentials.ts +373 -12
  104. package/src/oauth/kiro.ts +424 -43
  105. package/src/oauth/login-cli.ts +33 -6
  106. package/src/oauth/store.ts +56 -4
  107. package/src/oauth/types.ts +11 -0
  108. package/src/providers/alibaba-region-migration.ts +16 -3
  109. package/src/providers/antigravity-models.ts +3 -0
  110. package/src/providers/api-keys.ts +13 -6
  111. package/src/providers/derive.ts +8 -2
  112. package/src/providers/key-failover.ts +24 -4
  113. package/src/providers/model-discovery.ts +356 -0
  114. package/src/providers/quota.ts +233 -29
  115. package/src/providers/registry.ts +125 -3
  116. package/src/responses/parser.ts +11 -0
  117. package/src/responses/state.ts +22 -8
  118. package/src/responses/tool-groups.ts +19 -0
  119. package/src/router.ts +19 -7
  120. package/src/server/auth-cors.ts +114 -24
  121. package/src/server/claude-messages.ts +8 -1
  122. package/src/server/gui-static.ts +30 -6
  123. package/src/server/images.ts +303 -9
  124. package/src/server/index.ts +77 -9
  125. package/src/server/lifecycle.ts +25 -1
  126. package/src/server/live.ts +75 -25
  127. package/src/server/management/agent-settings-routes.ts +106 -8
  128. package/src/server/management/combo-routes.ts +7 -0
  129. package/src/server/management/config-routes.ts +22 -7
  130. package/src/server/management/context.ts +11 -1
  131. package/src/server/management/logs-usage-routes.ts +167 -3
  132. package/src/server/management/model-routes.ts +46 -13
  133. package/src/server/management/oauth-account-routes.ts +163 -17
  134. package/src/server/management/provider-routes.ts +73 -10
  135. package/src/server/management/shared.ts +2 -2
  136. package/src/server/management/sidebar-routes.ts +39 -0
  137. package/src/server/management/system-restart.ts +172 -0
  138. package/src/server/management/system-routes.ts +33 -10
  139. package/src/server/management-api.ts +5 -3
  140. package/src/server/management-auth.ts +216 -0
  141. package/src/server/proxy-liveness.ts +14 -3
  142. package/src/server/responses/compact.ts +21 -13
  143. package/src/server/responses/core.ts +614 -172
  144. package/src/server/responses/upstream-error.ts +48 -0
  145. package/src/server/responses-image-gen-repair.ts +118 -0
  146. package/src/server/responses-item-id-repair.ts +10 -85
  147. package/src/server/sse-payload-rewrite.ts +116 -0
  148. package/src/server/startup-action-control.ts +30 -14
  149. package/src/server/system-env.ts +28 -10
  150. package/src/service.ts +284 -19
  151. package/src/storage/cleanup-job.ts +57 -0
  152. package/src/storage/cleanup.ts +1504 -28
  153. package/src/storage/policy-job.ts +387 -0
  154. package/src/storage/policy-scheduler.ts +40 -0
  155. package/src/storage/policy-worker.ts +53 -0
  156. package/src/storage/policy.ts +522 -0
  157. package/src/storage/restore-job.ts +253 -0
  158. package/src/storage/restore-worker.ts +52 -0
  159. package/src/storage/storage-mutation-coordinator.ts +109 -0
  160. package/src/storage/worker-lifecycle.ts +81 -0
  161. package/src/tray/windows.ts +34 -4
  162. package/src/types.ts +107 -1
  163. package/src/update/badge.ts +72 -0
  164. package/src/update/index.ts +36 -18
  165. package/src/update/job.ts +111 -16
  166. package/src/update/npm-invocation.d.mts +23 -0
  167. package/src/update/npm-invocation.mjs +94 -0
  168. package/src/usage/debug.ts +2 -0
  169. package/src/usage/expected-prices.ts +6 -5
  170. package/src/usage/log.ts +12 -0
  171. package/src/web-search/loop.ts +57 -16
  172. package/gui/dist/assets/index-CjKFJHSC.js +0 -65
  173. package/gui/dist/assets/index-DfVGuN88.css +0 -1
@@ -1,3 +1,7 @@
1
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { atomicWriteFile, getConfigDir } from "../config";
4
+
1
5
  export type StoredAccountQuota = {
2
6
  weeklyPercent?: number;
3
7
  monthlyPercent?: number;
@@ -7,6 +11,20 @@ export type StoredAccountQuota = {
7
11
  updatedAt: number;
8
12
  };
9
13
 
14
+ /** Disk snapshot under OPENCODEX_HOME — usage percents only (no emails/tokens). */
15
+ const QUOTA_CACHE_FILENAME = "codex-quota-cache.json";
16
+ /** Keep last-known bars across restarts; WHAM still refreshes on TTL in live/prime paths. */
17
+ const QUOTA_DISK_MAX_AGE_MS = 6 * 60 * 60_000;
18
+ const QUOTA_PERSIST_DEBOUNCE_MS = 250;
19
+
20
+ type QuotaDiskFile = {
21
+ version: 1;
22
+ quotas: Record<string, StoredAccountQuota>;
23
+ };
24
+
25
+ let diskHydrated = false;
26
+ let persistTimer: ReturnType<typeof setTimeout> | null = null;
27
+
10
28
  export type WhamUsageResponse = {
11
29
  email?: string | null;
12
30
  plan_type?: string | null;
@@ -33,6 +51,21 @@ const MONTHLY_WINDOW_MIN_MINUTES = MONTHLY_WINDOW_MIN_SECONDS / 60;
33
51
  const accountQuota = new Map<string, StoredAccountQuota>();
34
52
 
35
53
  export const CODEX_UNKNOWN_USAGE_SCORE = 100;
54
+ export const CODEX_EXHAUSTED_USAGE_PERCENT = 100;
55
+
56
+ export function isCodexQuotaExhausted(
57
+ quota: Pick<StoredAccountQuota, "weeklyPercent" | "monthlyPercent"> | null,
58
+ plan?: string | null,
59
+ ): boolean {
60
+ if (!quota) return false;
61
+ const normalizedPlan = plan?.trim().toLowerCase();
62
+ const values = normalizedPlan === "go" || normalizedPlan === "free"
63
+ ? [quota.monthlyPercent]
64
+ : [quota.weeklyPercent, quota.monthlyPercent];
65
+ return values.some(value => typeof value === "number"
66
+ && Number.isFinite(value)
67
+ && value >= CODEX_EXHAUSTED_USAGE_PERCENT);
68
+ }
36
69
 
37
70
  export function normalizeUsagePercent(value: unknown): number | undefined {
38
71
  const numeric = typeof value === "number"
@@ -105,6 +138,7 @@ export function setAccountQuotaFromParsed(
105
138
  if (existing?.monthlyResetAt !== undefined) next.monthlyResetAt = existing.monthlyResetAt;
106
139
  next.resetCredits = quota.resetCredits;
107
140
  accountQuota.set(accountId, next);
141
+ schedulePersistAccountQuotas();
108
142
  return;
109
143
  }
110
144
 
@@ -130,6 +164,7 @@ export function setAccountQuotaFromParsed(
130
164
  else if (existing?.resetCredits !== undefined) next.resetCredits = existing.resetCredits;
131
165
 
132
166
  accountQuota.set(accountId, next);
167
+ schedulePersistAccountQuotas();
133
168
  }
134
169
 
135
170
  export function parseUpstreamQuotaHeaders(headers: Headers): Omit<StoredAccountQuota, "updatedAt"> | null {
@@ -220,19 +255,74 @@ export function updateAccountQuota(
220
255
  if (resetCredits !== undefined) quota.resetCredits = resetCredits;
221
256
 
222
257
  accountQuota.set(accountId, quota);
258
+ schedulePersistAccountQuotas();
259
+ }
260
+
261
+ function hydrateAccountQuotasFromDisk(): void {
262
+ if (diskHydrated) return;
263
+ diskHydrated = true;
264
+ try {
265
+ const path = join(getConfigDir(), QUOTA_CACHE_FILENAME);
266
+ if (!existsSync(path)) return;
267
+ const raw = readFileSync(path, "utf8");
268
+ const parsed = JSON.parse(raw) as QuotaDiskFile;
269
+ if (!parsed || parsed.version !== 1 || !parsed.quotas || typeof parsed.quotas !== "object") return;
270
+ const now = Date.now();
271
+ for (const [accountId, quota] of Object.entries(parsed.quotas)) {
272
+ if (!quota || typeof quota !== "object" || typeof quota.updatedAt !== "number") continue;
273
+ if (now - quota.updatedAt > QUOTA_DISK_MAX_AGE_MS) continue;
274
+ if (!accountQuota.has(accountId)) accountQuota.set(accountId, quota);
275
+ }
276
+ } catch {
277
+ // Corrupt/missing cache must never block routing or the dashboard.
278
+ }
279
+ }
280
+
281
+ function schedulePersistAccountQuotas(): void {
282
+ if (persistTimer) clearTimeout(persistTimer);
283
+ persistTimer = setTimeout(() => {
284
+ persistTimer = null;
285
+ try {
286
+ const quotas: Record<string, StoredAccountQuota> = {};
287
+ for (const [accountId, quota] of accountQuota.entries()) {
288
+ quotas[accountId] = quota;
289
+ }
290
+ const body: QuotaDiskFile = { version: 1, quotas };
291
+ atomicWriteFile(join(getConfigDir(), QUOTA_CACHE_FILENAME), `${JSON.stringify(body)}\n`);
292
+ } catch {
293
+ // Best-effort persistence only.
294
+ }
295
+ }, QUOTA_PERSIST_DEBOUNCE_MS);
223
296
  }
224
297
 
225
298
  export function getAccountQuota(accountId: string): StoredAccountQuota | null {
299
+ hydrateAccountQuotasFromDisk();
226
300
  return accountQuota.get(accountId) ?? null;
227
301
  }
228
302
 
229
303
  export function listAccountQuotas(): IterableIterator<[string, StoredAccountQuota]> {
304
+ hydrateAccountQuotasFromDisk();
230
305
  return accountQuota.entries();
231
306
  }
232
307
 
233
308
  export function clearAccountQuota(accountId?: string): void {
234
- if (accountId) accountQuota.delete(accountId);
235
- else accountQuota.clear();
309
+ if (accountId) {
310
+ accountQuota.delete(accountId);
311
+ schedulePersistAccountQuotas();
312
+ return;
313
+ }
314
+ accountQuota.clear();
315
+ diskHydrated = false;
316
+ if (persistTimer) {
317
+ clearTimeout(persistTimer);
318
+ persistTimer = null;
319
+ }
320
+ try {
321
+ const path = join(getConfigDir(), QUOTA_CACHE_FILENAME);
322
+ if (existsSync(path)) unlinkSync(path);
323
+ } catch {
324
+ // Best-effort; memory is already cleared.
325
+ }
236
326
  }
237
327
 
238
328
  export function parseUsageQuota(data: WhamUsageResponse): Omit<StoredAccountQuota, "updatedAt"> | null {