@bitkyc08/opencodex 2.11.0 → 2.11.1

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 (92) hide show
  1. package/gui/dist/assets/{index-Bk-PN-70.css → index-BA1dgo4q.css} +1 -1
  2. package/gui/dist/assets/index-DDZpgzKk.js +70 -0
  3. package/gui/dist/index.html +2 -2
  4. package/package.json +6 -4
  5. package/src/adapters/anthropic.ts +10 -2
  6. package/src/adapters/cursor/native-exec-common.ts +6 -2
  7. package/src/adapters/google-antigravity-replay.ts +3 -2
  8. package/src/adapters/google-antigravity-wire.ts +38 -6
  9. package/src/adapters/google.ts +57 -10
  10. package/src/adapters/openai-chat.ts +19 -2
  11. package/src/claude/model-info.ts +1 -1
  12. package/src/cli/account-auth.ts +3 -1
  13. package/src/cli/account-catalog-refresh.ts +14 -0
  14. package/src/cli/account-extended.ts +15 -1
  15. package/src/cli/codex-shim-readiness.ts +69 -0
  16. package/src/cli/combo.ts +5 -0
  17. package/src/cli/config-command.ts +33 -4
  18. package/src/cli/doctor.ts +21 -0
  19. package/src/cli/export-command.ts +6 -6
  20. package/src/cli/help.ts +6 -6
  21. package/src/cli/index.ts +22 -5
  22. package/src/cli/models-runtime.ts +13 -1
  23. package/src/cli/provider.ts +7 -0
  24. package/src/clients/config-export.ts +67 -5
  25. package/src/codex/account-lifecycle.ts +99 -10
  26. package/src/codex/auth-api.ts +222 -34
  27. package/src/codex/catalog/account-models.ts +9 -4
  28. package/src/codex/catalog/aggregation.ts +41 -8
  29. package/src/codex/catalog/bundled.ts +54 -22
  30. package/src/codex/catalog/effort.ts +47 -20
  31. package/src/codex/catalog/kinds.ts +2 -0
  32. package/src/codex/catalog/metadata.ts +70 -18
  33. package/src/codex/catalog/native-models.ts +7 -0
  34. package/src/codex/catalog/parsing.ts +29 -11
  35. package/src/codex/catalog/provider-fetch.ts +335 -50
  36. package/src/codex/catalog/sync.ts +588 -126
  37. package/src/codex/catalog-refresh-status.ts +87 -0
  38. package/src/codex/catalog-write-serialization.ts +2 -1
  39. package/src/codex/catalog.ts +4 -3
  40. package/src/codex/convergence-types.ts +1 -1
  41. package/src/codex/convergence.ts +190 -52
  42. package/src/codex/custom-model-catalog-migration.ts +176 -0
  43. package/src/codex/features.ts +79 -1
  44. package/src/codex/history-job.ts +81 -1
  45. package/src/codex/history-lock.ts +2 -1
  46. package/src/codex/history-provider.ts +4 -3
  47. package/src/codex/inject.ts +56 -12
  48. package/src/codex/model-cache.ts +50 -10
  49. package/src/codex/transition-state.ts +10 -2
  50. package/src/codex/user-identity.ts +110 -2
  51. package/src/combos/index.ts +3 -0
  52. package/src/combos/types.ts +75 -9
  53. package/src/config.ts +26 -12
  54. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +12 -10
  55. package/src/integrations/registry.ts +7 -0
  56. package/src/integrations/writer.ts +1 -1
  57. package/src/lib/pinned-http.ts +40 -9
  58. package/src/lib/process-control.ts +4 -1
  59. package/src/lib/provider-outbound.ts +42 -9
  60. package/src/oauth/cursor.ts +25 -5
  61. package/src/oauth/index.ts +59 -45
  62. package/src/providers/antigravity-models.ts +115 -3
  63. package/src/providers/context-cap.ts +13 -5
  64. package/src/providers/model-discovery-limits.ts +16 -0
  65. package/src/providers/model-discovery.ts +14 -15
  66. package/src/providers/provider-id-rewrite.ts +29 -0
  67. package/src/providers/quota.ts +93 -19
  68. package/src/providers/registry.ts +16 -5
  69. package/src/providers/slug-codec.ts +13 -6
  70. package/src/reasoning-effort.ts +22 -0
  71. package/src/router.ts +0 -20
  72. package/src/routing/history/indexer.ts +54 -39
  73. package/src/routing/quota.ts +77 -56
  74. package/src/server/index.ts +32 -7
  75. package/src/server/management/combo-routes.ts +43 -19
  76. package/src/server/management/config-routes.ts +115 -20
  77. package/src/server/management/model-routes.ts +10 -7
  78. package/src/server/management/model-rows.ts +6 -2
  79. package/src/server/management/oauth-account-routes.ts +12 -0
  80. package/src/server/management/provider-routes.ts +114 -40
  81. package/src/server/management/routing-profile-routes.ts +0 -22
  82. package/src/server/management-api.ts +7 -25
  83. package/src/server/responses/core.ts +3 -3
  84. package/src/server/responses/policy-fallback.ts +152 -0
  85. package/src/server/responses.ts +3 -2
  86. package/src/types.ts +15 -2
  87. package/src/usage/cost.ts +0 -0
  88. package/src/vision/describe.ts +3 -1
  89. package/src/vision/index.ts +17 -6
  90. package/src/vision/reasoning.ts +55 -0
  91. package/src/web-search/parse.ts +15 -3
  92. package/gui/dist/assets/index-BynIEIV-.js +0 -70
