@bitkyc08/opencodex 2.54.0 → 2.55.0-preview.20260914
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.
- package/gui/dist/assets/{index-CkvITofZ.js → index-DH2PUHqr.js} +10 -10
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapters/anthropic-image-codec.ts +57 -0
- package/src/adapters/anthropic-image-normalize.ts +28 -1
- package/src/adapters/anthropic.ts +68 -6
- package/src/adapters/base.ts +8 -0
- package/src/adapters/coding-agent/protocol.ts +41 -16
- package/src/adapters/cursor/cursor-errors.ts +1 -1
- package/src/adapters/cursor/live-transport.ts +5 -1
- package/src/adapters/cursor/native-exec-fs.ts +10 -10
- package/src/adapters/cursor/native-exec-network.ts +2 -2
- package/src/adapters/cursor/native-exec-shell.ts +13 -12
- package/src/adapters/cursor/native-exec.ts +51 -10
- package/src/adapters/cursor/policy-error.ts +75 -0
- package/src/adapters/cursor/protobuf-request.ts +105 -1
- package/src/adapters/devin/cloud-direct/catalog.ts +34 -2
- package/src/adapters/devin/live-models.ts +33 -2
- package/src/adapters/google-wire-compiler.ts +8 -0
- package/src/adapters/google.ts +46 -0
- package/src/adapters/input-media-guard.ts +45 -0
- package/src/adapters/kiro/adapter.ts +8 -0
- package/src/adapters/kiro/payload.ts +28 -6
- package/src/adapters/kiro-events.ts +25 -6
- package/src/adapters/kiro-images.ts +30 -0
- package/src/adapters/kiro-retry.ts +8 -0
- package/src/adapters/openai-chat.ts +33 -4
- package/src/adapters/openai-responses.ts +26 -0
- package/src/adapters/registry.ts +4 -0
- package/src/bridge.ts +163 -116
- package/src/chat/image-parts.ts +151 -0
- package/src/chat/inbound.ts +70 -33
- package/src/cli/connect.ts +30 -9
- package/src/cli/dispatch.ts +7 -3
- package/src/cli/index.ts +3 -0
- package/src/cli/runtime-api.ts +25 -0
- package/src/cli/status.ts +21 -19
- package/src/cli/system-restart-client.ts +25 -0
- package/src/clients/config-export.ts +14 -4
- package/src/codex/app-server-processes.ts +25 -0
- package/src/codex/auth-context.ts +8 -0
- package/src/codex/autostart-health.ts +36 -2
- package/src/codex/catalog/provider-fetch.ts +41 -0
- package/src/codex/catalog-auto-refresh.ts +182 -0
- package/src/codex/catalog-refresh-status.ts +93 -0
- package/src/codex/history-provider.ts +55 -0
- package/src/codex/model-entitlements.ts +78 -0
- package/src/codex/native-profile-processes.ts +114 -15
- package/src/codex/prompt-text-probe.ts +274 -41
- package/src/codex/routing-adoption.ts +189 -0
- package/src/codex/routing.ts +520 -48
- package/src/codex/runtime.ts +249 -7
- package/src/combos/failover.ts +45 -0
- package/src/config.ts +124 -4
- package/src/generated/compatibility-version.json +110 -74
- package/src/generated/model-metadata.ts +1 -0
- package/src/lib/request-execution-budget.ts +202 -0
- package/src/lib/upstream-retry.ts +95 -8
- package/src/lib/workflow-budget.ts +172 -0
- package/src/oauth/devin.ts +57 -12
- package/src/providers/quota.ts +37 -6
- package/src/providers/registry.ts +53 -6
- package/src/responses/input-media.ts +65 -0
- package/src/responses/parser-content.ts +42 -0
- package/src/responses/schema.ts +12 -2
- package/src/server/audio-live.ts +1 -2
- package/src/server/audio-transcriptions.ts +1 -2
- package/src/server/auth-cors.ts +1 -1
- package/src/server/background-lifecycle.ts +18 -0
- package/src/server/chat-completions.ts +23 -8
- package/src/server/chat-native.ts +17 -17
- package/src/server/index.ts +24 -0
- package/src/server/management/request-history-routes.ts +5 -0
- package/src/server/request-log.ts +8 -2
- package/src/server/responses/compact.ts +51 -3
- package/src/server/responses/core.ts +238 -28
- package/src/server/search.ts +7 -9
- package/src/types/config.ts +51 -6
- package/src/usage/log.ts +37 -0
- package/src/vision/eligibility.ts +37 -4
- package/src/vision/index.ts +1 -0
- package/src/vision/plan.ts +45 -10
- package/src/web-search/alpha-search.ts +324 -0
- package/src/web-search/index.ts +13 -22
- package/src/web-search/passthrough-bridge.ts +195 -22
- package/src/web-search/sidecar-providers.ts +22 -0
package/src/config.ts
CHANGED
|
@@ -507,9 +507,15 @@ export function requestPacingConfigError(value: unknown): string | null {
|
|
|
507
507
|
/**
|
|
508
508
|
* Bounds for the opt-in passthrough web-search bridge (`providers.<name>.webSearchBridge`,
|
|
509
509
|
* #3761). Strict for the same reason `retryOn429` is: a misspelled key here would silently
|
|
510
|
-
* leave the bridge disarmed while the operator believes they enabled it.
|
|
511
|
-
*
|
|
512
|
-
*
|
|
510
|
+
* leave the bridge disarmed while the operator believes they enabled it.
|
|
511
|
+
*
|
|
512
|
+
* `endpoint` names the destination that receives this provider's API key, so it gets the same
|
|
513
|
+
* literal destination assessment `baseUrl` gets (#4519) — see `providerWebSearchBridgeConfigError`
|
|
514
|
+
* below. This schema itself still only shape-checks: it is `.catch(undefined)` at the provider
|
|
515
|
+
* row, and a hand-edited config file never reaches the error function at all. The authorization
|
|
516
|
+
* boundary is therefore `resolveOllamaWebSearchEndpoint`, which runs the same assessment and is
|
|
517
|
+
* the only reader of this field in the tree; config validation is where an operator is told why,
|
|
518
|
+
* not what makes the value safe.
|
|
513
519
|
*/
|
|
514
520
|
const providerWebSearchBridgeSchema = z.object({
|
|
515
521
|
enabled: z.boolean().optional(),
|
|
@@ -519,7 +525,11 @@ const providerWebSearchBridgeSchema = z.object({
|
|
|
519
525
|
endpoint: z.string().min(1).optional(),
|
|
520
526
|
}).strict();
|
|
521
527
|
|
|
522
|
-
export function providerWebSearchBridgeConfigError(
|
|
528
|
+
export function providerWebSearchBridgeConfigError(
|
|
529
|
+
value: unknown,
|
|
530
|
+
providerName: string,
|
|
531
|
+
provider: Pick<OcxProviderConfig, "allowPrivateNetwork">,
|
|
532
|
+
): string | null {
|
|
523
533
|
if (value === undefined) return null;
|
|
524
534
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
525
535
|
return "webSearchBridge must be a plain object";
|
|
@@ -541,6 +551,17 @@ export function providerWebSearchBridgeConfigError(value: unknown): string | nul
|
|
|
541
551
|
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
542
552
|
return "webSearchBridge.endpoint must be an absolute http(s) URL";
|
|
543
553
|
}
|
|
554
|
+
// Same classifier baseUrl uses, so a metadata address is refused outright and loopback or
|
|
555
|
+
// private space needs the provider's allowPrivateNetwork opt-in (or a registry entry that is
|
|
556
|
+
// local by definition, which is what keeps a self-hosted Ollama working). Literal-only and
|
|
557
|
+
// synchronous, exactly as at the baseUrl boundary: no DNS is resolved here.
|
|
558
|
+
const destinationError = providerDestinationConfigError(providerName, {
|
|
559
|
+
baseUrl: endpoint,
|
|
560
|
+
allowPrivateNetwork: provider.allowPrivateNetwork,
|
|
561
|
+
});
|
|
562
|
+
if (destinationError) {
|
|
563
|
+
return destinationError.replace(/^baseUrl/, "webSearchBridge.endpoint");
|
|
564
|
+
}
|
|
544
565
|
}
|
|
545
566
|
return null;
|
|
546
567
|
}
|
|
@@ -1206,6 +1227,24 @@ const quotaResetNotifySchema = z.object({
|
|
|
1206
1227
|
command: z.array(z.string()).optional(),
|
|
1207
1228
|
}).strict();
|
|
1208
1229
|
|
|
1230
|
+
/**
|
|
1231
|
+
* Catalog auto-refresh section (issue #3630).
|
|
1232
|
+
*
|
|
1233
|
+
* `.strict()` like its neighbour: a typo in an optional feature section should surface as a
|
|
1234
|
+
* rejected write rather than a silently ignored key that leaves the operator believing they
|
|
1235
|
+
* enabled something.
|
|
1236
|
+
*
|
|
1237
|
+
* `intervalMinutes` admits 0 (configured but dormant, no timer) and the resolver clamps
|
|
1238
|
+
* anything between 1 and the 15-minute floor. Bounds live in the resolver rather than here
|
|
1239
|
+
* so a hand-edited value degrades to a sane one instead of discarding the whole section.
|
|
1240
|
+
* The 1440 ceiling keeps a hand edit from scheduling the refresh further out than a day,
|
|
1241
|
+
* which is operator error far more often than intent.
|
|
1242
|
+
*/
|
|
1243
|
+
const catalogAutoRefreshSchema = z.object({
|
|
1244
|
+
enabled: z.boolean().optional(),
|
|
1245
|
+
intervalMinutes: z.number().int().min(0).max(1440).optional(),
|
|
1246
|
+
}).strict();
|
|
1247
|
+
|
|
1209
1248
|
const configSchema = z.object({
|
|
1210
1249
|
port: z.number().int().min(0).max(65535).default(10100),
|
|
1211
1250
|
// A malformed hand edit must disable only remote-role behavior, not discard
|
|
@@ -1310,6 +1349,8 @@ const configSchema = z.object({
|
|
|
1310
1349
|
agentTaskRecovery: agentTaskRecoverySchema.optional().catch(undefined),
|
|
1311
1350
|
// Same rationale: a bad notify section must not cost the operator their providers.
|
|
1312
1351
|
quotaResetNotify: quotaResetNotifySchema.optional().catch(undefined),
|
|
1352
|
+
// Same rationale: a bad auto-refresh section must not cost the operator their providers.
|
|
1353
|
+
catalogAutoRefresh: catalogAutoRefreshSchema.optional().catch(undefined),
|
|
1313
1354
|
// These selections pre-date schema validation and used to pass through as
|
|
1314
1355
|
// unknown fields. Invalid hand edits must disable only the optional
|
|
1315
1356
|
// delegation/native-default feature, not reject the whole config and hide
|
|
@@ -2351,6 +2392,15 @@ function malformedQuotaResetNotifyWarning(rawParsed: unknown): string | null {
|
|
|
2351
2392
|
return `quotaResetNotify${field ? `.${field}` : ""} ignored: invalid quota-reset notification configuration`;
|
|
2352
2393
|
}
|
|
2353
2394
|
|
|
2395
|
+
function malformedCatalogAutoRefreshWarning(rawParsed: unknown): string | null {
|
|
2396
|
+
const raw = rawConfigRecord(rawParsed);
|
|
2397
|
+
if (!raw || !Object.hasOwn(raw, "catalogAutoRefresh")) return null;
|
|
2398
|
+
const result = catalogAutoRefreshSchema.safeParse(raw.catalogAutoRefresh);
|
|
2399
|
+
if (result.success) return null;
|
|
2400
|
+
const field = result.error.issues[0]?.path.join(".");
|
|
2401
|
+
return `catalogAutoRefresh${field ? `.${field}` : ""} ignored: invalid catalog auto-refresh configuration`;
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2354
2404
|
/**
|
|
2355
2405
|
* Same silent-in-the-wrong-direction failure as the notification block: a dropped pool policy means
|
|
2356
2406
|
* the accounts the operator meant to exclude keep taking traffic, and the only visible symptom is
|
|
@@ -2377,6 +2427,18 @@ function warnDegradedQuotaResetNotify(rawParsed: unknown): void {
|
|
|
2377
2427
|
if (warning) console.warn(`⚠️ config.json ${warning}. Other settings were preserved.`);
|
|
2378
2428
|
}
|
|
2379
2429
|
|
|
2430
|
+
/**
|
|
2431
|
+
* Warn once per load that the section was dropped.
|
|
2432
|
+
*
|
|
2433
|
+
* Same silent-in-the-wrong-direction failure as the notification block: a dropped section
|
|
2434
|
+
* means the scheduler never starts, so the operator sees a stale catalog — which is exactly
|
|
2435
|
+
* what they would see if the feature were working and no new models had shipped.
|
|
2436
|
+
*/
|
|
2437
|
+
function warnDegradedCatalogAutoRefresh(rawParsed: unknown): void {
|
|
2438
|
+
const warning = malformedCatalogAutoRefreshWarning(rawParsed);
|
|
2439
|
+
if (warning) console.warn(`⚠️ config.json ${warning}. Other settings were preserved.`);
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2380
2442
|
/**
|
|
2381
2443
|
* Warn once per load that the pool policy was dropped.
|
|
2382
2444
|
*
|
|
@@ -2552,6 +2614,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2552
2614
|
warnDegradedRuntimeRole(parsed);
|
|
2553
2615
|
warnDegradedOptionalRemoteBlocks(parsed);
|
|
2554
2616
|
warnDegradedQuotaResetNotify(parsed);
|
|
2617
|
+
warnDegradedCatalogAutoRefresh(parsed);
|
|
2555
2618
|
warnDegradedCodexPool(parsed);
|
|
2556
2619
|
return withRefreshedCostOverlays(normalizeClaudeSubagentEffort(normalizeNativeSubagentSync(config, parsed), parsed));
|
|
2557
2620
|
}
|
|
@@ -2594,6 +2657,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2594
2657
|
warnDegradedRuntimeRole(parsed);
|
|
2595
2658
|
warnDegradedOptionalRemoteBlocks(parsed);
|
|
2596
2659
|
warnDegradedQuotaResetNotify(parsed);
|
|
2660
|
+
warnDegradedCatalogAutoRefresh(parsed);
|
|
2597
2661
|
warnDegradedCodexPool(parsed);
|
|
2598
2662
|
return withRefreshedCostOverlays(normalizeClaudeSubagentEffort(normalizeNativeSubagentSync(config, parsed), parsed));
|
|
2599
2663
|
}
|
|
@@ -2621,6 +2685,7 @@ export function loadConfig(): OcxConfig {
|
|
|
2621
2685
|
warnDegradedRuntimeRole(parsed);
|
|
2622
2686
|
warnDegradedOptionalRemoteBlocks(parsed);
|
|
2623
2687
|
warnDegradedQuotaResetNotify(parsed);
|
|
2688
|
+
warnDegradedCatalogAutoRefresh(parsed);
|
|
2624
2689
|
warnDegradedCodexPool(parsed);
|
|
2625
2690
|
return withRefreshedCostOverlays(normalizeClaudeSubagentEffort(normalizeNativeSubagentSync(config, parsed), parsed));
|
|
2626
2691
|
}
|
|
@@ -2767,6 +2832,8 @@ function validFileConfigDiagnostics(config: OcxConfig, rawParsed: unknown): Conf
|
|
|
2767
2832
|
if (clientWarning) warnings.push(clientWarning);
|
|
2768
2833
|
const notifyWarning = malformedQuotaResetNotifyWarning(rawParsed);
|
|
2769
2834
|
if (notifyWarning) warnings.push(notifyWarning);
|
|
2835
|
+
const catalogRefreshWarning = malformedCatalogAutoRefreshWarning(rawParsed);
|
|
2836
|
+
if (catalogRefreshWarning) warnings.push(catalogRefreshWarning);
|
|
2770
2837
|
const codexPoolWarning = malformedCodexPoolWarning(rawParsed);
|
|
2771
2838
|
if (codexPoolWarning) warnings.push(codexPoolWarning);
|
|
2772
2839
|
const plaintextWarning = malformedPlaintextV2AgentMessagesWarning(rawParsed);
|
|
@@ -2932,6 +2999,16 @@ function quotaResetNotifyError(value: unknown): string | null {
|
|
|
2932
2999
|
return `schema_invalid: quotaResetNotify${field ? `.${field}` : ""}: ${issue?.message ?? "invalid configuration"}`;
|
|
2933
3000
|
}
|
|
2934
3001
|
|
|
3002
|
+
function catalogAutoRefreshError(value: unknown): string | null {
|
|
3003
|
+
const raw = rawConfigRecord(value);
|
|
3004
|
+
if (!raw || !Object.hasOwn(raw, "catalogAutoRefresh") || raw.catalogAutoRefresh === undefined) return null;
|
|
3005
|
+
const result = catalogAutoRefreshSchema.safeParse(raw.catalogAutoRefresh);
|
|
3006
|
+
if (result.success) return null;
|
|
3007
|
+
const issue = result.error.issues[0];
|
|
3008
|
+
const field = issue?.path.join(".");
|
|
3009
|
+
return `schema_invalid: catalogAutoRefresh${field ? `.${field}` : ""}: ${issue?.message ?? "invalid configuration"}`;
|
|
3010
|
+
}
|
|
3011
|
+
|
|
2935
3012
|
/**
|
|
2936
3013
|
* The read path degrades a malformed pool policy to undefined, which for an exclusion policy means
|
|
2937
3014
|
* the excluded accounts quietly keep serving traffic. Reject it on write so `ocx config set` cannot
|
|
@@ -3167,6 +3244,7 @@ export function validateConfigCandidate(value: unknown): { ok: true; config: Ocx
|
|
|
3167
3244
|
?? plaintextV2AgentMessagesError(value)
|
|
3168
3245
|
?? agentTaskRecoveryError(value)
|
|
3169
3246
|
?? quotaResetNotifyError(value)
|
|
3247
|
+
?? catalogAutoRefreshError(value)
|
|
3170
3248
|
?? codexPoolError(value)
|
|
3171
3249
|
?? googleAntigravityStaticCatalogVersionError(value)
|
|
3172
3250
|
?? codexAccountPrioritiesError(value)
|
|
@@ -3767,6 +3845,48 @@ export function ultraFastTierEnabled(config: Pick<OcxConfig, "ultraFastTier">):
|
|
|
3767
3845
|
return config.ultraFastTier === true;
|
|
3768
3846
|
}
|
|
3769
3847
|
|
|
3848
|
+
/**
|
|
3849
|
+
* Default cadence for the opt-in catalog auto-refresh (issue #3630): one converge pass
|
|
3850
|
+
* per hour. Each pass spends a live /models call against every enabled provider, and
|
|
3851
|
+
* provider catalogs are themselves cached upstream for minutes, so an hour is fresh
|
|
3852
|
+
* enough for newly released models to appear without an `ocx sync`.
|
|
3853
|
+
*/
|
|
3854
|
+
export const CATALOG_AUTO_REFRESH_DEFAULT_INTERVAL_MS: number = 60 * 60_000;
|
|
3855
|
+
|
|
3856
|
+
/**
|
|
3857
|
+
* Floor under the configured cadence, for the same reason src/quota/reset-poller.ts has
|
|
3858
|
+
* MIN_INTERVAL_MS: below this the refresh buys no freshness — upstream caches have not
|
|
3859
|
+
* moved — and only multiplies the chance of a rate limit across every enabled provider.
|
|
3860
|
+
*/
|
|
3861
|
+
export const CATALOG_AUTO_REFRESH_MIN_INTERVAL_MS: number = 15 * 60_000;
|
|
3862
|
+
|
|
3863
|
+
/**
|
|
3864
|
+
* Opt-in master switch, read with the house `=== true` idiom so an absent key and a
|
|
3865
|
+
* malformed one both mean off. Pure on purpose: the scheduler calls this from a
|
|
3866
|
+
* dynamically imported context, so it takes an explicit config slice and reads nothing
|
|
3867
|
+
* global.
|
|
3868
|
+
*/
|
|
3869
|
+
export function isCatalogAutoRefreshEnabled(
|
|
3870
|
+
config: Pick<OcxConfig, "catalogAutoRefresh">,
|
|
3871
|
+
): boolean {
|
|
3872
|
+
return config.catalogAutoRefresh?.enabled === true;
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
/**
|
|
3876
|
+
* Resolved tick interval in milliseconds. An explicit `intervalMinutes: 0` returns 0 —
|
|
3877
|
+
* the section stays configured but the timer stays dormant — and any other value is
|
|
3878
|
+
* clamped up to CATALOG_AUTO_REFRESH_MIN_INTERVAL_MS so a hand edit cannot outrun the
|
|
3879
|
+
* upstream catalog caches. Absent means the hourly default.
|
|
3880
|
+
*/
|
|
3881
|
+
export function resolveCatalogAutoRefreshIntervalMs(
|
|
3882
|
+
config: Pick<OcxConfig, "catalogAutoRefresh">,
|
|
3883
|
+
): number {
|
|
3884
|
+
const minutes = config.catalogAutoRefresh?.intervalMinutes;
|
|
3885
|
+
if (minutes === undefined) return CATALOG_AUTO_REFRESH_DEFAULT_INTERVAL_MS;
|
|
3886
|
+
if (minutes === 0) return 0;
|
|
3887
|
+
return Math.max(CATALOG_AUTO_REFRESH_MIN_INTERVAL_MS, Math.floor(minutes * 60_000));
|
|
3888
|
+
}
|
|
3889
|
+
|
|
3770
3890
|
// ---------------------------------------------------------------------------
|
|
3771
3891
|
// Hand-edit protection for the `claudeCode` subtree (devlog 260726_claude_auth_auto/040 H1).
|
|
3772
3892
|
//
|