@bitkyc08/opencodex 2.48.0 → 2.49.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 (97) hide show
  1. package/README.md +8 -5
  2. package/SPONSORS.md +1 -1
  3. package/assets/sponsors/orcarouter.png +0 -0
  4. package/assets/sponsors/packycode.png +0 -0
  5. package/gui/dist/assets/index-BoBRSehJ.css +1 -0
  6. package/gui/dist/assets/index-BtyONQrZ.js +115 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/packycode.svg +19 -0
  9. package/gui/dist/provider-icons/qoder.svg +5 -0
  10. package/package.json +5 -3
  11. package/src/adapters/anthropic.ts +31 -16
  12. package/src/adapters/codebuddy/adapter.ts +85 -0
  13. package/src/adapters/codebuddy/profiles.ts +52 -0
  14. package/src/adapters/coding-agent/profile.ts +100 -0
  15. package/src/adapters/coding-agent/protocol.ts +463 -0
  16. package/src/adapters/coding-agent/turn.ts +353 -0
  17. package/src/adapters/google.ts +15 -11
  18. package/src/adapters/mimo-free.ts +3 -0
  19. package/src/adapters/openai-chat.ts +2 -2
  20. package/src/adapters/openai-responses.ts +18 -11
  21. package/src/adapters/qoder/adapter.ts +70 -0
  22. package/src/adapters/qoder/live-models.ts +89 -0
  23. package/src/adapters/qoder/profiles.ts +36 -0
  24. package/src/adapters/registry.ts +12 -0
  25. package/src/adapters/responses-tool-schema.ts +113 -8
  26. package/src/cli/dispatch.ts +2 -0
  27. package/src/cli/doctor.ts +40 -0
  28. package/src/cli/effort.ts +24 -8
  29. package/src/cli/help.ts +2 -0
  30. package/src/cli/index.ts +24 -1
  31. package/src/cli/provider-runtime.ts +2 -1
  32. package/src/cli/registry.ts +2 -2
  33. package/src/cli/system-command.ts +10 -3
  34. package/src/cli/usage-report.ts +9 -5
  35. package/src/codex/account-lifecycle.ts +35 -2
  36. package/src/codex/auth-api.ts +6 -3
  37. package/src/codex/auth-collision.ts +12 -2
  38. package/src/codex/auth-context.ts +75 -7
  39. package/src/codex/catalog/provider-fetch.ts +73 -9
  40. package/src/codex/inject.ts +127 -30
  41. package/src/codex/internal/catalog-writer.ts +3 -0
  42. package/src/codex/journal.ts +61 -12
  43. package/src/codex/model-cache.ts +11 -4
  44. package/src/codex/native-profile-startup.ts +72 -5
  45. package/src/codex/native-profile-store.ts +2 -2
  46. package/src/codex/ocx-compaction-history.ts +226 -0
  47. package/src/codex/project-config-warnings.ts +3 -1
  48. package/src/codex/quota.ts +18 -8
  49. package/src/codex/reserve-availability.ts +21 -5
  50. package/src/codex/runtime.ts +45 -1
  51. package/src/codex/sync.ts +5 -0
  52. package/src/config.ts +1 -0
  53. package/src/generated/compatibility-version.json +126 -74
  54. package/src/images/loop.ts +1 -0
  55. package/src/images/xai-video-client.ts +2 -0
  56. package/src/integrations/registry.ts +1 -0
  57. package/src/lib/process-control.ts +52 -8
  58. package/src/lib/upstream-retry.ts +1 -0
  59. package/src/oauth/chatgpt.ts +83 -0
  60. package/src/oauth/xai.ts +151 -8
  61. package/src/providers/api-key-selection-capture.ts +10 -0
  62. package/src/providers/api-key-selection.ts +2 -7
  63. package/src/providers/caller-authorization.ts +36 -0
  64. package/src/providers/codebuddy-models.ts +184 -0
  65. package/src/providers/derive.ts +5 -0
  66. package/src/providers/free-directory.ts +26 -2
  67. package/src/providers/openai-sidecar.ts +35 -11
  68. package/src/providers/qoder-models.ts +25 -0
  69. package/src/providers/registry.ts +139 -0
  70. package/src/responses/compaction.ts +4 -0
  71. package/src/responses/task-input.ts +21 -1
  72. package/src/router.ts +1 -1
  73. package/src/server/chat-completions.ts +26 -9
  74. package/src/server/claude-messages.ts +12 -2
  75. package/src/server/images.ts +1 -0
  76. package/src/server/management/account-selection-stream.ts +13 -4
  77. package/src/server/management/config-routes.ts +24 -5
  78. package/src/server/management/logs-usage-routes.ts +1 -0
  79. package/src/server/management/native-integration-routes.ts +2 -1
  80. package/src/server/management/provider-routes.ts +24 -0
  81. package/src/server/management-api.ts +14 -0
  82. package/src/server/port-reclaim.ts +11 -26
  83. package/src/server/request-log.ts +6 -0
  84. package/src/server/responses/collaboration.ts +4 -9
  85. package/src/server/responses/core.ts +141 -19
  86. package/src/server/responses/fetch-helpers.ts +18 -7
  87. package/src/server/responses/policy-fallback.ts +12 -0
  88. package/src/service.ts +36 -2
  89. package/src/storage/cleanup.ts +77 -45
  90. package/src/types/config.ts +7 -1
  91. package/src/usage/log.ts +24 -0
  92. package/src/vision/anthropic-describe.ts +1 -0
  93. package/src/web-search/anthropic-executor.ts +1 -0
  94. package/src/web-search/loop.ts +1 -0
  95. package/src/web-search/progress-stream.ts +4 -0
  96. package/gui/dist/assets/index-B5r7LNHN.js +0 -115
  97. package/gui/dist/assets/index-D5SiRo8X.css +0 -1
