@bitkyc08/opencodex 2.59.0 → 2.61.0-preview.20260922
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/AGENTS_INSTALL.md +64 -0
- package/README.md +28 -1
- package/bin/ocx.mjs +382 -209
- package/gui/dist/assets/App-E64Rzjap.js +50 -0
- package/gui/dist/assets/Tray-_nfzD8k4.js +1 -0
- package/gui/dist/assets/index-DpdfZWMK.js +86 -0
- package/gui/dist/assets/index-_bpvxJu0.css +1 -0
- package/gui/dist/assets/usage-companion-chart-DtoK7T6h.js +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/stepfun-color.svg +1 -0
- package/package.json +8 -1
- package/src/adapters/anthropic-image-codec.ts +16 -2
- package/src/adapters/anthropic-image-normalize.ts +49 -2
- package/src/adapters/anthropic.ts +20 -1
- package/src/adapters/base.ts +23 -0
- package/src/adapters/coding-agent/protocol.ts +36 -6
- package/src/adapters/coding-agent/turn.ts +32 -4
- package/src/adapters/command-code.ts +52 -4
- package/src/adapters/cursor/catalog.ts +51 -7
- package/src/adapters/cursor/checkpoint-store.ts +3 -0
- package/src/adapters/cursor/discovery.ts +11 -8
- package/src/adapters/cursor/live-transport.ts +26 -9
- package/src/adapters/cursor/protobuf-request.ts +6 -3
- package/src/adapters/cursor/request-builder.ts +20 -4
- package/src/adapters/cursor/transport.ts +19 -0
- package/src/adapters/cursor.ts +14 -3
- package/src/adapters/declaration-carrier.ts +45 -0
- package/src/adapters/devin/cloud-direct/chat.ts +3 -1
- package/src/adapters/devin/cloud-direct/stated-reset-retry.ts +42 -5
- package/src/adapters/devin.ts +125 -36
- package/src/adapters/google-antigravity-replay.ts +1 -1
- package/src/adapters/google-antigravity-wire.ts +34 -7
- package/src/adapters/google-errors.ts +7 -1
- package/src/adapters/google-http.ts +49 -10
- package/src/adapters/google-tool-schema.ts +595 -31
- package/src/adapters/google-wire-compiler.ts +93 -10
- package/src/adapters/google-wire-shape.ts +461 -0
- package/src/adapters/google.ts +66 -11
- package/src/adapters/image.ts +4 -1
- package/src/adapters/input-media-guard.ts +21 -9
- package/src/adapters/kiro/usage.ts +3 -2
- package/src/adapters/kiro-tool-fallback.ts +1 -1
- package/src/adapters/ollama-native.ts +6 -0
- package/src/adapters/openai-chat/developer-role.ts +61 -0
- package/src/adapters/openai-chat/messages.ts +46 -27
- package/src/adapters/openai-chat/parallel-tool-calls.ts +32 -0
- package/src/adapters/openai-chat/passthrough.ts +33 -9
- package/src/adapters/openai-chat/reasoning-wire.ts +89 -0
- package/src/adapters/openai-chat-images.ts +3 -1
- package/src/adapters/openai-chat.ts +23 -58
- package/src/adapters/openai-responses/image-gen.ts +8 -6
- package/src/adapters/openai-responses/passthrough.ts +17 -3
- package/src/adapters/openai-responses/reasoning.ts +7 -0
- package/src/adapters/opencode-go-additional-tools.ts +12 -2
- package/src/adapters/registry.ts +3 -2
- package/src/adapters/run-turn-queue.ts +178 -29
- package/src/adapters/xai-web-search.ts +16 -1
- package/src/bridge/errors.ts +8 -2
- package/src/bridge/response-json.ts +9 -1
- package/src/bridge/sse.ts +13 -151
- package/src/chat/inbound.ts +141 -5
- package/src/claude/desktop-3p.ts +7 -1
- package/src/claude/desktop-first-party.ts +183 -0
- package/src/claude/desktop-gateway-state.ts +41 -0
- package/src/claude/inbound-content-options.ts +6 -0
- package/src/claude/inbound.ts +32 -6
- package/src/claude/intercept/connect-proxy.ts +179 -0
- package/src/claude/intercept/listener.ts +122 -0
- package/src/claude/intercept/local-ca.ts +298 -0
- package/src/claude/intercept/runtime.ts +98 -0
- package/src/claude/intercept/settings.ts +189 -0
- package/src/cli/access.ts +87 -0
- package/src/cli/account-auth.ts +19 -0
- package/src/cli/account-extended.ts +4 -4
- package/src/cli/capabilities.ts +31 -0
- package/src/cli/claude-desktop.ts +206 -16
- package/src/cli/codex-shim-autorestore.ts +3 -0
- package/src/cli/companion.ts +56 -0
- package/src/cli/dispatch.ts +46 -7
- package/src/cli/doctor.ts +28 -9
- package/src/cli/ensure-desired-integrations.ts +43 -5
- package/src/cli/help.ts +7 -9
- package/src/cli/hub.ts +3 -2
- package/src/cli/index.ts +203 -59
- package/src/cli/init.ts +8 -0
- package/src/cli/integrations.ts +7 -1
- package/src/cli/opencode.ts +2 -2
- package/src/cli/provider.ts +13 -1
- package/src/cli/registry.ts +41 -2
- package/src/cli/resolve.ts +230 -0
- package/src/cli/root.ts +24 -1
- package/src/cli/start-ownership-publication.ts +56 -0
- package/src/cli/status-probes.ts +2 -18
- package/src/cli/status.ts +62 -0
- package/src/cli/stop-report.ts +143 -0
- package/src/cli/uninstall-plan.ts +9 -0
- package/src/client/machine-api.ts +2 -2
- package/src/client/machine-listener.ts +4 -7
- package/src/client/runtime.ts +26 -2
- package/src/clients/aside-profiles.ts +4 -0
- package/src/clients/config-export/zcode-store.ts +157 -0
- package/src/clients/config-export.ts +36 -0
- package/src/codex/account-store.ts +65 -0
- package/src/codex/app-server-processes.ts +72 -40
- package/src/codex/auth-api/account-list.ts +19 -11
- package/src/codex/auth-api/login-flow.ts +6 -1
- package/src/codex/auth-api/pool-quota-probe.ts +30 -7
- package/src/codex/autostart-health.ts +28 -0
- package/src/codex/catalog/build-entries.ts +2 -2
- package/src/codex/catalog/effort.ts +3 -3
- package/src/codex/catalog/gather-capture.ts +21 -2
- package/src/codex/catalog/model-hints.ts +29 -28
- package/src/codex/catalog/parsing.ts +7 -0
- package/src/codex/catalog/provider-models.ts +43 -17
- package/src/codex/catalog/retained-sync.ts +24 -28
- package/src/codex/catalog/routed-gather.ts +19 -0
- package/src/codex/context-compat.ts +5 -2
- package/src/codex/convergence.ts +2 -2
- package/src/codex/desired-state.ts +4 -1
- package/src/codex/history-job.ts +6 -6
- package/src/codex/history-provider.ts +31 -166
- package/src/codex/history-rollout-read.ts +174 -0
- package/src/codex/inject/config-toml.ts +41 -6
- package/src/codex/inject/paginated-openai-compat.ts +90 -0
- package/src/codex/inject.ts +18 -15
- package/src/codex/injected-marker.ts +18 -0
- package/src/codex/internal/catalog-writer.ts +33 -1
- package/src/codex/main-account.ts +6 -0
- package/src/codex/model-cache.ts +99 -6
- package/src/codex/model-entitlement-admission.ts +59 -0
- package/src/codex/model-entitlements.ts +116 -54
- package/src/codex/native-main-admission.ts +83 -0
- package/src/codex/observed-model-denials.ts +101 -8
- package/src/codex/prompt-text-probe.ts +9 -6
- package/src/codex/routing/health-store.ts +39 -0
- package/src/codex/routing/selection.ts +37 -1
- package/src/codex/routing.ts +12 -42
- package/src/codex/shim-templates.ts +29 -3
- package/src/codex/shim.ts +1 -1
- package/src/codex/subagent-model-fallback.ts +22 -4
- package/src/combos/failover.ts +3 -0
- package/src/companion/settings.ts +132 -0
- package/src/config/admitted-identity.ts +222 -0
- package/src/config/atomic-write.ts +117 -5
- package/src/config/diagnostics.ts +22 -1
- package/src/config/feature-flags.ts +5 -0
- package/src/config/load-degrade.ts +52 -7
- package/src/config/process-state.ts +1 -1
- package/src/config/proxy-env.ts +8 -2
- package/src/config/schema/compaction-triggers.ts +11 -0
- package/src/config/schema/config-schema.ts +31 -1
- package/src/config/schema/leaf-validators.ts +59 -0
- package/src/config.ts +3 -3
- package/src/generated/compatibility-version.json +604 -280
- package/src/grok/reset-coupons.ts +38 -19
- package/src/images/loop.ts +6 -1
- package/src/integrations/aside-profile-context.ts +37 -3
- package/src/integrations/aside-profile-journal.ts +68 -3
- package/src/integrations/aside-profiles.ts +128 -3
- package/src/integrations/config-io.ts +44 -10
- package/src/integrations/merge.ts +120 -13
- package/src/integrations/mutation-plan.ts +921 -0
- package/src/integrations/registry.ts +38 -0
- package/src/integrations/state.ts +78 -45
- package/src/integrations/target.ts +208 -0
- package/src/integrations/writer.ts +134 -110
- package/src/lab/conformance/fixture-provider.ts +5 -0
- package/src/lab/live/transport.ts +4 -0
- package/src/lab/live/types.ts +5 -0
- package/src/lab/subject/behavior-fingerprint.ts +1 -1
- package/src/lib/admin-secrets.ts +9 -1
- package/src/lib/browser-launch-notice.ts +59 -0
- package/src/lib/bun-runtime.ts +6 -2
- package/src/lib/debug-log-buffer.ts +6 -1
- package/src/lib/debug.ts +63 -0
- package/src/lib/errors.ts +79 -0
- package/src/lib/http-response-semantics.ts +57 -0
- package/src/lib/lab-live-pinned-sender.ts +26 -12
- package/src/lib/open-url.ts +51 -7
- package/src/lib/package-tree-integrity.ts +2 -1
- package/src/lib/package-version.ts +8 -0
- package/src/lib/pinned-http.ts +142 -2
- package/src/lib/plain-data.ts +103 -0
- package/src/lib/process-control.ts +13 -5
- package/src/lib/provider-egress.ts +310 -0
- package/src/lib/provider-outbound.ts +109 -16
- package/src/lib/proxy-env.ts +82 -7
- package/src/lib/request-execution-budget.ts +72 -0
- package/src/lib/request-failure-attribution.ts +183 -0
- package/src/lib/request-failure-model.ts +236 -0
- package/src/lib/request-resend-gate.ts +138 -0
- package/src/lib/socks5-fetch.ts +136 -26
- package/src/lib/spend-ledger-owner.ts +364 -0
- package/src/lib/spend-reservation-ledger.ts +218 -27
- package/src/lib/standalone.ts +16 -0
- package/src/lib/upstream-retry.ts +167 -16
- package/src/lib/windows-system-proxy.ts +16 -11
- package/src/lib/winsw.ts +2 -2
- package/src/oauth/callback-server.ts +4 -3
- package/src/oauth/generic-account-failover.ts +1 -0
- package/src/oauth/health.ts +12 -1
- package/src/oauth/index.ts +27 -108
- package/src/oauth/login-cli.ts +80 -29
- package/src/oauth/login-flow-state.ts +127 -0
- package/src/providers/api-key-resolve.ts +133 -0
- package/src/providers/api-key-selection.ts +5 -1
- package/src/providers/derive.ts +34 -17
- package/src/providers/devin-cli-authmode-migration.ts +14 -10
- package/src/providers/key-failover.ts +97 -19
- package/src/providers/key-store.ts +34 -110
- package/src/providers/model-rename-fields.ts +147 -0
- package/src/providers/model-rename-migration.ts +179 -38
- package/src/providers/model-rename-startup.ts +7 -5
- package/src/providers/openai-virtual-models.ts +42 -2
- package/src/providers/quota/antigravity.ts +22 -2
- package/src/providers/quota/vendor-probes-key.ts +38 -23
- package/src/providers/reasoning-metadata.ts +43 -18
- package/src/providers/registry/entries-core.ts +47 -20
- package/src/providers/registry/entries-extended.ts +63 -4
- package/src/providers/registry/model-ids.ts +168 -0
- package/src/providers/registry/model-seeds.ts +56 -10
- package/src/providers/registry/types.ts +2 -0
- package/src/providers/resolved-model-policy-merge.ts +167 -0
- package/src/providers/resolved-model-policy.ts +406 -0
- package/src/providers/stale-vision-classification-migration.ts +137 -0
- package/src/providers/xai-transport.ts +12 -1
- package/src/reasoning-effort.ts +8 -0
- package/src/responses/apply-patch-envelope.ts +0 -12
- package/src/responses/freeform-wrapper-scan.ts +279 -0
- package/src/responses/function-call-compat.ts +38 -1
- package/src/responses/inline-document.ts +65 -0
- package/src/responses/input-media.ts +42 -8
- package/src/responses/legacy-dotted-tool-name-repair.ts +134 -0
- package/src/responses/muse-tool-name-alias.ts +19 -0
- package/src/responses/parser-content.ts +8 -2
- package/src/responses/parser-tools.ts +3 -0
- package/src/responses/parser.ts +3 -1
- package/src/responses/progressive-freeform-input.ts +130 -0
- package/src/responses/reasoning-envelope.ts +30 -0
- package/src/responses/schema.ts +3 -0
- package/src/responses/state.ts +5 -12
- package/src/responses/tool-name-aliases.ts +15 -1
- package/src/router.ts +108 -117
- package/src/routing/compatibility/behavior.ts +9 -0
- package/src/routing/compatibility/subject.ts +16 -1
- package/src/server/adapter-resolve.ts +9 -0
- package/src/server/admission-model-scope.ts +219 -0
- package/src/server/audio-live.ts +9 -3
- package/src/server/audio-upstream.ts +18 -0
- package/src/server/auth-cors.ts +29 -0
- package/src/server/chat-completions.ts +60 -4
- package/src/server/chat-native.ts +19 -4
- package/src/server/claude-messages.ts +61 -20
- package/src/server/effort-row.ts +11 -3
- package/src/server/grok-responses-control-frame.ts +160 -1
- package/src/server/grok-responses-snapshot-repair.ts +113 -11
- package/src/server/gui-freshness.ts +103 -0
- package/src/server/gui-static.ts +7 -9
- package/src/server/images.ts +59 -6
- package/src/server/index/claude-intercept-lifecycle.ts +49 -0
- package/src/server/index/serve-options.ts +142 -39
- package/src/server/index/spend-ledger-lifecycle.ts +92 -0
- package/src/server/index/startup-warnings.ts +24 -0
- package/src/server/index/websocket-handler.ts +6 -1
- package/src/server/index.ts +34 -38
- package/src/server/lifecycle.ts +4 -4
- package/src/server/live-call-bindings.ts +6 -0
- package/src/server/live.ts +88 -3
- package/src/server/management/agent-settings-routes.ts +121 -36
- package/src/server/management/aside-profile-routes.ts +266 -7
- package/src/server/management/companion-routes.ts +77 -0
- package/src/server/management/config-routes.ts +18 -2
- package/src/server/management/context.ts +3 -0
- package/src/server/management/integration-routes.ts +287 -5
- package/src/server/management/logs-usage-routes.ts +19 -0
- package/src/server/management/metrics-routes.ts +20 -0
- package/src/server/management/model-rows.ts +224 -12
- package/src/server/management/native-integration-routes.ts +103 -6
- package/src/server/management/oauth-account-routes.ts +45 -7
- package/src/server/management/route-registry.ts +20 -0
- package/src/server/management/shared.ts +28 -4
- package/src/server/management/system-restart.ts +7 -2
- package/src/server/management/system-routes.ts +2 -0
- package/src/server/management/usage-aggregate-cache.ts +4 -0
- package/src/server/management/usage-timeline-routes.ts +44 -0
- package/src/server/management-api.ts +10 -9
- package/src/server/management-auth.ts +15 -1
- package/src/server/proxy-liveness.ts +75 -0
- package/src/server/readiness.ts +29 -10
- package/src/server/relay-eager.ts +24 -2
- package/src/server/relay.ts +138 -12
- package/src/server/request-log-failure-attribution.ts +99 -0
- package/src/server/request-log.ts +169 -2
- package/src/server/request-metrics.ts +298 -0
- package/src/server/responses/adapter-continuation.ts +3 -3
- package/src/server/responses/adapter-dispatch.ts +11 -6
- package/src/server/responses/codex-ws-wire.ts +34 -8
- package/src/server/responses/combo-stream-preflight.ts +168 -6
- package/src/server/responses/compact.ts +43 -10
- package/src/server/responses/compaction-routing.ts +111 -0
- package/src/server/responses/core-codex-account.ts +8 -3
- package/src/server/responses/core-combo.ts +7 -7
- package/src/server/responses/core-normalize.ts +6 -12
- package/src/server/responses/core-opaque-recovery.ts +91 -0
- package/src/server/responses/core-options.ts +4 -0
- package/src/server/responses/encrypted-payload.ts +20 -2
- package/src/server/responses/fetch-helpers.ts +124 -8
- package/src/server/responses/input-admission.ts +10 -0
- package/src/server/responses/passthrough-delivery.ts +45 -15
- package/src/server/responses/passthrough-dispatch.ts +215 -44
- package/src/server/responses/passthrough-error.ts +27 -8
- package/src/server/responses/policy-fallback.ts +5 -13
- package/src/server/responses/request-prepare.ts +109 -18
- package/src/server/responses/request-send-budget.ts +17 -1
- package/src/server/responses/request-sidecar-auth.ts +1 -1
- package/src/server/responses/request-transport.ts +26 -6
- package/src/server/responses/reset-replay.ts +108 -0
- package/src/server/responses/run-turn-execution.ts +25 -3
- package/src/server/responses/sidecar-execution.ts +17 -2
- package/src/server/responses/ws-upstream.ts +14 -27
- package/src/server/responses-custom-tool-repair.ts +27 -54
- package/src/server/responses-request-tool-scope.ts +214 -0
- package/src/server/responses-undeclared-tool-guard.ts +35 -2
- package/src/server/search.ts +25 -1
- package/src/server/sse-payload-rewrite.ts +1 -1
- package/src/server/usage-ledger-retention.ts +73 -0
- package/src/service/cli.ts +48 -2
- package/src/service/health.ts +3 -2
- package/src/service/install-state-contract.d.mts +27 -0
- package/src/service/install-state-contract.mjs +34 -0
- package/src/service/launchd.ts +1 -1
- package/src/service/orchestration.ts +2 -4
- package/src/service/ownership-compatibility.ts +164 -0
- package/src/service/ownership-mutation-lease.d.mts +32 -0
- package/src/service/ownership-mutation-lease.mjs +211 -0
- package/src/service/repair.ts +45 -1
- package/src/service/state-lock.ts +269 -0
- package/src/service/state-record.d.mts +36 -0
- package/src/service/state-record.mjs +138 -0
- package/src/service/state.ts +582 -68
- package/src/service/windows-taskxml.ts +11 -10
- package/src/service.ts +7 -3
- package/src/tray/windows-tray.ps1 +156 -4
- package/src/types/config.ts +48 -3
- package/src/types/provider.ts +91 -0
- package/src/types/request.ts +30 -2
- package/src/types/tools.ts +33 -0
- package/src/types.ts +4 -0
- package/src/update/index.ts +207 -63
- package/src/update/job.ts +9 -5
- package/src/update/ownership-transaction.ts +47 -0
- package/src/update/restart-ownership.ts +54 -0
- package/src/update/runtime-ownership.d.mts +40 -0
- package/src/update/runtime-ownership.mjs +122 -0
- package/src/usage/attempt-delivery.ts +198 -0
- package/src/usage/cache-diagnostic.ts +305 -0
- package/src/usage/failure-fingerprint.ts +118 -0
- package/src/usage/failure-projection-cache.ts +174 -0
- package/src/usage/failure-projection.ts +174 -0
- package/src/usage/ledger-retention.ts +165 -0
- package/src/usage/log.ts +126 -79
- package/src/usage/request-outcome.ts +150 -0
- package/src/usage/retention-contract.ts +28 -0
- package/src/usage/summary.ts +2 -2
- package/src/usage/telemetry-contract.ts +237 -0
- package/src/usage/timeline.ts +236 -0
- package/src/vision/eligibility.ts +88 -9
- package/src/vision/plan.ts +34 -10
- package/src/web-search/alpha-search.ts +21 -1
- package/src/web-search/executor.ts +41 -2
- package/src/web-search/loop.ts +6 -1
- package/gui/dist/assets/index-C5IebErG.js +0 -136
- package/gui/dist/assets/index-OESInAjC.css +0 -1
package/src/server/gui-static.ts
CHANGED
|
@@ -2,15 +2,11 @@ import { existsSync, readFileSync, statSync } from "node:fs";
|
|
|
2
2
|
import { basename, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import { browserSecurityHeaders } from "./auth-cors";
|
|
4
4
|
import type { GuiSessionBootstrap } from "./gui-session";
|
|
5
|
+
import { packageVersion } from "../lib/package-version";
|
|
6
|
+
import { isStandaloneBinary, standaloneRoot } from "../lib/standalone";
|
|
5
7
|
|
|
6
8
|
/** opencodex version, read from the packaged package.json (same source as the server bootstrap). */
|
|
7
|
-
const VERSION = (
|
|
8
|
-
try {
|
|
9
|
-
return JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version as string;
|
|
10
|
-
} catch {
|
|
11
|
-
return "0.0.0";
|
|
12
|
-
}
|
|
13
|
-
})();
|
|
9
|
+
const VERSION = packageVersion("0.0.0");
|
|
14
10
|
|
|
15
11
|
const MIME_TYPES: Record<string, string> = {
|
|
16
12
|
".html": "text/html", ".js": "application/javascript", ".css": "text/css",
|
|
@@ -24,11 +20,13 @@ const MIME_TYPES: Record<string, string> = {
|
|
|
24
20
|
*/
|
|
25
21
|
const HASHED_ASSET_PATTERN = /-[a-zA-Z0-9_-]{8,}\.[a-zA-Z0-9]+$/;
|
|
26
22
|
|
|
27
|
-
function findGuiDist(): string | null {
|
|
23
|
+
export function findGuiDist(): string | null {
|
|
28
24
|
const candidates = [
|
|
25
|
+
process.env.OPENCODEX_GUI_DIST,
|
|
26
|
+
...(isStandaloneBinary() ? [join(standaloneRoot(), "gui", "dist")] : []),
|
|
29
27
|
join(import.meta.dir, "..", "..", "gui", "dist"),
|
|
30
28
|
join(import.meta.dir, "..", "..", "..", "gui", "dist"),
|
|
31
|
-
];
|
|
29
|
+
].filter((candidate): candidate is string => Boolean(candidate));
|
|
32
30
|
for (const c of candidates) {
|
|
33
31
|
if (existsSync(join(c, "index.html"))) return c;
|
|
34
32
|
}
|
package/src/server/images.ts
CHANGED
|
@@ -33,6 +33,8 @@ import { selectProactiveApiKeyTransport } from "../providers/key-failover";
|
|
|
33
33
|
import { getProviderRegistryEntry } from "../providers/registry";
|
|
34
34
|
import { readJsonRequestBody, resolveInboundBodyLimitBytes } from "./request-decompress";
|
|
35
35
|
import { ForwardAdmissionCredentialError, validateForwardAdmissionCredential } from "./auth-cors";
|
|
36
|
+
import type { DataPlaneAdmission } from "./auth-cors";
|
|
37
|
+
import { admissionScopeDenial } from "./admission-model-scope";
|
|
36
38
|
import type { RequestLogContext } from "./request-log";
|
|
37
39
|
import { codexLogAccountId, decodeRequestErrorResponse } from "./responses";
|
|
38
40
|
import { getValidAccessToken, getOAuthCredentialProjectId } from "../oauth/index";
|
|
@@ -115,6 +117,18 @@ export async function readImageResponseBytes(
|
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
const CCA_IMAGE_MODEL = "gemini-3.1-flash-image";
|
|
120
|
+
const XAI_IMAGE_BRIDGE_MODEL = "grok-imagine-image-quality";
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The model this request names, or undefined when it names none.
|
|
124
|
+
*
|
|
125
|
+
* An absent `model` is relayed as an absent `model`: the upstream picks, so
|
|
126
|
+
* there is no destination to echo and none a model list can allow.
|
|
127
|
+
*/
|
|
128
|
+
function requestedImageSelector(body: unknown): string | undefined {
|
|
129
|
+
const model = (body as { model?: unknown } | null)?.model;
|
|
130
|
+
return typeof model === "string" && model.trim() ? model : undefined;
|
|
131
|
+
}
|
|
118
132
|
|
|
119
133
|
/**
|
|
120
134
|
* Google Gemini finishReasons that indicate a permanent content/safety block.
|
|
@@ -207,11 +221,21 @@ async function tryCcaImageGeneration(
|
|
|
207
221
|
logCtx: RequestLogContext,
|
|
208
222
|
signal: AbortSignal,
|
|
209
223
|
endpoint: ImagesEndpoint,
|
|
224
|
+
admission: DataPlaneAdmission | undefined,
|
|
210
225
|
): Promise<Response | undefined> {
|
|
211
226
|
if (endpoint !== "generations") return undefined;
|
|
212
227
|
const provider = config.providers?.["google-antigravity"];
|
|
213
228
|
if (!provider || provider.disabled) return undefined;
|
|
214
229
|
|
|
230
|
+
// The destination is decided here, not by the caller: this branch always
|
|
231
|
+
// bills Antigravity for CCA_IMAGE_MODEL whatever the body named. That is the
|
|
232
|
+
// pair a scoped key is held to.
|
|
233
|
+
const denial = admissionScopeDenial(config, admission, requestedImageSelector(body), {
|
|
234
|
+
providerName: "google-antigravity",
|
|
235
|
+
modelId: CCA_IMAGE_MODEL,
|
|
236
|
+
});
|
|
237
|
+
if (denial) return denial;
|
|
238
|
+
|
|
215
239
|
const prompt = (body as { prompt?: unknown })?.prompt;
|
|
216
240
|
if (typeof prompt !== "string" || !prompt.trim()) {
|
|
217
241
|
return formatErrorResponse(400, "invalid_request_error", "prompt is required and must not be empty");
|
|
@@ -446,10 +470,20 @@ async function tryXaiImageRelay(
|
|
|
446
470
|
logCtx: RequestLogContext,
|
|
447
471
|
signal: AbortSignal | undefined,
|
|
448
472
|
endpoint: ImagesEndpoint,
|
|
473
|
+
admission: DataPlaneAdmission | undefined,
|
|
449
474
|
): Promise<Response | undefined> {
|
|
450
475
|
if (config.images?.bridgeEnabled !== true) return undefined;
|
|
451
476
|
const found = findXaiProvider(config);
|
|
452
477
|
if (!found) return undefined;
|
|
478
|
+
const bridgeModel = config.images?.bridgeModel ?? XAI_IMAGE_BRIDGE_MODEL;
|
|
479
|
+
// The bridge sends this request to the configured xAI provider and the bridge
|
|
480
|
+
// model regardless of the selector in the body, so that is what the key is
|
|
481
|
+
// checked against.
|
|
482
|
+
const denial = admissionScopeDenial(config, admission, requestedImageSelector(body), {
|
|
483
|
+
providerName: found.name,
|
|
484
|
+
modelId: bridgeModel,
|
|
485
|
+
});
|
|
486
|
+
if (denial) return denial;
|
|
453
487
|
const obj = body && typeof body === "object" && !Array.isArray(body)
|
|
454
488
|
? body as Record<string, unknown>
|
|
455
489
|
: {};
|
|
@@ -496,11 +530,11 @@ async function tryXaiImageRelay(
|
|
|
496
530
|
}
|
|
497
531
|
if (!token) return xaiImageAuthMissing();
|
|
498
532
|
logCtx.provider = "xai";
|
|
499
|
-
logCtx.model =
|
|
533
|
+
logCtx.model = bridgeModel;
|
|
500
534
|
const result = await callXaiImages(
|
|
501
535
|
{
|
|
502
536
|
prompt,
|
|
503
|
-
model:
|
|
537
|
+
model: bridgeModel,
|
|
504
538
|
n,
|
|
505
539
|
size,
|
|
506
540
|
quality,
|
|
@@ -602,6 +636,7 @@ export async function handleImages(
|
|
|
602
636
|
endpoint: ImagesEndpoint,
|
|
603
637
|
logCtx: RequestLogContext,
|
|
604
638
|
turnAdmissionLease?: AdmissionLease,
|
|
639
|
+
admission?: DataPlaneAdmission,
|
|
605
640
|
): Promise<Response> {
|
|
606
641
|
let body: unknown;
|
|
607
642
|
try {
|
|
@@ -616,7 +651,7 @@ export async function handleImages(
|
|
|
616
651
|
// Explicit images.provider owns the route, including its validation errors.
|
|
617
652
|
// Do not divert that selection to the xAI Imagine relay.
|
|
618
653
|
if (config.images?.provider === undefined) {
|
|
619
|
-
const xaiRelay = await tryXaiImageRelay(body, config, logCtx, req.signal, endpoint);
|
|
654
|
+
const xaiRelay = await tryXaiImageRelay(body, config, logCtx, req.signal, endpoint, admission);
|
|
620
655
|
if (xaiRelay) return xaiRelay;
|
|
621
656
|
}
|
|
622
657
|
if (candidates.error) {
|
|
@@ -641,7 +676,7 @@ export async function handleImages(
|
|
|
641
676
|
const canUseOpenAiForward = !skipOpenAiForwardForAdmissionBearer && candidates.forwardCandidates.length > 0;
|
|
642
677
|
|
|
643
678
|
if (!canUseOpenAiForward && !candidates.keyed) {
|
|
644
|
-
const ccaResponse = await tryCcaImageGeneration(body, config, logCtx, req.signal, endpoint);
|
|
679
|
+
const ccaResponse = await tryCcaImageGeneration(body, config, logCtx, req.signal, endpoint, admission);
|
|
645
680
|
if (ccaResponse) return ccaResponse;
|
|
646
681
|
// 400, not 5xx: codex retries every 5xx up to 5 total attempts, and this is a permanent
|
|
647
682
|
// configuration state that must surface on the first attempt.
|
|
@@ -688,7 +723,20 @@ export async function handleImages(
|
|
|
688
723
|
|
|
689
724
|
const headers: Record<string, string> = { "content-type": "application/json" };
|
|
690
725
|
let url: string;
|
|
726
|
+
// Both relay branches copy the body upstream, so the destination is the
|
|
727
|
+
// provider chosen in that branch and the model the caller named. Each branch
|
|
728
|
+
// is checked as it is entered, before it resolves a credential or commits a
|
|
729
|
+
// key rotation, so a refused request spends nothing.
|
|
730
|
+
const relaySelector = requestedImageSelector(body);
|
|
691
731
|
if (forward) {
|
|
732
|
+
const denial = admissionScopeDenial(config, admission, relaySelector, {
|
|
733
|
+
providerName: forward.providerName,
|
|
734
|
+
modelId: relaySelector,
|
|
735
|
+
});
|
|
736
|
+
if (denial) {
|
|
737
|
+
forward.releaseProbeLease?.();
|
|
738
|
+
return denial;
|
|
739
|
+
}
|
|
692
740
|
const { provider } = forward;
|
|
693
741
|
if (provider.headers) Object.assign(headers, provider.headers);
|
|
694
742
|
for (const [name, value] of forward.headers) headers[name] = value;
|
|
@@ -697,13 +745,18 @@ export async function handleImages(
|
|
|
697
745
|
} else if (forwardAuthError) {
|
|
698
746
|
// Before surfacing the OpenAI auth failure, try CCA — the user may have a
|
|
699
747
|
// valid Google Antigravity login even though their OpenAI pool is broken.
|
|
700
|
-
const ccaResponse = await tryCcaImageGeneration(body, config, logCtx, req.signal, endpoint);
|
|
748
|
+
const ccaResponse = await tryCcaImageGeneration(body, config, logCtx, req.signal, endpoint, admission);
|
|
701
749
|
if (ccaResponse) return ccaResponse;
|
|
702
750
|
// No CCA either: a configured OpenAI pool mode owns its authentication failure.
|
|
703
751
|
// Do not hide a broken/expired pool behind separately billed API-key image generation.
|
|
704
752
|
return forwardAuthError;
|
|
705
753
|
} else if (candidates.keyed) {
|
|
706
754
|
const { providerName } = candidates.keyed;
|
|
755
|
+
const denial = admissionScopeDenial(config, admission, relaySelector, {
|
|
756
|
+
providerName,
|
|
757
|
+
modelId: relaySelector,
|
|
758
|
+
});
|
|
759
|
+
if (denial) return denial;
|
|
707
760
|
// The keyed image path builds its own URL and Authorization header and never enters
|
|
708
761
|
// handleResponses, so the pre-dispatch key pick happens here.
|
|
709
762
|
//
|
|
@@ -737,7 +790,7 @@ export async function handleImages(
|
|
|
737
790
|
url = `${provider.baseUrl.replace(/\/v1\/?$/, "")}/v1/images/${endpoint}`;
|
|
738
791
|
} else {
|
|
739
792
|
// No usable OpenAI credential — try CCA before giving up.
|
|
740
|
-
const ccaResponse = await tryCcaImageGeneration(body, config, logCtx, req.signal, endpoint);
|
|
793
|
+
const ccaResponse = await tryCcaImageGeneration(body, config, logCtx, req.signal, endpoint, admission);
|
|
741
794
|
if (ccaResponse) return ccaResponse;
|
|
742
795
|
return formatErrorResponse(
|
|
743
796
|
401,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Server } from "bun";
|
|
2
|
+
import {
|
|
3
|
+
startClaudeIntercept,
|
|
4
|
+
type ClaudeInterceptHandle,
|
|
5
|
+
type StartClaudeInterceptOptions,
|
|
6
|
+
} from "../../claude/intercept/runtime";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Owns the Claude intercept pair (CONNECT proxy + TLS listener) on behalf of `startServer`.
|
|
10
|
+
* The pair is an optional integration: a bind failure degrades to a warning, never to a
|
|
11
|
+
* startup failure, because every other client keeps working without it. `startServer` stays
|
|
12
|
+
* synchronous, so the start is fire-and-forget and `stop()` awaits whatever it produced.
|
|
13
|
+
*/
|
|
14
|
+
export interface ClaudeInterceptLifecycle<T> {
|
|
15
|
+
/** True once the TLS listener has bound and `requestServer` is it. */
|
|
16
|
+
ownsListener(requestServer: Server<T>): boolean;
|
|
17
|
+
start(options: StartClaudeInterceptOptions<T>): void;
|
|
18
|
+
stop(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createClaudeInterceptLifecycle<T>(): ClaudeInterceptLifecycle<T> {
|
|
22
|
+
let listener: Server<T> | null = null;
|
|
23
|
+
let pending: Promise<ClaudeInterceptHandle<T> | null> = Promise.resolve(null);
|
|
24
|
+
return {
|
|
25
|
+
ownsListener: requestServer => listener !== null && requestServer === listener,
|
|
26
|
+
start(options) {
|
|
27
|
+
const dispatch = options.dispatch;
|
|
28
|
+
pending = startClaudeIntercept<T>({
|
|
29
|
+
...options,
|
|
30
|
+
dispatch: (req, requestServer) => {
|
|
31
|
+
listener ??= requestServer;
|
|
32
|
+
return dispatch(req, requestServer);
|
|
33
|
+
},
|
|
34
|
+
}).then(handle => {
|
|
35
|
+
if (handle) {
|
|
36
|
+
listener = handle.listener;
|
|
37
|
+
console.log(`🔐 Claude intercept proxy active on http://127.0.0.1:${handle.proxyPort} (CONNECT api.anthropic.com → local TLS)`);
|
|
38
|
+
}
|
|
39
|
+
return handle;
|
|
40
|
+
}).catch((error: unknown) => {
|
|
41
|
+
console.warn(`⚠ Claude intercept proxy could not start: ${error instanceof Error ? error.message : String(error)}`);
|
|
42
|
+
return null;
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
async stop() {
|
|
46
|
+
await (await pending)?.stop();
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|