@@ -1,8 +1,10 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import type { OcxConfig, OcxContentPart, OcxMessage, OcxParsedRequest, OcxProviderConfig, OcxTextContent } from "../types";
3
3
  import { modelInList } from "../types";
4
+ import type { VisionReasoningEffort } from "../reasoning-effort";
4
5
  import { describeImage, type DescribeOutcome, type VisionSettings } from "./describe";
5
6
  import { describeImageAnthropic } from "./anthropic-describe";
7
+ import { normalizeVisionReasoningForModel } from "./reasoning";
6
8
  import type { CodexAuthContext } from "../codex/auth-context";
7
9
  import { getAccountSet } from "../oauth/store";
8
10
  import type { ResolvedOpenAiForwardSidecar } from "../providers/openai-sidecar";
@@ -16,6 +18,7 @@ export { describeImageAnthropic, parseAnthropicVisionSSE } from "./anthropic-des
16
18
  const DEFAULT_VISION_MODEL = "gpt-5.4-mini";
17
19
  const DEFAULT_ANTHROPIC_VISION_MODEL = "claude-sonnet-5";
18
20
  const DEFAULT_TIMEOUT_MS = 45_000;
21
+ const DEFAULT_REASONING: VisionReasoningEffort = "low";
19
22
  const DEFAULT_MAX_DESCRIPTIONS_PER_TURN = 8;
20
23
  const DESCRIPTION_CACHE_MAX_ENTRIES = 256;
21
24
  export const VISION_DESCRIPTION_CACHE_MAX_BYTES = 1024 * 1024;
