@bitkyc08/opencodex 2.82.0 → 2.84.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.
- package/gui/dist/assets/App-CZtqiGcw.js +56 -0
- package/gui/dist/assets/Tray-C9TGtwad.js +1 -0
- package/gui/dist/assets/{index-BAbcj51J.css → index-BB6uK6tU.css} +1 -1
- package/gui/dist/assets/index-CTm4l-HQ.js +94 -0
- package/gui/dist/assets/{quota-summary-DTBC8n7-.js → quota-summary-BbEeRfPY.js} +1 -1
- package/gui/dist/index.html +2 -2
- package/package.json +2 -2
- package/src/adapters/coding-agent/protocol.ts +15 -8
- package/src/adapters/cursor/catalog.ts +2 -2
- package/src/adapters/cursor/effort-map.ts +1 -1
- package/src/adapters/devin/live-models.ts +2 -2
- package/src/adapters/google-truncation.ts +22 -0
- package/src/adapters/google.ts +7 -3
- package/src/adapters/ollama-native.ts +47 -15
- package/src/adapters/openai-chat/messages.ts +8 -4
- package/src/adapters/openai-responses/empty-assistant.ts +32 -0
- package/src/adapters/openai-responses/passthrough.ts +5 -0
- package/src/adapters/openai-responses/plaintext-reasoning-notice.ts +85 -0
- package/src/adapters/openai-responses/reasoning.ts +11 -1
- package/src/adapters/openai-responses/request-strips.ts +10 -2
- package/src/adapters/qoder/adapter.ts +16 -14
- package/src/bridge/errors.ts +26 -1
- package/src/bridge.ts +1 -1
- package/src/claude/context-windows.ts +57 -4
- package/src/claude/desktop-picker.ts +1 -1
- package/src/claude/intercept/connect-proxy.ts +10 -3
- package/src/claude/intercept/picker-ca-persistence.ts +3 -1
- package/src/claude/intercept/picker-listener.ts +49 -1
- package/src/claude/intercept/settings-no-proxy.ts +146 -0
- package/src/claude/intercept/settings.ts +101 -9
- package/src/cli/account-api.ts +65 -0
- package/src/cli/account-auth.ts +44 -12
- package/src/cli/account.ts +41 -5
- package/src/cli/capabilities-access-remote.ts +8 -0
- package/src/cli/capabilities-base.ts +13 -1
- package/src/cli/catalog-command-result.ts +2 -1
- package/src/cli/claude.ts +15 -6
- package/src/cli/config-command.ts +8 -2
- package/src/cli/debug.ts +8 -0
- package/src/cli/dispatch.ts +16 -3
- package/src/cli/export-command.ts +14 -1
- package/src/cli/hub-disable.ts +99 -0
- package/src/cli/hub.ts +4 -2
- package/src/cli/index.ts +13 -4
- package/src/cli/link-child.ts +104 -0
- package/src/cli/link-enrollment.ts +96 -0
- package/src/cli/link.ts +39 -24
- package/src/cli/observe-stream.ts +6 -1
- package/src/cli/observe.ts +10 -2
- package/src/cli/provider.ts +12 -0
- package/src/cli/registry.ts +5 -4
- package/src/cli/resolve.ts +1 -1
- package/src/cli/runtime-api.ts +27 -2
- package/src/cli/status.ts +104 -20
- package/src/client/connect.ts +39 -4
- package/src/client/hub-client.ts +14 -7
- package/src/client/hub-state.ts +25 -14
- package/src/client/link-home.ts +248 -0
- package/src/client/link-management-relay.ts +61 -0
- package/src/client/link-relay.ts +6 -1
- package/src/client/link-status.ts +14 -0
- package/src/client/machine-api.ts +14 -7
- package/src/client/machine-listener.ts +29 -4
- package/src/clients/config-export/model-metadata.ts +16 -0
- package/src/clients/config-export/zcode-store.ts +46 -11
- package/src/clients/config-export/zcode.ts +3 -5
- package/src/clients/config-export.ts +47 -17
- package/src/clients/omo-role-models.ts +6 -3
- package/src/codex/agent-role-models.ts +26 -8
- package/src/codex/auth-api/account-list.ts +17 -2
- package/src/codex/auth-api/account-selection.ts +17 -7
- package/src/codex/auth-api/pool-mode-gate.ts +4 -5
- package/src/codex/auth-api/routes.ts +5 -1
- package/src/codex/auth-context.ts +8 -3
- package/src/codex/autostart-health.ts +3 -1
- package/src/codex/catalog/bundled.ts +5 -1
- package/src/codex/catalog/effort.ts +2 -2
- package/src/codex/catalog/metadata.ts +4 -2
- package/src/codex/catalog/native-models.ts +17 -3
- package/src/codex/catalog/provider-models.ts +25 -0
- package/src/codex/desktop-app/darwin.ts +1 -1
- package/src/codex/desktop-app/handoff.ts +1 -1
- package/src/codex/desktop-app/linux.ts +1 -1
- package/src/codex/desktop-app/lock.ts +1 -1
- package/src/codex/desktop-app/types.ts +1 -1
- package/src/codex/desktop-app/windows.ts +1 -1
- package/src/codex/desktop-app-restart.ts +1 -1
- package/src/codex/main-account.ts +6 -7
- package/src/codex/native-profile-startup.ts +4 -1
- package/src/codex/prompt-journal.ts +20 -2
- package/src/codex/prompt-layers/encoding.ts +49 -0
- package/src/codex/prompt-layers/import-source.ts +30 -0
- package/src/codex/prompt-layers/toml-edit.ts +269 -37
- package/src/codex/prompt-layers/toml-read.ts +52 -4
- package/src/codex/prompt-layers.ts +383 -20
- package/src/codex/prompt-lock-claim.ts +13 -3
- package/src/codex/prompt-lock-evidence.ts +3 -3
- package/src/codex/prompt-lock-owner.ts +14 -6
- package/src/codex/prompt-text-probe.ts +34 -5
- package/src/codex/quota.ts +13 -6
- package/src/codex/role-auto-assign.ts +2 -5
- package/src/codex/routing/active-account.ts +21 -0
- package/src/codex/routing.ts +1 -1
- package/src/codex/runtime.ts +196 -8
- package/src/codex/shim-overlay.ts +8 -4
- package/src/codex/shim.ts +1 -1
- package/src/combos/failover.ts +3 -0
- package/src/config/api-key-reconcile.ts +34 -0
- package/src/config/diagnostics.ts +16 -0
- package/src/config/feature-flags.ts +5 -0
- package/src/config/live-reconcile.ts +43 -29
- package/src/config/live-topology.ts +29 -0
- package/src/config/load-degrade.ts +2 -1
- package/src/config/paths.ts +3 -0
- package/src/config/salvage.ts +3 -1
- package/src/config/schema/config-schema.ts +2 -0
- package/src/generated/compatibility-version.json +373 -217
- package/src/grok/grpc-web.ts +23 -1
- package/src/grok/inject.ts +245 -221
- package/src/grok/reset-coupon-ledger.ts +293 -57
- package/src/grok/reset-coupons.ts +15 -6
- package/src/integrations/cursor-detect.ts +1 -1
- package/src/integrations/mutation-plan.ts +13 -7
- package/src/integrations/registry.ts +45 -11
- package/src/integrations/state.ts +19 -7
- package/src/integrations/target.ts +42 -5
- package/src/integrations/writer.ts +14 -6
- package/src/lib/app-owned-memory-stores.ts +4 -0
- package/src/lib/app-owned-memory.ts +11 -0
- package/src/lib/errors.ts +25 -0
- package/src/lib/json-byte-size.ts +31 -0
- package/src/lib/optional-shutdown-hooks.ts +35 -0
- package/src/lib/outbound-credential-registry.ts +210 -0
- package/src/lib/passive-read.ts +35 -0
- package/src/lib/redact.ts +2 -2
- package/src/lib/shadow-call.ts +44 -5
- package/src/link/codex-settings.ts +155 -0
- package/src/link/management-routes.ts +89 -0
- package/src/link/remote-probe.ts +38 -0
- package/src/link/ssh-argv.ts +26 -5
- package/src/link/ssh-runner.ts +58 -27
- package/src/link/status-projection.ts +22 -4
- package/src/link/supervisor.ts +144 -49
- package/src/link/tunnel-state.ts +11 -4
- package/src/oauth/anthropic-continuity.ts +4 -3
- package/src/oauth/anthropic-identity.ts +13 -2
- package/src/oauth/anthropic-model-quota.ts +13 -1
- package/src/oauth/anthropic-routing.ts +230 -23
- package/src/oauth/anthropic.ts +18 -4
- package/src/oauth/google-antigravity.ts +24 -7
- package/src/oauth/index.ts +25 -16
- package/src/oauth/kiro-account-identity.ts +106 -0
- package/src/oauth/kiro.ts +48 -5
- package/src/oauth/meta-muse-device.ts +1 -1
- package/src/oauth/plan.ts +29 -0
- package/src/oauth/store.ts +40 -3
- package/src/oauth/types.ts +3 -1
- package/src/plugins/loader.ts +11 -0
- package/src/providers/anthropic-billing-ownership.ts +74 -0
- package/src/providers/anthropic-billing-recovery.ts +31 -0
- package/src/providers/anthropic-billing-refusal.ts +55 -0
- package/src/providers/anthropic-fast.ts +1 -1
- package/src/providers/anthropic-reset-admission.ts +62 -0
- package/src/providers/anthropic-reset-grant-ledger.ts +29 -7
- package/src/providers/api-key-resolve.ts +17 -2
- package/src/providers/devin-cli-authmode-migration.ts +1 -1
- package/src/providers/devin-provider-merge-migration.ts +1 -1
- package/src/providers/github-copilot-auto.ts +169 -0
- package/src/providers/key-failover.ts +52 -5
- package/src/providers/model-presets.ts +1 -1
- package/src/providers/model-rename-startup.ts +5 -3
- package/src/providers/muse-subscription-usage.ts +1 -1
- package/src/providers/quota/account-cache.ts +11 -0
- package/src/providers/quota/anthropic-account-quota.ts +4 -2
- package/src/providers/quota/report-cache.ts +14 -0
- package/src/providers/quota/vendor-probes-oauth.ts +3 -3
- package/src/providers/quota.ts +4 -1
- package/src/providers/registry/entries-core.ts +20 -20
- package/src/providers/registry/entries-extended.ts +4 -1
- package/src/providers/registry/model-seeds.ts +20 -3
- package/src/providers/request-pacing.ts +9 -0
- package/src/providers/stale-no-vision-seed-migration.ts +72 -0
- package/src/providers/xai-fast-model.ts +1 -1
- package/src/responses/compaction.ts +14 -0
- package/src/responses/parser.ts +7 -1
- package/src/server/auth-cors.ts +42 -0
- package/src/server/configured-credentials.ts +194 -0
- package/src/server/inbound-body-admission.ts +24 -7
- package/src/server/index/link-listener.ts +30 -17
- package/src/server/index/link-management.ts +58 -0
- package/src/server/index/optional-listeners.ts +5 -1
- package/src/server/index/serve-options.ts +21 -2
- package/src/server/index.ts +1 -1
- package/src/server/lifecycle.ts +33 -5
- package/src/server/management/agent-settings-routes.ts +28 -10
- package/src/server/management/anthropic-reset-grant-routes.ts +17 -1
- package/src/server/management/codex-agent-role-routes.ts +19 -6
- package/src/server/management/codex-prompt-routes.ts +136 -5
- package/src/server/management/codex-role-auto-assign.ts +1 -1
- package/src/server/management/grok-coupon-routes.ts +333 -57
- package/src/server/management/link-enrollment.ts +192 -0
- package/src/server/management/link-route-state.ts +185 -0
- package/src/server/management/link-routes.ts +92 -390
- package/src/server/management/model-rows.ts +3 -1
- package/src/server/management/provider-overwrite-carry.ts +10 -0
- package/src/server/management/provider-routes.ts +1 -0
- package/src/server/management/route-registry.ts +7 -5
- package/src/server/management/shared.ts +3 -0
- package/src/server/management-api.ts +3 -1
- package/src/server/messages-native.ts +68 -42
- package/src/server/relay-eager.ts +4 -0
- package/src/server/relay.ts +18 -7
- package/src/server/request-log-failure-attribution.ts +3 -0
- package/src/server/request-log-filter.ts +6 -1
- package/src/server/request-log-terminal-status.ts +243 -0
- package/src/server/request-log.ts +15 -118
- package/src/server/responses/adapter-continuation.ts +9 -1
- package/src/server/responses/adapter-dispatch.ts +293 -81
- package/src/server/responses/code-mode-collab-surface.ts +205 -0
- package/src/server/responses/codex-ws-exchange.ts +147 -6
- package/src/server/responses/codex-ws-wire.ts +203 -0
- package/src/server/responses/collaboration.ts +36 -7
- package/src/server/responses/compact.ts +129 -50
- package/src/server/responses/context-overflow.ts +13 -1
- package/src/server/responses/core-codex-account.ts +105 -1
- package/src/server/responses/core-combo-failure.ts +14 -0
- package/src/server/responses/core-combo.ts +7 -2
- package/src/server/responses/core-errors.ts +29 -1
- package/src/server/responses/core-opaque-recovery.ts +5 -5
- package/src/server/responses/core-options.ts +2 -0
- package/src/server/responses/core.ts +6 -6
- package/src/server/responses/deferred-collab-surface.ts +158 -0
- package/src/server/responses/deferred-send-reporter.ts +25 -0
- package/src/server/responses/empty-completion-guard.ts +18 -2
- package/src/server/responses/fetch-helpers.ts +12 -1
- package/src/server/responses/jev-model-invoke.ts +1 -1
- package/src/server/responses/passthrough-delivery.ts +4 -1
- package/src/server/responses/passthrough-dispatch.ts +130 -64
- package/src/server/responses/passthrough-execution.ts +3 -3
- package/src/server/responses/request-prepare.ts +6 -4
- package/src/server/responses/request-transport.ts +131 -13
- package/src/server/responses/run-turn-execution.ts +13 -5
- package/src/server/responses/sidecar-execution.ts +16 -2
- package/src/server/responses/spend-storage-error.ts +33 -0
- package/src/server/responses/ws-upstream.ts +9 -1
- package/src/server/startup-action-control.ts +22 -2
- package/src/server/startup-health-cache.ts +4 -0
- package/src/server/system-env-shell.ts +7 -2
- package/src/server/system-env.ts +11 -1
- package/src/service/cli.ts +5 -1
- package/src/service/desktop-startup.ts +147 -34
- package/src/service/desktop-supervision.d.mts +27 -1
- package/src/service/desktop-supervision.mjs +111 -5
- package/src/service/health-sentinel-launch.ts +176 -0
- package/src/service/health-sentinel-main.ts +447 -0
- package/src/service/health-sentinel-policy.ts +241 -0
- package/src/service/health-sentinel-probe.ts +54 -0
- package/src/service/health-sentinel-windows.ts +87 -0
- package/src/service/linux-linger.ts +20 -0
- package/src/types/config.ts +5 -0
- package/src/types/request.ts +5 -0
- package/src/usage/expected-prices.ts +5 -1
- package/src/usage/log.ts +19 -1
- package/gui/dist/assets/App-Ds_qL7o8.js +0 -54
- package/gui/dist/assets/Tray-BqHF5Trd.js +0 -1
- package/gui/dist/assets/index-D3FBCNiP.js +0 -94
|
@@ -327,9 +327,9 @@ async function readAnthropicUsageQuota(accessToken: string): Promise<ProviderQuo
|
|
|
327
327
|
* This endpoint reports quota only. Its body carries `five_hour`, `seven_day`, the
|
|
328
328
|
* model-scoped weekly buckets (`seven_day_fable`/`_opus`/`_sonnet`) and a `limits` array,
|
|
329
329
|
* and **no subscription or tier field** — nor does the OAuth token response, which yields only
|
|
330
|
-
* `account.uuid` and `account.email_address` (`src/oauth/anthropic.ts`).
|
|
331
|
-
*
|
|
332
|
-
*
|
|
330
|
+
* `account.uuid` and `account.email_address` (`src/oauth/anthropic.ts`). Subscription labels
|
|
331
|
+
* instead come from the authenticated profile in `src/oauth/anthropic-identity.ts`, never
|
|
332
|
+
* from this quota response.
|
|
333
333
|
*
|
|
334
334
|
* A tier must not be inferred from what is here. Percentages are normalized per account, so a
|
|
335
335
|
* Max x5 seat at 50% is byte-identical to a Max x20 seat at 50%, and the presence of a
|
package/src/providers/quota.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from "./kiro-usage";
|
|
16
16
|
import { mapQuotaRoster, readProviderApiKeyQuotas, type ProviderApiKeyQuota } from "./quota-key-accounts";
|
|
17
17
|
import type { OcxConfig, OcxProviderConfig } from "../types";
|
|
18
|
+
import { isPassiveRead } from "../lib/passive-read";
|
|
18
19
|
import type { ProviderQuota, QuotaFailureCode } from "./quota-types";
|
|
19
20
|
import {
|
|
20
21
|
accountReportCurrent,
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
captureProviderReportEpochs, providerReportEpochChanged,
|
|
24
25
|
cacheKeyWithAggregationState,
|
|
25
26
|
getProviderQuotaReportCache,
|
|
26
|
-
hasCodexPoolProvider,
|
|
27
|
+
hasCodexPoolProvider, heldProviderQuotaReports,
|
|
27
28
|
inflight,
|
|
28
29
|
invalidationEpoch,
|
|
29
30
|
isBuiltInChatGptForwardProvider,
|
|
@@ -229,6 +230,8 @@ export function flushProviderQuotaObservationsForTests(): Promise<void> {
|
|
|
229
230
|
}
|
|
230
231
|
|
|
231
232
|
export async function fetchProviderQuotaReports(config: OcxConfig, forceRefresh = false): Promise<ProviderQuotaResponse> {
|
|
233
|
+
// A passive read (a Remote Link Child's, #6959) shows the held reports and starts nothing.
|
|
234
|
+
if (isPassiveRead()) return heldProviderQuotaReports(Object.keys(config.providers));
|
|
232
235
|
// A Pool report's cache signature and provider fetch must share one account snapshot.
|
|
233
236
|
// Preserve force semantics when deciding whether that snapshot refreshes upstream data.
|
|
234
237
|
const prefetchedCodexSnapshot = hasCodexPoolProvider(config)
|
|
@@ -32,12 +32,12 @@ import {
|
|
|
32
32
|
OPENAI_API_GPT56_MAX_INPUT_TOKENS,
|
|
33
33
|
OPENAI_API_GPT56_VIRTUAL_MODELS,
|
|
34
34
|
OPENAI_API_GPT56_REASONING_EFFORTS,
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
META_MODEL_API_REASONING_EFFORTS,
|
|
36
|
+
META_MODEL_API_REASONING_EFFORT_MAPS,
|
|
37
37
|
META_MUSE_CODE_REASONING_EFFORTS,
|
|
38
38
|
META_MUSE_CODE_REASONING_EFFORT_MAP,
|
|
39
39
|
META_MUSE_CONTEXT_WINDOW,
|
|
40
|
-
|
|
40
|
+
META_MODEL_API_MODELS,
|
|
41
41
|
OPENAI_DAYBREAK_MODELS,
|
|
42
42
|
OPENAI_DAYBREAK_CONTEXT_WINDOWS,
|
|
43
43
|
OPENAI_DAYBREAK_MAX_INPUT_TOKENS,
|
|
@@ -94,7 +94,7 @@ import {
|
|
|
94
94
|
* Only the models Anthropic documents for the lane are classified; Opus 4.6 silently runs
|
|
95
95
|
* standard and Opus 4.7, Sonnet, Haiku and Fable reject `speed`, so they and future ids stay
|
|
96
96
|
* unclassified. Source: https://platform.claude.com/docs/en/build-with-claude/fast-mode
|
|
97
|
-
* (2026-09-23) and the live probe in devlog/
|
|
97
|
+
* (2026-09-23) and the live probe in devlog/_fin/260923_anthropic_fast_speed.
|
|
98
98
|
*/
|
|
99
99
|
const ANTHROPIC_FAST_WIRE = Object.freeze({
|
|
100
100
|
kind: "anthropic-speed" as const,
|
|
@@ -209,7 +209,7 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
209
209
|
},
|
|
210
210
|
{
|
|
211
211
|
// The canonical Cognition account provider, after absorbing `devin-cli`
|
|
212
|
-
// (devlog/
|
|
212
|
+
// (devlog/_fin/260913_devin_provider_merge). The two ids were the same
|
|
213
213
|
// `devin` adapter, the same server.codeium.com api-server, and the same
|
|
214
214
|
// `devin-session-token$<JWT>` credential — only the account source
|
|
215
215
|
// differed: this entry did an Auth0 browser sign-in while `devin-cli`
|
|
@@ -273,7 +273,7 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
273
273
|
// the field but answers service_tier "default" — a live downgrade, not a fast tier.
|
|
274
274
|
// Unlisted and future-discovered ids stay unclassified.
|
|
275
275
|
// grok-4.7 applied and confirmed priority on OAuth Responses in the 2026-09-23
|
|
276
|
-
// live probe: devlog/
|
|
276
|
+
// live probe: devlog/_fin/260923_grok47_parity/010_probe-evidence.md.
|
|
277
277
|
modelSupportsServiceTier: {
|
|
278
278
|
"grok-4.7": true,
|
|
279
279
|
"grok-4.6": true,
|
|
@@ -320,7 +320,7 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
320
320
|
models: XAI_MODELS,
|
|
321
321
|
// grok-4.7-build-fast arrives only through OAuth discovery: xAI's Grok 4.7 Fast, "the same model
|
|
322
322
|
// served on faster infrastructure" (docs.x.ai/developers/grok-4-7). Probed 2026-09-30
|
|
323
|
-
// (devlog/
|
|
323
|
+
// (devlog/_fin/260930_grok47_build_unify/010_probe-evidence.md): identical effort ladder, image
|
|
324
324
|
// input, 500k limit and advertised defaults, 1.5-1.7x faster, ~2x the ticks per output token. It is
|
|
325
325
|
// not a second model row: shouldExposeProviderModel hides it, and grok-4.7's Fast selection on OAuth
|
|
326
326
|
// serializes it (src/providers/xai-fast-model.ts). It keeps grok-4.7's facts in the lists below so an
|
|
@@ -450,7 +450,7 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
450
450
|
// documents high as the 4.6 default but no multi-agent default, so do not invent one.
|
|
451
451
|
modelReasoningEfforts: {
|
|
452
452
|
// 2026-09-23 live probe accepted low..xhigh and rejected max on both wires;
|
|
453
|
-
// devlog/
|
|
453
|
+
// devlog/_fin/260923_grok47_parity/010_probe-evidence.md.
|
|
454
454
|
"grok-4.7": ["low", "medium", "high", "xhigh"],
|
|
455
455
|
"grok-4.7-build-fast": ["low", "medium", "high", "xhigh"],
|
|
456
456
|
"grok-4.6": ["low", "medium", "high", "xhigh"],
|
|
@@ -460,7 +460,7 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
460
460
|
modelDefaultReasoningEfforts: { "grok-4.7": "high", "grok-4.7-build-fast": "high", "grok-4.6": "high" },
|
|
461
461
|
modelContextWindows: {
|
|
462
462
|
// 500k confirmed by context_length_exceeded:
|
|
463
|
-
// devlog/
|
|
463
|
+
// devlog/_fin/260923_grok47_parity/010_probe-evidence.md.
|
|
464
464
|
"grok-4.7": 500_000,
|
|
465
465
|
"grok-4.7-build-fast": 500_000,
|
|
466
466
|
"grok-4.6": 500_000,
|
|
@@ -736,7 +736,7 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
736
736
|
authKind: "key",
|
|
737
737
|
dashboardUrl: "https://dev.meta.ai/docs/authentication",
|
|
738
738
|
defaultModel: "muse-spark-1.3",
|
|
739
|
-
models:
|
|
739
|
+
models: META_MODEL_API_MODELS,
|
|
740
740
|
// Static roster: no authenticated /v1/models payload was ever observed (the only
|
|
741
741
|
// contact was an unauthenticated GET returning 401 invalid_api_key), and Meta serves
|
|
742
742
|
// non-agent families on this same base URL. Turning discovery on would publish an
|
|
@@ -746,20 +746,20 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
746
746
|
// without this, registry transport canonicalization would retarget it and send their
|
|
747
747
|
// saved key to Meta.
|
|
748
748
|
preserveCustomDestination: true,
|
|
749
|
-
modelContextWindows: Object.fromEntries(
|
|
749
|
+
modelContextWindows: Object.fromEntries(META_MODEL_API_MODELS.map(id => [id, META_MUSE_CONTEXT_WINDOW])),
|
|
750
750
|
// text+image only. Meta also documents video, audio (degraded on 1.3), and PDF, but
|
|
751
751
|
// the catalog modality enum is text/image and over-advertising poisons the exported
|
|
752
752
|
// client config (see tests/codex-integration/catalog-input-modality-enum.test.ts).
|
|
753
|
-
modelInputModalities: Object.fromEntries(
|
|
754
|
-
modelReasoningEfforts:
|
|
755
|
-
modelReasoningEffortMap:
|
|
753
|
+
modelInputModalities: Object.fromEntries(META_MODEL_API_MODELS.map(id => [id, ["text", "image"] as ["text", "image"]])),
|
|
754
|
+
modelReasoningEfforts: META_MODEL_API_REASONING_EFFORTS,
|
|
755
|
+
modelReasoningEffortMap: META_MODEL_API_REASONING_EFFORT_MAPS,
|
|
756
756
|
// No defaultMaxOutputTokens: Meta publishes none. The only number in its docs
|
|
757
757
|
// (131072) appears inside a third-party config sample, and the protocol pages call
|
|
758
758
|
// the real limit "model-dependent".
|
|
759
759
|
// Meta names its variable MODEL_API_KEY, but the env var opencodex reads is derived
|
|
760
760
|
// from the provider id (META_MODEL_API_KEY). Saying only Meta's name would send a
|
|
761
761
|
// user to export a variable this proxy never reads.
|
|
762
|
-
note: "Pay-as-you-go Meta Model API. Get a key at https://dev.meta.ai (Meta calls it MODEL_API_KEY; export it here as META_MODEL_API_KEY) — a Meta developer account needs a payment method before it can serve requests, and every call is metered per token. A Muse Code subscription does NOT work here: Meta scopes that credential to the Muse Code CLI and bills any other key pay-as-you-go (dev.meta.ai/docs/muse-code/subscriptions). The Contributor tier (muse-spark-1.3-contributor) is cheap because Meta trains on your prompts — about 92% off input, 95% off output, 99% off cached input; do not send confidential material through it. Muse Spark is also reachable through resellers: command-code carries both tiers, opencode-go serves only muse-spark-1.3-contributor.",
|
|
762
|
+
note: "Pay-as-you-go Meta Model API. Get a key at https://dev.meta.ai (Meta calls it MODEL_API_KEY; export it here as META_MODEL_API_KEY) — a Meta developer account needs a payment method before it can serve requests, and every call is metered per token. A Muse Code subscription does NOT work here: Meta scopes that credential to the Muse Code CLI and bills any other key pay-as-you-go (dev.meta.ai/docs/muse-code/subscriptions). The Contributor tier (muse-spark-1.3-contributor) is cheap because Meta trains on your prompts — about 92% off input, 95% off output, 99% off cached input; do not send confidential material through it. Muse Wonder (muse-wonder-1.0, preview) is Standard mode only on this API ($4 input / $20 output per 1M tokens, no Contributor tier) and accepts reasoning effort up to max; the Spark rows stop at xhigh. Muse Spark is also reachable through resellers: command-code carries both tiers, opencode-go serves only muse-spark-1.3-contributor.",
|
|
763
763
|
},
|
|
764
764
|
/* [Decision Log]
|
|
765
765
|
- 목적과 의도: Let an operator who already signed the Muse Code CLI in reach Muse Spark with that credential, instead of provisioning a second key.
|
|
@@ -787,14 +787,14 @@ export const PROVIDER_REGISTRY_CORE: readonly ProviderRegistryEntry[] = [
|
|
|
787
787
|
oauthId: "meta-muse",
|
|
788
788
|
dashboardUrl: "https://dev.meta.ai",
|
|
789
789
|
defaultModel: "muse-spark-1.3",
|
|
790
|
-
models:
|
|
790
|
+
models: META_MODEL_API_MODELS,
|
|
791
791
|
// Same reason as meta-model: the authenticated roster carries muse-image-1.0 and
|
|
792
792
|
// muse-voice-transcribe-1.0, which this Responses-agent provider cannot drive.
|
|
793
793
|
liveModels: false,
|
|
794
|
-
modelContextWindows: Object.fromEntries(
|
|
795
|
-
modelInputModalities: Object.fromEntries(
|
|
796
|
-
modelReasoningEfforts: Object.fromEntries(
|
|
797
|
-
modelReasoningEffortMap: Object.fromEntries(
|
|
794
|
+
modelContextWindows: Object.fromEntries(META_MODEL_API_MODELS.map(id => [id, META_MUSE_CONTEXT_WINDOW])),
|
|
795
|
+
modelInputModalities: Object.fromEntries(META_MODEL_API_MODELS.map(id => [id, ["text", "image"] as ["text", "image"]])),
|
|
796
|
+
modelReasoningEfforts: Object.fromEntries(META_MODEL_API_MODELS.map(id => [id, META_MUSE_CODE_REASONING_EFFORTS])),
|
|
797
|
+
modelReasoningEffortMap: Object.fromEntries(META_MODEL_API_MODELS.map(id => [id, META_MUSE_CODE_REASONING_EFFORT_MAP])),
|
|
798
798
|
note: "Signs in to Meta with a browser device code on any platform, then mints the Muse Code subscription key. That grant is reimplemented from the one the Muse Code CLI performs and has NOT been exercised against Meta from OpenCodex, so treat the first login as unverified. If the Muse Code CLI is already signed in on macOS, the existing key is imported instead of starting a new grant. A pasted key from https://dev.meta.ai still works as a fallback when a device login cannot complete, and faces the same format check and live validation. A device login authenticates as Meta own Muse Code client, which is a stronger claim than reusing a key the CLI already minted. Meta scopes that credential to the Muse Code CLI, so this is an UNSUPPORTED use: Meta does not authorize subscription coverage outside its own CLI, how these calls settle is not observable from the API, and you should treat every call as billable against your account. The key, imported or pasted, is copied into OpenCodex's auth store. For an account signed in with the device login, OpenCodex refreshes Meta's subscription windows on demand from the same key endpoint the login uses, at most once every five minutes. For an imported or pasted key there is no endpoint to query them on demand, so OpenCodex reads them from streaming responses and shows the last observed value with its age; refreshing one then requires another streaming turn, and translated (non-passthrough) turns report none. Rate limits apply per team, not per key. For a supported path use the meta-model provider with your own key (export it as META_MODEL_API_KEY).",
|
|
799
799
|
},
|
|
800
800
|
{
|
|
@@ -1176,6 +1176,10 @@ export const PROVIDER_REGISTRY_EXTENDED: readonly ProviderRegistryEntry[] = [
|
|
|
1176
1176
|
"openai/o3-pro": ["text"],
|
|
1177
1177
|
},
|
|
1178
1178
|
noVisionModels: ["openai/o3-pro"],
|
|
1179
|
+
// #6877: on the Responses wire OpenGateway answers 400 once history replays native
|
|
1180
|
+
// custom_tool_call/custom_tool_call_output items (Codex code-mode exec), and accepts the
|
|
1181
|
+
// same request after the custom tool is lowered to a function. Same contract as xAI.
|
|
1182
|
+
supportsResponsesCustomTools: false,
|
|
1179
1183
|
// Chat is the broad wire (77/80 active rows). o3-pro is Responses-only, on all
|
|
1180
1184
|
// inbounds. Only the two live-verified Sionic models bypass translation for Codex.
|
|
1181
1185
|
// Other OpenAI/Anthropic/Gemini rows stay on Chat until their Responses tool replay
|
|
@@ -1464,7 +1468,6 @@ export const PROVIDER_REGISTRY_EXTENDED: readonly ProviderRegistryEntry[] = [
|
|
|
1464
1468
|
models: [...QODER_GLOBAL_MODELS],
|
|
1465
1469
|
liveModels: true,
|
|
1466
1470
|
reasoningEfforts: [...QODER_REASONING_EFFORTS],
|
|
1467
|
-
noVisionModels: [...QODER_GLOBAL_MODELS],
|
|
1468
1471
|
note: "Official Qoder Global CLI using QODER_PERSONAL_ACCESS_TOKEN. Models are discovered per account with `qoder --list-models`; the documented roster is a degraded fallback. The CLI runs single-turn with tools, MCP, settings hooks, and session persistence disabled. Requires `npm install -g @qoder-ai/qodercli`.",
|
|
1469
1472
|
},
|
|
1470
1473
|
{
|
|
@@ -129,7 +129,7 @@ export const ZAI_GLM_5X_SIDECAR_VISION_MODELS = ZAI_GLM_5X_MODELS.filter(id => i
|
|
|
129
129
|
*
|
|
130
130
|
* Authoritative source: `GET https://api.z.ai/api/v1/models` returns `input_modalities:
|
|
131
131
|
* ["text"]` for glm-5.3 and `["text", "image"]` for glm-5.3-flash (captured in
|
|
132
|
-
* devlog/
|
|
132
|
+
* devlog/_fin/260912_zcode_protocol_and_catalog/evidence/zai-responses-models.json).
|
|
133
133
|
* docs.z.ai/devpack/latest-model says the same in prose: "GLM-5.3 is a text-only model...
|
|
134
134
|
* GLM-5.3-FLASH is a multimodal model". Upstream also lists video and file for Flash;
|
|
135
135
|
* neither the internal vocabulary nor the export vocabulary can express them, so `image`
|
|
@@ -158,7 +158,7 @@ export const ZAI_GLM_5X_REASONING_EFFORTS: Record<string, string[]> = {
|
|
|
158
158
|
// 260930 MiniMax-M3.1-Flash-Preview: Token Plan / MiniMax Code only, 1M context, thinking
|
|
159
159
|
// always on (effort none or thinking disabled answers 400 code 2013), omitted effort = max.
|
|
160
160
|
// It returns thinking as reasoning_content and ignores reasoning_split. The live /v1/models
|
|
161
|
-
// roster does not list it yet. Evidence: devlog/
|
|
161
|
+
// roster does not list it yet. Evidence: devlog/_fin/260930_minimax_m31_flash_preview/.
|
|
162
162
|
export const MINIMAX_M31_FLASH_PREVIEW = "MiniMax-M3.1-Flash-Preview";
|
|
163
163
|
export const MINIMAX_MODELS = [
|
|
164
164
|
MINIMAX_M31_FLASH_PREVIEW,
|
|
@@ -255,6 +255,23 @@ export const META_MUSE_CODE_REASONING_EFFORT_MAP: Record<string, string> = Objec
|
|
|
255
255
|
/** Both Muse Spark 1.3 tiers publish a 1,048,576-token window (dev.meta.ai/docs/models). */
|
|
256
256
|
export const META_MUSE_CONTEXT_WINDOW = 1_048_576;
|
|
257
257
|
export const META_MUSE_MODELS = ["muse-spark-1.3", "muse-spark-1.3-contributor"];
|
|
258
|
+
/*
|
|
259
|
+
* Muse Wonder (preview), announced 2026-10-12 (research.meta.ai/blog/muse-wonder). Per
|
|
260
|
+
* dev.meta.ai/docs/models and dev.meta.ai/docs/pricing-rate-limits, verified 2026-10-13:
|
|
261
|
+
* id muse-wonder-1.0, a 1,048,576-token window, reasoning effort "minimal" through "max",
|
|
262
|
+
* and Standard mode only on the Model API (no Contributor variant). Muse Wonder Full is
|
|
263
|
+
* reachable only inside Muse Code subscriptions and has no Model API id, so it is absent.
|
|
264
|
+
*/
|
|
265
|
+
export const META_MUSE_WONDER_MODEL = "muse-wonder-1.0";
|
|
266
|
+
/** Roster both direct Meta providers serve: the Spark 1.3 tiers plus Muse Wonder. */
|
|
267
|
+
export const META_MODEL_API_MODELS = [...META_MUSE_MODELS, META_MUSE_WONDER_MODEL];
|
|
268
|
+
/** Model API ladders: Spark stops at xhigh; Wonder documents minimal..max. */
|
|
269
|
+
export const META_MODEL_API_REASONING_EFFORTS: Record<string, string[]> = Object.fromEntries(
|
|
270
|
+
META_MODEL_API_MODELS.map(id => [id, id === META_MUSE_WONDER_MODEL ? META_MUSE_CODE_REASONING_EFFORTS : META_MUSE_REASONING_EFFORTS]),
|
|
271
|
+
);
|
|
272
|
+
export const META_MODEL_API_REASONING_EFFORT_MAPS: Record<string, Record<string, string>> = Object.fromEntries(
|
|
273
|
+
META_MODEL_API_MODELS.map(id => [id, id === META_MUSE_WONDER_MODEL ? META_MUSE_CODE_REASONING_EFFORT_MAP : META_MUSE_REASONING_EFFORT_MAP]),
|
|
274
|
+
);
|
|
258
275
|
/**
|
|
259
276
|
* Daybreak program aliases. These `-latest` ids are the stable contract: OpenAI repoints
|
|
260
277
|
* them at newer snapshots over time (red -> gpt-5.6-cyber, blue -> gpt-5.6-sol as of
|
|
@@ -416,7 +433,7 @@ export const COMMAND_CODE_IMAGE_MODELS = [
|
|
|
416
433
|
// Live 2026-09-23 3x3 random-color grid (180x180) via ocx 2.62.0:
|
|
417
434
|
// 4.7 read 9/9 in user messages and tool results; 4.6 read 9/9 and 8/9.
|
|
418
435
|
// Neither route requested a vision sidecar. Evidence:
|
|
419
|
-
// devlog/
|
|
436
|
+
// devlog/_fin/260923_grok47_parity/010_probe-evidence.md.
|
|
420
437
|
"xai/grok-4.6",
|
|
421
438
|
"xai/grok-4.7",
|
|
422
439
|
// Native Z.AI VLM (docs.z.ai/guides/vlm/glm-5.3-flash). This exact id is already
|
|
@@ -33,6 +33,12 @@ export const REQUEST_PACING_CONCURRENCY_RETRY_AFTER_SECONDS = 5;
|
|
|
33
33
|
let maxQueueDepth = REQUEST_PACING_MAX_QUEUE_DEPTH;
|
|
34
34
|
let maxQueueAgeMs = REQUEST_PACING_MAX_QUEUE_AGE_MS;
|
|
35
35
|
|
|
36
|
+
// Optional owners register internal response markers; only this owned body rewrap carries them.
|
|
37
|
+
const responseProvenance = new Set<WeakMap<Response, unknown>>();
|
|
38
|
+
export function registerProviderResponseProvenance(markers: WeakMap<Response, unknown>): void {
|
|
39
|
+
responseProvenance.add(markers);
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
export type RequestPacingQueueOverloadReason = "queue_full" | "queue_expired";
|
|
37
43
|
|
|
38
44
|
export class RequestPacingQueueOverloadError extends Error {
|
|
@@ -588,6 +594,9 @@ export function trackProviderRequestSlotBody(
|
|
|
588
594
|
// Retry helpers mark the response they return from, and recovery decisions key on these
|
|
589
595
|
// identity markers; the rewrap must not make a non-replayable response look replayable.
|
|
590
596
|
if (isNonReplayableResponse(response)) markResponseNonReplayable(wrapped);
|
|
597
|
+
for (const markers of responseProvenance) {
|
|
598
|
+
if (markers.has(response)) markers.set(wrapped, markers.get(response));
|
|
599
|
+
}
|
|
591
600
|
return carryReplayRefusal(response, wrapped);
|
|
592
601
|
}
|
|
593
602
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drop a saved `noVisionModels` list that is still, byte for byte, a retired registry seed.
|
|
3
|
+
*
|
|
4
|
+
* `enrichProviderFromRegistry` fills `noVisionModels` all-or-nothing, so a provider row saved
|
|
5
|
+
* while the registry seeded a blanket list keeps that list after the registry stops seeding it.
|
|
6
|
+
* Qoder Global seeded its whole static discovery roster as text-only until the Global adapter
|
|
7
|
+
* began forwarding image input to the Qoder CLI (#6906). The saved copy would keep every image
|
|
8
|
+
* on the vision sidecar path, stripped or captioned before the adapter could forward it.
|
|
9
|
+
*
|
|
10
|
+
* This projection removes one thing: a saved list identical, in order, to a seed this file names,
|
|
11
|
+
* on a row the registry still owns (same adapter, and the registry transport rule enrichment uses),
|
|
12
|
+
* and only while the registry no longer seeds the list at all. Any edited list does not match and
|
|
13
|
+
* is left alone. `modelCapabilities` and `modelInputModalities` are untouched; they are where a
|
|
14
|
+
* deliberate per-model text-only declaration belongs.
|
|
15
|
+
*/
|
|
16
|
+
import { PROVIDER_REGISTRY, providerMatchesRegistryTransport } from "./registry";
|
|
17
|
+
import type { OcxConfig } from "../types";
|
|
18
|
+
|
|
19
|
+
export interface StaleNoVisionSeed {
|
|
20
|
+
/** Registry provider id whose saved rows may carry the retired list. */
|
|
21
|
+
provider: string;
|
|
22
|
+
/** Every list the registry ever seeded, in seed order; only an exact match is removed. */
|
|
23
|
+
seeds: readonly (readonly string[])[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface StaleNoVisionSeedProjection {
|
|
27
|
+
config: OcxConfig;
|
|
28
|
+
changed: boolean;
|
|
29
|
+
warnings: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const STALE_NO_VISION_SEEDS: readonly StaleNoVisionSeed[] = [
|
|
33
|
+
{
|
|
34
|
+
provider: "qoder",
|
|
35
|
+
seeds: [
|
|
36
|
+
// 2026-09-03 (Qoder Global PAT provider) until the DeepSeek V4.1 transition (#4282).
|
|
37
|
+
["Qwen3.8-Max", "Qwen3.7-Max", "Qwen3.7-Plus", "Kimi-K3", "Kimi-K2.7-Code", "GLM-5.3", "GLM-5.2", "DeepSeek-V4-Pro"],
|
|
38
|
+
// #4282 until Global image input (#6906).
|
|
39
|
+
["Qwen3.8-Max", "Qwen3.7-Max", "Qwen3.7-Plus", "Kimi-K3", "Kimi-K2.7-Code", "GLM-5.3", "GLM-5.2"],
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
function sameList(current: readonly unknown[], expected: readonly string[]): boolean {
|
|
45
|
+
return current.length === expected.length && current.every((value, index) => value === expected[index]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Pure projection. The caller decides whether to persist. */
|
|
49
|
+
export function projectStaleNoVisionSeeds(
|
|
50
|
+
config: OcxConfig,
|
|
51
|
+
entries: readonly StaleNoVisionSeed[] = STALE_NO_VISION_SEEDS,
|
|
52
|
+
): StaleNoVisionSeedProjection {
|
|
53
|
+
const warnings: string[] = [];
|
|
54
|
+
let changed = false;
|
|
55
|
+
for (const entry of entries) {
|
|
56
|
+
const prov = config.providers?.[entry.provider];
|
|
57
|
+
if (!prov || !Array.isArray(prov.noVisionModels)) continue;
|
|
58
|
+
const registry = PROVIDER_REGISTRY.find(row => row.id === entry.provider);
|
|
59
|
+
// While the registry still seeds a list, the saved one is not stale by this file's rule.
|
|
60
|
+
if (!registry || registry.noVisionModels !== undefined || registry.adapter !== prov.adapter) continue;
|
|
61
|
+
if (!providerMatchesRegistryTransport(entry.provider, prov)) continue;
|
|
62
|
+
const saved = prov.noVisionModels;
|
|
63
|
+
if (!entry.seeds.some(seed => sameList(saved, seed))) continue;
|
|
64
|
+
delete prov.noVisionModels;
|
|
65
|
+
changed = true;
|
|
66
|
+
warnings.push(
|
|
67
|
+
`removed the retired registry noVisionModels seed (${saved.length} model(s)) from "${entry.provider}"; `
|
|
68
|
+
+ "image input now follows the provider's current classification.",
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return { config, changed, warnings };
|
|
72
|
+
}
|
|
@@ -7,7 +7,7 @@ import type { FastWire, OcxParsedRequest, OcxProviderConfig, TierDecision } from
|
|
|
7
7
|
* on two lanes (same effort ladder, image input, 500k limit and advertised defaults). Measured live on
|
|
8
8
|
* 2026-09-30: build-fast is 1.5-1.7x faster end to end, while `service_tier: "priority"` on grok-4.7 bought
|
|
9
9
|
* no measurable speed and cost ~5.9x the ticks per output token (build-fast costs ~2x).
|
|
10
|
-
* Evidence: devlog/
|
|
10
|
+
* Evidence: devlog/_fin/260930_grok47_build_unify/010_probe-evidence.md.
|
|
11
11
|
*
|
|
12
12
|
* So on the OAuth lane only, a Fast grok-4.7 request is SERIALIZED as the build-fast id and sends no tier.
|
|
13
13
|
* The logical id stays grok-4.7 everywhere else (parsed.modelId, route, policy, usage attempt), so effort,
|
|
@@ -56,6 +56,20 @@ export const SUMMARY_PREFIX = "Another language model started to solve this prob
|
|
|
56
56
|
|
|
57
57
|
export const OPAQUE_COMPACTION_NOTE = "[earlier conversation was compacted; the summary is stored in a format this model cannot read]";
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Prompt contract for a routed model receiving a decoded `ocx1` checkpoint as user text (#6764).
|
|
61
|
+
* It preserves existing authorization scope and permission gates; it grants no authority.
|
|
62
|
+
* Kept apart from SUMMARY_PREFIX, which the v1 retention and recovery paths match exactly.
|
|
63
|
+
*/
|
|
64
|
+
export const CHECKPOINT_CONTINUATION_NOTE = "This conversation was compacted automatically. A checkpoint summary from an earlier context window appears as a user message and records prior work. Treat earlier requests it reports as completed as history; do not repeat them unless a later user message asks you to. Continue an unfinished task only when it was already authorized and remains within the scope of that authorization. Do not ask for the same authorization again while it still applies. Preserve all existing permission and confirmation gates; if a decision or required permission is pending, wait for it before taking the dependent action. A checkpoint or delegation, including one from another thread, does not itself grant authority or expand the task's scope. Later user messages take priority; obey any pause, cancellation, replacement, or change of scope.";
|
|
65
|
+
|
|
66
|
+
/** Append the continuation note to existing instructions once. */
|
|
67
|
+
export function appendCheckpointContinuationNote(instructions: unknown): string {
|
|
68
|
+
const existing = typeof instructions === "string" ? instructions : "";
|
|
69
|
+
if (existing.includes(CHECKPOINT_CONTINUATION_NOTE)) return existing;
|
|
70
|
+
return existing.trim().length > 0 ? `${existing}\n\n${CHECKPOINT_CONTINUATION_NOTE}` : CHECKPOINT_CONTINUATION_NOTE;
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
/**
|
|
60
74
|
* Item types in the compact wire family. Each carries an `encrypted_content` blob the client
|
|
61
75
|
* replays verbatim on every later turn, and the minting backend verifies it is unmodified.
|
package/src/responses/parser.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { createToolChoiceResolver, namespacedToolName } from "../types";
|
|
|
15
15
|
import { responsesRequestSchema } from "./schema";
|
|
16
16
|
import { providerMetadataFromResponsesFunctionCall } from "./provider-opaque-metadata";
|
|
17
17
|
import { lookupReplayThoughtSignature } from "./thought-signature-replay";
|
|
18
|
-
import { compactionItemToText, isCompactionItemType } from "./compaction";
|
|
18
|
+
import { CHECKPOINT_CONTINUATION_NOTE, compactionItemToText, decodeCompactionSummary, isCompactionItemType } from "./compaction";
|
|
19
19
|
import { previousResponseReplayPrefixLength } from "./state";
|
|
20
20
|
import { decodeReasoningEnvelope } from "./reasoning-envelope";
|
|
21
21
|
import { hasRoutedIdentity, nameRoutedIdentity } from "../adapters/identity";
|
|
@@ -193,6 +193,7 @@ export function parseRequest(
|
|
|
193
193
|
// Remote compaction v2: the input tail carries `{type:"compaction_trigger"}` and Codex expects a
|
|
194
194
|
// synthetic `{type:"compaction"}` output item (src/responses/compaction.ts). Flagged for the server.
|
|
195
195
|
let compactionRequest = false;
|
|
196
|
+
let decodedCheckpoint = false;
|
|
196
197
|
let contextCompactionBoundary = false;
|
|
197
198
|
let continuationConversationMessageIndex: number | undefined;
|
|
198
199
|
|
|
@@ -261,6 +262,7 @@ export function parseRequest(
|
|
|
261
262
|
if (inputIndex >= replayedInputPrefixLength) contextCompactionBoundary = true;
|
|
262
263
|
const encrypted = (item as { encrypted_content?: unknown }).encrypted_content;
|
|
263
264
|
if (effectiveType === "context_compaction" && typeof encrypted !== "string") continue;
|
|
265
|
+
if (typeof encrypted === "string" && decodeCompactionSummary(encrypted) !== null) decodedCheckpoint = true;
|
|
264
266
|
pendingReasoning.length = 0;
|
|
265
267
|
messages.push({
|
|
266
268
|
role: "user",
|
|
@@ -586,6 +588,10 @@ export function parseRequest(
|
|
|
586
588
|
.map(t => loadedToolNames.has(namespacedToolName(t.namespace, t.name))
|
|
587
589
|
? { ...t, loadedFromToolSearch: true }
|
|
588
590
|
: t);
|
|
591
|
+
// #6764: the decoded checkpoint is ordinary user text on this route. Say in the system prompt
|
|
592
|
+
// what it is, so a retained earlier request that it reports as completed is not repeated.
|
|
593
|
+
// A compaction request is a summarizer turn and must not be told to continue.
|
|
594
|
+
if (decodedCheckpoint && !compactionRequest) systemPrompt.push(CHECKPOINT_CONTINUATION_NOTE);
|
|
589
595
|
const context: OcxContext = {
|
|
590
596
|
...(systemPrompt.length > 0 ? { systemPrompt } : {}),
|
|
591
597
|
messages,
|
package/src/server/auth-cors.ts
CHANGED
|
@@ -47,6 +47,18 @@ import { googleVertexLocationConfigError } from "../providers/google-vertex-loca
|
|
|
47
47
|
import { xaiResponsesOptInState } from "../providers/xai-responses-opt-in";
|
|
48
48
|
|
|
49
49
|
let _corsOrigin = "http://localhost:10100";
|
|
50
|
+
// Listener identity is process-local. Never infer this trust from forwarded headers: the
|
|
51
|
+
// request handler marks a Request only after resolving the actual Bun Server instance.
|
|
52
|
+
const trustedHubManagementRequests = new WeakSet<Request>();
|
|
53
|
+
|
|
54
|
+
export function markTrustedHubManagementRequest(req: Request): void {
|
|
55
|
+
trustedHubManagementRequests.add(req);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function inheritTrustedHubManagementRequest(source: Request, target: Request): void {
|
|
59
|
+
if (trustedHubManagementRequests.has(source)) trustedHubManagementRequests.add(target);
|
|
60
|
+
}
|
|
61
|
+
|
|
50
62
|
export function setCorsOrigin(port: number): void { _corsOrigin = `http://localhost:${port}`; }
|
|
51
63
|
/** The proxy's own listening port. No admission check uses it: both loopback predicates key on hostname alone. */
|
|
52
64
|
export function configuredPort(): string {
|
|
@@ -144,6 +156,24 @@ export function managementRequestOrigin(req: Request, config: OcxConfig): string
|
|
|
144
156
|
return null;
|
|
145
157
|
}
|
|
146
158
|
}
|
|
159
|
+
if (trustedHubManagementRequests.has(req)) {
|
|
160
|
+
if (config.runtimeRole !== "hub") return null;
|
|
161
|
+
const canonical = canonicalHubManagementOrigin(config.hub?.managementPublicOrigin);
|
|
162
|
+
if (!canonical) return null;
|
|
163
|
+
try {
|
|
164
|
+
// The dedicated listener may receive HTTP from a local TLS terminator, so its URL
|
|
165
|
+
// scheme is not authoritative. Host must still name exactly the configured public
|
|
166
|
+
// authority; forwarded host/proto headers are deliberately ignored.
|
|
167
|
+
const requestAuthority = new URL(`https://${host}`);
|
|
168
|
+
if (requestAuthority.username || requestAuthority.password || requestAuthority.pathname !== "/"
|
|
169
|
+
|| requestAuthority.search || requestAuthority.hash || requestAuthority.host !== new URL(canonical).host) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
return canonical;
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
147
177
|
if (!isApiAuthRequired(config)) return null;
|
|
148
178
|
if (config.runtimeRole === "hub" && config.hub?.managementPublicOrigin) {
|
|
149
179
|
try {
|
|
@@ -437,6 +467,18 @@ export function resolveDataPlaneAdmissionSecret(
|
|
|
437
467
|
return null;
|
|
438
468
|
}
|
|
439
469
|
|
|
470
|
+
function canonicalHubManagementOrigin(value: unknown): string | null {
|
|
471
|
+
if (typeof value !== "string") return null;
|
|
472
|
+
try {
|
|
473
|
+
const parsed = new URL(value);
|
|
474
|
+
if (parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.pathname !== "/"
|
|
475
|
+
|| parsed.search || parsed.hash) return null;
|
|
476
|
+
return parsed.origin;
|
|
477
|
+
} catch {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
440
482
|
/** The principal an authenticated admission belongs to, or undefined for loopback. */
|
|
441
483
|
export function contextPrincipalIdOf(admission: DataPlaneAdmission | undefined): string | undefined {
|
|
442
484
|
return admission && "contextPrincipalId" in admission ? admission.contextPrincipalId : undefined;
|