@@ -86,6 +86,8 @@ export interface PersistedCodexRuntimeState {
86
86
 
87
87
  const PERSIST_FILE = "codex-runtime.json";
88
88
  const CLAMP_PERSIST_FILE = "codex-runtime-clamp.json";
89
+ /** Probe rejection for an absolute candidate whose file is gone. Matched when retiring a dead pin (#4035). */
90
+ const PATH_MISSING_REASON = "path does not exist";
89
91
 
90
92
  function cloneAndDeepFreeze<T>(value: T): DeepReadonly<T> {
91
93
  const clone = (current: unknown): unknown => {
@@ -283,6 +285,31 @@ export function persistCodexRuntime(
283
285
  atomicWriteFile(codexRuntimeStatePath(configDir), `${JSON.stringify(payload, null, 2)}\n`);
284
286
  }
285
287
 
288
+ /**
289
+ * Delete `codex-runtime.json`. Used to retire a pin whose path no longer exists, so a
290
+ * later resolve stops re-probing it (#4035).
291
+ *
292
+ * Invalidates the process resolve memo the same way `persistCodexRuntime` does: the memo
293
+ * folds the persisted `updatedAt` into its key, and a removed file has no stamp to fold.
294
+ */
295
+ export function clearPersistedCodexRuntime(deps: ResolveCodexRuntimeDeps = {}): void {
296
+ const configDir = deps.configDir ?? getConfigDir();
297
+ clearCodexRuntimeResolveCache();
298
+ try {
299
+ unlinkSync(codexRuntimeStatePath(configDir));
300
+ } catch (error) {
301
+ // An already-missing file is the success case: the pin is gone, which is the point.
302
+ // Anything else means the pin SURVIVES and stays authoritative, so every later
303
+ // resolve re-probes the same dead path — #4035 unfixed, silently. Say so once.
304
+ const code = (error as NodeJS.ErrnoException | null)?.code;
305
+ if (code === "ENOENT") return;
306
+ console.warn(
307
+ `[opencodex] Could not remove the stale Codex runtime pin at ${displayCodexRuntimePath(codexRuntimeStatePath(configDir))}`
308
+ + ` (${code ?? "unknown error"}). It will be re-probed until the file is removed.`,
309
+ );
310
+ }
311
+ }
312
+
286
313
  function probeVersion(
287
314
  command: string,
288
315
  deps: ResolveCodexRuntimeDeps,
@@ -290,7 +317,7 @@ function probeVersion(
290
317
  const platform = deps.platform ?? process.platform;
291
318
  if (command.includes("/") || command.includes("\\") || /^[A-Za-z]:/.test(command)) {
292
319
  const exists = deps.existsSync ?? existsSync;
293
- if (!exists(command)) return { ok: false, reason: "path does not exist" };
320
+ if (!exists(command)) return { ok: false, reason: PATH_MISSING_REASON };
294
321
  if (!isSpawnableCodexCandidate(command, platform)) {
295
322
  return { ok: false, reason: "not a spawnable Codex launcher on this platform" };
296
323
  }
@@ -654,6 +681,23 @@ export function resolveAndPersistCodexRuntime(
654
681
  return cloneAndDeepFreeze({ ...result, persistError });
655
682
  }
656
683
  }
684
+ // A pin whose path has vanished must be RETIRED, not merely skipped. A Codex App update
685
+ // replaces the hashed plugin directory the pin names, the probe rejects it with
686
+ // "path does not exist", nothing else resolves, and the selection degrades to `fallback` —
687
+ // which the write guard above declines. The dead entry then survived every later resolve
688
+ // and each one re-probed a path that cannot exist (#4035). Bound narrowly: only when the
689
+ // degraded result is `fallback`, only for the persisted command, and only for the
690
+ // path-does-not-exist rejection, so a present-but-unusable binary is left for the operator.
691
+ else if (result.runtime.source === "fallback" && persistedRuntime?.command) {
692
+ const pinVanished = result.failures.some(
693
+ // Exact comparison, not `sameRuntimeCommand`: that helper lowercases, and on a
694
+ // case-sensitive filesystem `/plugins/Codex` and `/plugins/codex` are different
695
+ // files. A missing lowercase path must not retire a live uppercase pin.
696
+ failure => failure.command.trim() === persistedRuntime.command.trim()
697
+ && failure.reason === PATH_MISSING_REASON,
698
+ );
699
+ if (pinVanished) clearPersistedCodexRuntime(deps);
700
+ }
657
701
  return result;
658
702
  }
659
703
 
package/src/codex/sync.ts CHANGED
@@ -8,6 +8,7 @@ import { summarizeComboCatalogOmissions, type ComboCatalogOmission } from "./cat
8
8
  import { shouldSyncCodexOnStart } from "./desired-state";
9
9
  import { admitCodexWrite, type CodexAdmission } from "./admission";
10
10
  import type { CodexCatalogSyncOptions } from "./catalog/sync";
11
+ import { resetCodexAppServerCatalogStateCache } from "./app-server-processes";
11
12
 
12
13
  export interface CodexSyncResult {
13
14
  /**
@@ -116,6 +117,10 @@ export async function syncModelsToCodex(
116
117
  message: admission.message,
117
118
  };
118
119
  }
120
+ // Config injection is a relevant Codex write even when the catalog bytes are unchanged.
121
+ // Drop cached process evidence before async discovery so a process that appeared since the
122
+ // last read cannot make native-default guidance report active after this sync.
123
+ resetCodexAppServerCatalogStateCache();
119
124
  const p = port ?? config.port ?? 10100;
120
125
  const externalProvider = (deps.currentExternalCodexModelProvider ?? currentExternalCodexModelProvider)();
121
126
 
package/src/config.ts CHANGED
@@ -1189,6 +1189,7 @@ const configSchema = z.object({
1189
1189
  ).optional().catch(undefined),
1190
1190
  codexShimAutoRestore: z.boolean().optional(),
1191
1191
  codexDesktopAuthless: z.boolean().optional().catch(undefined),
1192
+ codexClientCompaction: z.boolean().optional().catch(undefined),
1192
1193
  pausedCodexAccountIds: z.array(z.string().regex(/^[a-zA-Z0-9._-]{1,64}$/)).optional(),
1193
1194
  codexQuotaAutoRefresh: codexQuotaAutoRefreshSchema.optional().catch(undefined),
1194
1195
  codexAccountNamespaces: codexAccountNamespacesSchema.optional(),