@@ -186,7 +189,7 @@ export function resolveVisionBackend(
186
189
 
187
190
  /** Native model used by the OpenAI vision helper, including its bounded default. */
188
191
  export function resolveOpenAiVisionModel(config: Pick<OcxConfig, "visionSidecar">): string {
189
- return config.visionSidecar?.model ?? DEFAULT_VISION_MODEL;
192
+ return config.visionSidecar?.model || DEFAULT_VISION_MODEL;
190
193
  }
191
194
 
192
195
  /** A user/developer/toolResult message can carry images (toolResult: e.g. Codex view_image output). */
@@ -242,19 +245,29 @@ export function planVisionSidecar(
242
245
 
243
246
  if (backend === "anthropic") {
244
247
  if (!anthropicSidecar) return undefined;
248
+ const model = cfg.model || DEFAULT_ANTHROPIC_VISION_MODEL;
245
249
  return {
246
250
  backend,
247
251
  anthropicSidecar,
248
- settings: { model: cfg.model ?? DEFAULT_ANTHROPIC_VISION_MODEL, timeoutMs: cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS },
252
+ settings: {
253
+ model,
254
+ reasoning: normalizeVisionReasoningForModel(model, cfg.reasoning) ?? DEFAULT_REASONING,
255
+ timeoutMs: cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS,
256
+ },
249
257
  maxDescriptionsPerTurn,
250
258
  };
251
259
  }
252
260
 
253
261
  if (!openAiSidecar) return undefined;
262
+ const model = resolveOpenAiVisionModel(config);
254
263
  return {
255
264
  backend,
256
265
  forwardSidecar: openAiSidecar,
257
- settings: { model: resolveOpenAiVisionModel(config), timeoutMs: cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS },
266
+ settings: {
267
+ model,
268
+ reasoning: normalizeVisionReasoningForModel(model, cfg.reasoning) ?? DEFAULT_REASONING,
269
+ timeoutMs: cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS,
270
+ },
258
271
  maxDescriptionsPerTurn,
259
272
  };
260
273
  }
@@ -363,6 +376,7 @@ function descriptionIdentity(job: ImageJob, plan: VisionPlan): { key: string; pe
363
376
  key: JSON.stringify([
364
377
  plan.backend,
365
378
  plan.settings.model,
379
+ ...(plan.backend === "openai" ? [plan.settings.reasoning] : []),
366
380
  job.detail ?? "high",
367
381
  imageHash,
368
382
  sha256(normalizedContext(job.contextText)),
@@ -418,7 +432,6 @@ export async function describeImagesInPlace(
418
432
  recordSidecarOutcome?: SidecarOutcomeRecorder,
419
433
  translatorBudget?: TranslatorBudget,
420
434
  ): Promise<void> {
421
- // 1. Gather every image part across messages, each with its own message's text as context.
422
435
  const jobs: ImageJob[] = [];
423
436
  const targets: { msg: OcxMessage; parts: OcxContentPart[] }[] = [];
424
437
  for (const msg of parsed.context.messages) {
@@ -440,7 +453,6 @@ export async function describeImagesInPlace(
440
453
  return;
441
454
  }
442
455
 
443
- // 2. Admit misses in source order. Cache hits and same-turn waiters do not consume the cap.
444
456
  const inFlight = new Map<string, Promise<DescribeOutcome>>();
445
457
  const executions: Array<() => Promise<void>> = [];
446
458
  const outcomePromises: Array<Promise<DescribeOutcome>> = [];
@@ -492,7 +504,6 @@ export async function describeImagesInPlace(
492
504
  await runBounded(executions, VISION_CONCURRENCY, execute => execute());
493
505
  const outcomes = await Promise.all(outcomePromises);
494
506
 
495
- // 3. Rebuild each message, replacing image parts with their descriptions in order.
496
507
  let oi = 0;
497
508
  const descriptions: string[] = [];
498
509
  for (const { msg, parts } of targets) {
@@ -0,0 +1,55 @@
1
+ import { NATIVE_OPENAI_MODELS, nativeReasoningEfforts } from "../codex/catalog/metadata";
2
+ import {
3
+ VISION_REASONING_EFFORTS,
4
+ sanitizeVisionReasoning,
5
+ type VisionReasoningEffort,
6
+ } from "../reasoning-effort";
7
+
8
+ /** Keep the public config type aligned without replacing the heavily-changed shared types file. */
9
+ declare module "../types" {
10
+ interface OcxVisionSidecarConfig {
11
+ /** OpenAI Responses reasoning effort used by the vision describer. Default: low. */
12
+ reasoning?: VisionReasoningEffort;
13
+ }
14
+ }
15
+
16
+ const NATIVE_VISION_MODELS = new Set(NATIVE_OPENAI_MODELS);
17
+
18
+ /**
19
+ * Return the known vision reasoning ladder for a native OpenAI model.
20
+ * Unknown/custom models deliberately return undefined so callers stay permissive when reliable
21
+ * capability metadata is unavailable.
22
+ */
23
+ export function nativeVisionReasoningEfforts(modelId: string): VisionReasoningEffort[] | undefined {
24
+ if (!NATIVE_VISION_MODELS.has(modelId)) return undefined;
25
+ const advertised = new Set(nativeReasoningEfforts(modelId));
26
+ const supported = VISION_REASONING_EFFORTS.filter(effort => advertised.has(effort));
27
+ return supported.length > 0 ? [...supported] : undefined;
28
+ }
29
+
30
+ /**
31
+ * Normalize one configured effort against a model's known ladder. Invalid enum values degrade to
32
+ * undefined; valid values on unknown/custom models are preserved. A known native model clamps to
33
+ * the highest supported rung at or below the requested value.
34
+ */
35
+ export function normalizeVisionReasoningForModel(
36
+ modelId: string,
37
+ value: unknown,
38
+ ): VisionReasoningEffort | undefined {
39
+ const requested = sanitizeVisionReasoning(value);
40
+ if (!requested) return undefined;
41
+ const supported = nativeVisionReasoningEfforts(modelId);
42
+ if (!supported || supported.includes(requested)) return requested;
43
+
44
+ const requestedRank = VISION_REASONING_EFFORTS.indexOf(requested);
45
+ let best = supported[0];
46
+ let bestRank = VISION_REASONING_EFFORTS.indexOf(best);
47
+ for (const effort of supported) {
48
+ const rank = VISION_REASONING_EFFORTS.indexOf(effort);
49
+ if (rank <= requestedRank && rank >= bestRank) {
50
+ best = effort;
51
+ bestRank = rank;
52
+ }
53
+ }
54
+ return best;
55
+ }
@@ -155,11 +155,23 @@ export async function parseSidecarSSE(response: Response): Promise<WebSearchResu
155
155
 
156
156
  const handle = (payload: string): void => {
157
157
  if (!payload || payload === "[DONE]") return;
158
- let data: Record<string, unknown>;
159
- try { data = JSON.parse(payload) as Record<string, unknown>; } catch {
160
- console.warn(`[web-search-parse] malformed SSE JSON (${payload.length} chars): ${payload.slice(0, 120)}`);
158
+ // Neither warning below copies the frame's content. An upstream SSE payload can carry model
159
+ // output or credential material, and a malformed frame is exactly the case where the content
160
+ // is least trustworthy. Length plus a classification separates the two failure modes in a log
161
+ // without reproducing anything from the wire.
162
+ let parsed: unknown;
163
+ try { parsed = JSON.parse(payload); } catch {
164
+ console.warn(`[web-search-parse] malformed SSE JSON (${payload.length} chars)`);
161
165
  return;
162
166
  }
167
+ // `JSON.parse("null")` returns null rather than throwing, so the catch above cannot cover it
168
+ // and the `data.type` read below threw out of parseSidecarSSE.
169
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
170
+ const shape = Array.isArray(parsed) ? "array" : parsed === null ? "null" : typeof parsed;
171
+ console.warn(`[web-search-parse] non-record SSE JSON frame (${payload.length} chars, ${shape})`);
172
+ return;
173
+ }
174
+ const data = parsed as Record<string, unknown>;
163
175
  const type = data.type as string | undefined;
164
176
  if (type === "response.output_text.delta" && typeof data.delta === "string") {
165
177
  acc.deltaText += data.delta;