@bitkyc08/opencodex 2.10.2 → 2.11.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 (121) hide show
  1. package/README.md +31 -0
  2. package/bin/ocx.mjs +10 -0
  3. package/gui/dist/assets/index-Bk-PN-70.css +1 -0
  4. package/gui/dist/assets/index-BynIEIV-.js +70 -0
  5. package/gui/dist/index.html +2 -2
  6. package/package.json +4 -2
  7. package/src/adapters/cursor/effort-map.ts +11 -0
  8. package/src/adapters/cursor/live-transport.ts +11 -0
  9. package/src/adapters/cursor/native-exec-fs.ts +9 -6
  10. package/src/adapters/cursor/native-exec.ts +4 -2
  11. package/src/adapters/cursor/protobuf-events.ts +176 -4
  12. package/src/adapters/cursor/request-builder.ts +15 -4
  13. package/src/adapters/cursor/tool-definitions.ts +118 -2
  14. package/src/adapters/google.ts +15 -5
  15. package/src/adapters/openai-chat.ts +24 -2
  16. package/src/adapters/openai-responses.ts +2 -1
  17. package/src/bridge.ts +9 -5
  18. package/src/chat/outbound.ts +4 -3
  19. package/src/claude/desktop-3p.ts +222 -2
  20. package/src/claude/outbound.ts +15 -6
  21. package/src/cli/account-api.ts +4 -0
  22. package/src/cli/account-extended.ts +112 -0
  23. package/src/cli/account.ts +23 -6
  24. package/src/cli/claude-desktop.ts +26 -3
  25. package/src/cli/config-command.ts +9 -0
  26. package/src/cli/help.ts +18 -2
  27. package/src/cli/index.ts +277 -55
  28. package/src/cli/models.ts +5 -1
  29. package/src/cli/provider.ts +8 -2
  30. package/src/cli/ready.ts +301 -0
  31. package/src/cli/system-restart-client.ts +146 -0
  32. package/src/cli/tray-proxy.ts +153 -6
  33. package/src/clients/config-export.ts +12 -19
  34. package/src/codex/account-lifecycle.ts +3 -0
  35. package/src/codex/account-namespaces.ts +49 -3
  36. package/src/codex/account-priority.ts +83 -0
  37. package/src/codex/auth-api.ts +83 -0
  38. package/src/codex/auth-context.ts +5 -2
  39. package/src/codex/catalog/provider-fetch.ts +11 -0
  40. package/src/codex/catalog/sync.ts +23 -1
  41. package/src/codex/codex-write-lock.ts +16 -4
  42. package/src/codex/desired-state.ts +37 -4
  43. package/src/codex/history-job.ts +15 -5
  44. package/src/codex/history-provider.ts +31 -14
  45. package/src/codex/history-worker.ts +28 -4
  46. package/src/codex/inject-coordination.ts +13 -1
  47. package/src/codex/inject.ts +360 -66
  48. package/src/codex/internal/history-writer.ts +1 -1
  49. package/src/codex/native-main-lock-file.ts +5 -1
  50. package/src/codex/native-main-owner.ts +17 -3
  51. package/src/codex/native-profile-manager.ts +19 -0
  52. package/src/codex/native-profile-startup.ts +8 -0
  53. package/src/codex/native-residue.ts +140 -27
  54. package/src/codex/pool-rotation.ts +74 -4
  55. package/src/codex/refresh.ts +7 -0
  56. package/src/codex/routing.ts +177 -36
  57. package/src/codex/subagent-model-fallback.ts +34 -4
  58. package/src/codex/sync.ts +61 -0
  59. package/src/codex/upstream-host-health.ts +329 -31
  60. package/src/combos/request.ts +2 -0
  61. package/src/config.ts +221 -2
  62. package/src/images/loop.ts +1 -1
  63. package/src/integrations/native/ownership-preflight.ts +39 -2
  64. package/src/lib/bun-stream-caps.ts +3 -3
  65. package/src/lib/sse-decoder.ts +41 -0
  66. package/src/lib/system-restart-contract.ts +73 -0
  67. package/src/lib/windows-secret-acl.ts +141 -39
  68. package/src/lib/windows-user-principal.ts +283 -0
  69. package/src/lib/winsw.ts +18 -2
  70. package/src/oauth/key-providers.ts +12 -0
  71. package/src/providers/derive.ts +54 -2
  72. package/src/providers/free-directory.ts +6 -5
  73. package/src/providers/model-discovery.ts +9 -3
  74. package/src/providers/quota.ts +592 -0
  75. package/src/providers/registry.ts +316 -13
  76. package/src/responses/parser.ts +26 -10
  77. package/src/responses/reasoning-replay-cache.ts +1 -0
  78. package/src/routing/profile-namespace.ts +15 -0
  79. package/src/routing/profile.ts +2 -1
  80. package/src/server/auth-cors.ts +44 -13
  81. package/src/server/chat-completions.ts +0 -4
  82. package/src/server/claude-messages.ts +73 -15
  83. package/src/server/github-copilot-responses-repair.ts +338 -0
  84. package/src/server/index.ts +328 -111
  85. package/src/server/lifecycle.ts +36 -0
  86. package/src/server/management/agent-settings-routes.ts +147 -56
  87. package/src/server/management/config-routes.ts +7 -2
  88. package/src/server/management/context.ts +4 -0
  89. package/src/server/management/native-integration-routes.ts +199 -20
  90. package/src/server/management/provider-routes.ts +41 -0
  91. package/src/server/management/routing-profile-routes.ts +234 -5
  92. package/src/server/management/system-restart.ts +12 -10
  93. package/src/server/management/system-routes.ts +20 -0
  94. package/src/server/management-auth.ts +51 -3
  95. package/src/server/ports.ts +41 -1
  96. package/src/server/proxy-liveness.ts +129 -4
  97. package/src/server/readiness.ts +99 -0
  98. package/src/server/relay.ts +113 -97
  99. package/src/server/request-log.ts +10 -4
  100. package/src/server/responses/compact.ts +107 -12
  101. package/src/server/responses/core.ts +220 -39
  102. package/src/server/responses-item-id-repair.ts +22 -3
  103. package/src/server/responses-model-rewrite.ts +29 -0
  104. package/src/server/sse-frame-buffer.ts +292 -0
  105. package/src/server/sse-payload-rewrite.ts +25 -14
  106. package/src/server/ws-bridge.ts +27 -22
  107. package/src/service-manager-probe.ts +520 -10
  108. package/src/service.ts +134 -2
  109. package/src/storage/worker-lifecycle.ts +14 -14
  110. package/src/tray/windows-tray.ps1 +74 -9
  111. package/src/types.ts +68 -2
  112. package/src/update/index.ts +12 -0
  113. package/src/update/job.ts +392 -18
  114. package/src/update/npm-cache-preflight.d.mts +47 -0
  115. package/src/update/npm-cache-preflight.mjs +201 -0
  116. package/src/usage/log.ts +1 -1
  117. package/src/vision/index.ts +77 -2
  118. package/src/web-search/loop.ts +1 -1
  119. package/src/web-search/parse.ts +4 -1
  120. package/gui/dist/assets/index-BKVqyYqT.js +0 -70
  121. package/gui/dist/assets/index-Ca_3269W.css +0 -1
@@ -1,5 +1,10 @@
1
1
  import type { CodexAccountMode, OcxProviderConfig } from "../types";
2
- import { PROVIDER_REGISTRY, providerMatchesRegistryTransport, type ProviderRegistryEntry } from "./registry";
2
+ import {
3
+ PROVIDER_REGISTRY,
4
+ providerMatchesRegistryTransport,
5
+ registryEntryForProviderDestination,
6
+ type ProviderRegistryEntry,
7
+ } from "./registry";
3
8
 
4
9
  export interface DerivedKeyLoginProvider {
5
10
  label: string;
@@ -239,9 +244,55 @@ export function deriveProviderPresets(): DerivedProviderPreset[] {
239
244
  return [...dedupePresets(presets), customPreset()];
240
245
  }
241
246
 
247
+ /**
248
+ * Merge registry reasoning-summary defaults PER KEY, letting explicit user values win.
249
+ *
250
+ * Not a whole-Record `=== undefined` fill like the scalars around it: a user who sets one
251
+ * model's flag creates a defined Record, and a whole-object check would then suppress every
252
+ * registry default for that provider. Spreading registry-first also preserves an explicit
253
+ * `false` — someone who disabled summaries for a model because their backend 400s on it keeps
254
+ * that. The result is a fresh object, so saved config never aliases the registry constant.
255
+ */
256
+ function applyReasoningSummaryDefaults(
257
+ prov: OcxProviderConfig,
258
+ defaults: Readonly<Record<string, boolean>> | undefined,
259
+ ): void {
260
+ if (!defaults) return;
261
+ prov.modelSupportsReasoningSummaries = {
262
+ ...defaults,
263
+ ...(prov.modelSupportsReasoningSummaries ?? {}),
264
+ };
265
+ }
266
+
267
+ /**
268
+ * Last-resort enrichment for a provider whose NAME matches no registry id.
269
+ *
270
+ * #1100 was reported against a hand-added provider called "GLM" pointing at a vendor endpoint
271
+ * we recognize. Routing worked, so the row looked healthy, but every piece of registry metadata
272
+ * was skipped and the reasoning ladder was advertised without summary support — exactly the
273
+ * inconsistency that makes Codex drop the inbound reasoning object.
274
+ *
275
+ * Deliberately narrow: only the reasoning-summary map, and only via
276
+ * `registryEntryForProviderDestination`, which matches fixed key destinations and refuses
277
+ * templated or overridable base URLs. A custom row keeps its own identity for everything else.
278
+ */
279
+ function enrichReasoningSummariesByDestination(prov: OcxProviderConfig): void {
280
+ const destination = registryEntryForProviderDestination(prov);
281
+ applyReasoningSummaryDefaults(prov, destination?.modelSupportsReasoningSummaries);
282
+ }
283
+
242
284
  export function enrichProviderFromRegistry(name: string, prov: OcxProviderConfig): void {
243
285
  const entry = PROVIDER_REGISTRY.find(row => row.id === name);
244
- if (!entry || !providerMatchesRegistryTransport(name, prov)) return;
286
+ if (!entry || !providerMatchesRegistryTransport(name, prov)) {
287
+ // Name lookup failed, but the row may still point at a vendor route we know. #1100 was
288
+ // reported against a hand-added provider literally named "GLM": routing worked, yet every
289
+ // piece of registry metadata was skipped because no registry id is called "GLM".
290
+ // `registryEntryForProviderDestination` answers the question that actually matters here —
291
+ // which vendor endpoint is this row talking to — and is already restricted to fixed key
292
+ // destinations, so a templated or overridable base URL cannot be claimed by it.
293
+ enrichReasoningSummariesByDestination(prov);
294
+ return;
295
+ }
245
296
  const seed = providerConfigSeed(entry);
246
297
  if (prov.apiKeyTransport === undefined && seed.apiKeyTransport !== undefined) prov.apiKeyTransport = seed.apiKeyTransport;
247
298
  if (!prov.defaultModel && seed.defaultModel) prov.defaultModel = seed.defaultModel;
@@ -276,6 +327,7 @@ export function enrichProviderFromRegistry(name: string, prov: OcxProviderConfig
276
327
  // the entry so an explicit user value stays distinguishable from the default.
277
328
  if (prov.supportsServiceTier === undefined && entry.supportsServiceTier !== undefined) prov.supportsServiceTier = entry.supportsServiceTier;
278
329
  if (prov.preserveResponsesReasoningContent === undefined && entry.preserveResponsesReasoningContent !== undefined) prov.preserveResponsesReasoningContent = entry.preserveResponsesReasoningContent;
330
+ applyReasoningSummaryDefaults(prov, entry.modelSupportsReasoningSummaries);
279
331
  // Registry-only repair policy (#938): fill only when the runtime provider has
280
332
  // no explicit policy, and deep-clone so saved/user values never alias the
281
333
  // registry constant.
@@ -99,7 +99,7 @@ const CONNECTABLE: Record<string, ConnectableOverride> = {
99
99
  ovhcloud: openAi("https://oai.endpoints.kepler.ai.cloud.ovh.net/v1", "https://console.ovhcloud.com", { keyOptional: true, modelsUrl: "https://oai.endpoints.kepler.ai.cloud.ovh.net/v1/models" }),
100
100
  pollinations: openAi("https://gen.pollinations.ai/v1", "https://pollinations.ai", { keyOptional: true }),
101
101
  reka: openAi("https://api.reka.ai/v1", "https://platform.reka.ai"),
102
- sambanova: openAi("https://api.sambanova.ai/v1", "https://cloud.sambanova.ai/apis", { supportLevel: "supported", verification: "official", documentationUrl: "https://docs.sambanova.ai/cloud/docs/api-reference/models" }),
102
+ sambanova: openAi("https://api.sambanova.ai/v1", "https://cloud.sambanova.ai/apis", { supportLevel: "supported", verification: "official", documentationUrl: "https://docs.sambanova.ai/docs/en/get-started/api-keys-urls", modelsUrl: "https://api.sambanova.ai/v1/models", lastVerified: "2026-08-02" }),
103
103
  sparkdesk: openAi("https://spark-api-open.xf-yun.com/v1", "https://console.xfyun.cn", { verification: "official", documentationUrl: "https://www.xfyun.cn/doc/spark/HTTP%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3.html" }),
104
104
  agnes: openAi("https://apihub.agnes-ai.com/v1", "https://agnes-ai.com"),
105
105
  ainative: openAi("https://api.ainative.studio/api/v1", "https://ainative.studio", { modelsUrl: "https://api.ainative.studio/api/v1/models" }),
@@ -132,12 +132,12 @@ const CONNECTABLE: Record<string, ConnectableOverride> = {
132
132
  hyperbolic: openAi("https://api.hyperbolic.xyz/v1", "https://app.hyperbolic.xyz/settings", { verification: "official" }),
133
133
  longcat: openAi("https://api.longcat.chat/openai/v1", "https://longcat.chat", { verification: "official", discovery: "static", liveModels: false, models: ["LongCat-2.0"] }),
134
134
  monsterapi: openAi("https://api.monsterapi.ai/v1", "https://monsterapi.ai", { verification: "official" }),
135
- nebius: openAi("https://api.tokenfactory.nebius.com/v1", "https://studio.nebius.com", { verification: "official" }),
135
+ nebius: openAi("https://api.tokenfactory.nebius.com/v1", "https://tokenfactory.nebius.com", { supportLevel: "supported", verification: "official", documentationUrl: "https://docs.tokenfactory.nebius.com/quickstart", modelsUrl: "https://api.tokenfactory.nebius.com/v1/models?verbose=true", lastVerified: "2026-08-02" }),
136
136
  novita: openAi("https://api.novita.ai/openai/v1", "https://novita.ai/settings/key-management", { supportLevel: "supported", verification: "official", modelsUrl: "https://api.novita.ai/openai/v1/models" }),
137
- nscale: openAi("https://inference.api.nscale.com/v1", "https://console.nscale.com", { verification: "official" }),
137
+ nscale: openAi("https://inference.api.nscale.com/v1", "https://console.nscale.com", { supportLevel: "supported", verification: "official", documentationUrl: "https://docs.nscale.com/docs/use-cases/chat", modelsUrl: "https://inference.api.nscale.com/v1/models", lastVerified: "2026-08-03" }),
138
138
  nvidia: openAi("https://integrate.api.nvidia.com/v1", "https://build.nvidia.com", { supportLevel: "supported", verification: "official", documentationUrl: "https://docs.api.nvidia.com/nim/reference/llm-apis" }),
139
139
  publicai: openAi("https://api.publicai.co/v1", "https://publicai.co"),
140
- scaleway: openAi("https://api.scaleway.ai/v1", "https://console.scaleway.com/generative-api", { verification: "official" }),
140
+ scaleway: openAi("https://api.scaleway.ai/v1", "https://console.scaleway.com/generative-api", { supportLevel: "supported", verification: "official", documentationUrl: "https://www.scaleway.com/en/docs/generative-apis/api-cli/using-generative-apis/", modelsUrl: "https://api.scaleway.ai/v1/models", lastVerified: "2026-08-01" }),
141
141
  sensenova: openAi("https://token.sensenova.cn/v1", "https://console.sensenova.cn", { verification: "official" }),
142
142
  stepfun: openAi("https://api.stepfun.com/v1", "https://platform.stepfun.com", { verification: "official" }),
143
143
  together: openAi("https://api.together.xyz/v1", "https://api.together.xyz/settings/api-keys", { supportLevel: "supported", verification: "official", documentationUrl: "https://docs.together.ai/reference/models-1" }),
@@ -155,7 +155,8 @@ const LABELS: Record<string, string> = {
155
155
  glm: "Z.AI GLM", "glm-cn": "BigModel GLM (CN)", "kilo-gateway": "Kilo Gateway", "opencode-zen": "OpenCode Zen",
156
156
  sealion: "SEA-LION", bytez: "Bytez", "nous-research": "Nous Research", agentrouter: "AgentRouter",
157
157
  ai21: "AI21", baichuan: "Baichuan", deepinfra: "DeepInfra", deepseek: "DeepSeek", doubao: "Doubao",
158
- "freemodel-dev": "FreeModel.dev", nebius: "Nebius", novita: "Novita", nscale: "Nscale", nvidia: "NVIDIA NIM",
158
+ "freemodel-dev": "FreeModel.dev", sambanova: "SambaNova Cloud", nebius: "Nebius Token Factory",
159
+ novita: "Novita", nscale: "Nscale", nvidia: "NVIDIA NIM",
159
160
  publicai: "PublicAI", qoder: "Qoder", sensenova: "SenseNova", stepfun: "StepFun", vertex: "Google Vertex AI",
160
161
  };
161
162
 
@@ -2,6 +2,7 @@ import type { OcxProviderConfig } from "../types";
2
2
  import {
3
3
  getProviderRegistryEntry,
4
4
  providerMatchesRegistryTransport,
5
+ registryEntryForProviderDestination,
5
6
  type ProviderModelDiscoveryFilter,
6
7
  type ProviderModelDiscoveryPredicate,
7
8
  type ProviderModelDiscoveryScalar,
@@ -124,9 +125,14 @@ export function resolveProviderModelDiscovery(
124
125
  providerName: string,
125
126
  provider: Pick<OcxProviderConfig, "baseUrl" | "adapter"> & Partial<Pick<OcxProviderConfig, "authMode">>,
126
127
  ): ResolvedProviderModelDiscovery {
127
- const entry = providerMatchesRegistryTransport(providerName, provider)
128
- ? getProviderRegistryEntry(providerName)
129
- : undefined;
128
+ // The dashboard permits a canonical preset to be saved under a different name. Recover its
129
+ // registry-owned discovery policy by transport in that case. The destination helper is limited
130
+ // to exact fixed-key baseUrl + adapter matches, so custom endpoints, OAuth rows, templates, and
131
+ // overridable destinations cannot acquire another provider's discovery URL or filter.
132
+ const namedEntry = getProviderRegistryEntry(providerName);
133
+ const entry = namedEntry
134
+ ? (providerMatchesRegistryTransport(providerName, provider) ? namedEntry : undefined)
135
+ : registryEntryForProviderDestination(provider);
130
136
  const spec = entry?.modelDiscovery;
131
137
  return {
132
138
  ...(spec ? { spec } : {}),