From 73bb38781704f4c6fd6fec9ae2818d10d706f537 Mon Sep 17 00:00:00 2001
From: t
Date: Sat, 5 Sep 2026 09:50:52 +0900
Subject: [PATCH 1/2] refactor(providers): isolate OpenAI destination
classification (split S02 L1/4)
---
src/providers/openai-tiers-destination.ts | 102 ++++++++++++++++++++++
src/providers/openai-tiers.ts | 101 +--------------------
2 files changed, 104 insertions(+), 99 deletions(-)
create mode 100644 src/providers/openai-tiers-destination.ts
diff --git a/src/providers/openai-tiers-destination.ts b/src/providers/openai-tiers-destination.ts
new file mode 100644
index 0000000000..5c6124f29d
--- /dev/null
+++ b/src/providers/openai-tiers-destination.ts
@@ -0,0 +1,102 @@
+import type { OcxProviderConfig } from "../types";
+import { openaiResponsesUrl } from "../adapters/openai-responses-url";
+
+export const OPENAI_CODEX_PROVIDER_ID = "openai";
+export const LEGACY_OPENAI_MULTI_PROVIDER_ID = "openai-multi";
+export const OPENAI_API_PROVIDER_ID = "openai-apikey";
+export const LEGACY_CHATGPT_PROVIDER_ID = "chatgpt";
+
+export const CODEX_FORWARD_BASE_URL = "https://chatgpt.com/backend-api/codex";
+
+function normalizedBaseUrl(value: string): string | undefined {
+ try {
+ const url = new URL(value.trim());
+ if (url.username || url.password || url.search || url.hash) return undefined;
+ const path = url.pathname.replace(/\/+$/, "");
+ return `${url.origin}${path}`;
+ } catch {
+ return undefined;
+ }
+}
+
+export function isCanonicalOpenAiForwardProvider(provider: OcxProviderConfig): boolean {
+ return provider.adapter === "openai-responses"
+ && provider.authMode === "forward"
+ && normalizedBaseUrl(provider.baseUrl) === CODEX_FORWARD_BASE_URL;
+}
+
+const OPENAI_API_ORIGIN = "https://api.openai.com";
+const OPENAI_API_BASE_URL = `${OPENAI_API_ORIGIN}/v1`;
+const OPENAI_API_RESPONSES_URL = `${OPENAI_API_BASE_URL}/responses`;
+
+/**
+ * The Responses endpoint the adapter would actually POST key-auth traffic to, normalized.
+ *
+ * Mirrors the adapter's own construction (`src/adapters/openai-responses.ts`): a configured
+ * `responsesPath` is appended to the base verbatim, and only the default branch runs the
+ * `/v1/responses` suffix normalization. Classifying on the base URL alone would call
+ * `baseUrl: "https://api.openai.com"` with `responsesPath: "/other"` official even though that
+ * request never reaches the official Responses endpoint.
+ */
+function resolvedResponsesEndpoint(provider: OcxProviderConfig): string | undefined {
+ try {
+ const raw = provider.responsesPath === undefined
+ ? openaiResponsesUrl(provider.baseUrl)
+ : `${provider.baseUrl.replace(/\/$/, "")}${provider.responsesPath}`;
+ return normalizedBaseUrl(raw);
+ } catch {
+ return undefined;
+ }
+}
+
+function isOfficialOpenAiResponsesDestination(provider: OcxProviderConfig): boolean {
+ // Exact normalized URL keeps lookalike/suffix hosts out of this set: `api.openai.com.evil.test`
+ // resolves to its own origin, never to the official one.
+ return resolvedResponsesEndpoint(provider) === OPENAI_API_RESPONSES_URL;
+}
+
+/**
+ * Whether this provider can serve `POST /responses/compact`. The canonical ChatGPT
+ * backend can, and so can the official OpenAI API — but an arbitrary gateway that
+ * merely speaks the Responses wire cannot, and calling it there fails compaction
+ * with an unhelpful error instead of falling back to a routed summary (#422).
+ */
+export function supportsNativeResponsesCompactEndpoint(
+ providerName: string,
+ provider: OcxProviderConfig,
+): boolean {
+ if (isCanonicalOpenAiForwardProvider(provider)) return true;
+ return providerName === OPENAI_API_PROVIDER_ID
+ && provider.adapter === "openai-responses"
+ && normalizedBaseUrl(provider.baseUrl) === OPENAI_API_BASE_URL;
+}
+
+/**
+ * Whether this destination is an OpenAI-operated Responses backend — the canonical ChatGPT Codex
+ * surface or the official OpenAI API.
+ *
+ * Deliberately not keyed on `authMode === "forward"`: a noncanonical forward provider does not
+ * receive the caller's credentials (see the forward-header gate in the Responses adapter), so
+ * forward auth says nothing about which backend is on the other end.
+ */
+export function isOpenAiOperatedResponsesDestination(provider: OcxProviderConfig): boolean {
+ if (isCanonicalOpenAiForwardProvider(provider)) return true;
+ return provider.adapter === "openai-responses"
+ && isOfficialOpenAiResponsesDestination(provider);
+}
+
+/**
+ * Whether this destination can decode a native (non-`ocx1:`) compaction blob.
+ *
+ * Only the backend that minted a blob can decode it. `authMode: "forward"` alone is not a signal:
+ * the adapter forwards caller credentials only to the canonical ChatGPT Codex surface, while a
+ * noncanonical forward provider receives no caller credentials and may point at any backend.
+ *
+ * Relay only to an OpenAI-operated destination or a destination whose operator explicitly opts in.
+ * Keyed by destination rather than provider id: a blob's issuer is the URL that produced it, not the
+ * local config key a replay travels under.
+ */
+export function destinationDecodesNativeCompactionBlob(provider: OcxProviderConfig): boolean {
+ return isOpenAiOperatedResponsesDestination(provider)
+ || provider.decodesNativeCompactionBlobs === true;
+}
diff --git a/src/providers/openai-tiers.ts b/src/providers/openai-tiers.ts
index 5e99c89963..9b33d6e573 100644
--- a/src/providers/openai-tiers.ts
+++ b/src/providers/openai-tiers.ts
@@ -2,13 +2,9 @@ import type { CodexAccountMode, OcxConfig, OcxProviderConfig, ProviderCostOverla
import { OPENAI_PROVIDER_TIER_VERSION } from "../types";
import { openaiResponsesUrl } from "../adapters/openai-responses-url";
import { MAX_COST4_RATE } from "../usage/expected-prices";
+import { OPENAI_CODEX_PROVIDER_ID, LEGACY_OPENAI_MULTI_PROVIDER_ID, LEGACY_CHATGPT_PROVIDER_ID, CODEX_FORWARD_BASE_URL, isCanonicalOpenAiForwardProvider } from "./openai-tiers-destination";
+export { OPENAI_CODEX_PROVIDER_ID, LEGACY_OPENAI_MULTI_PROVIDER_ID, OPENAI_API_PROVIDER_ID, LEGACY_CHATGPT_PROVIDER_ID, CODEX_FORWARD_BASE_URL, isCanonicalOpenAiForwardProvider, supportsNativeResponsesCompactEndpoint, isOpenAiOperatedResponsesDestination, destinationDecodesNativeCompactionBlob } from "./openai-tiers-destination";
-export const OPENAI_CODEX_PROVIDER_ID = "openai";
-export const LEGACY_OPENAI_MULTI_PROVIDER_ID = "openai-multi";
-export const OPENAI_API_PROVIDER_ID = "openai-apikey";
-export const LEGACY_CHATGPT_PROVIDER_ID = "chatgpt";
-
-export const CODEX_FORWARD_BASE_URL = "https://chatgpt.com/backend-api/codex";
const LEGACY_OPENAI_MULTI_PREFIX = `${LEGACY_OPENAI_MULTI_PROVIDER_ID}/`;
function canonicalCodexForwardProvider(mode: CodexAccountMode): OcxProviderConfig {
@@ -20,99 +16,6 @@ function canonicalCodexForwardProvider(mode: CodexAccountMode): OcxProviderConfi
};
}
-function normalizedBaseUrl(value: string): string | undefined {
- try {
- const url = new URL(value.trim());
- if (url.username || url.password || url.search || url.hash) return undefined;
- const path = url.pathname.replace(/\/+$/, "");
- return `${url.origin}${path}`;
- } catch {
- return undefined;
- }
-}
-
-export function isCanonicalOpenAiForwardProvider(provider: OcxProviderConfig): boolean {
- return provider.adapter === "openai-responses"
- && provider.authMode === "forward"
- && normalizedBaseUrl(provider.baseUrl) === CODEX_FORWARD_BASE_URL;
-}
-
-const OPENAI_API_ORIGIN = "https://api.openai.com";
-const OPENAI_API_BASE_URL = `${OPENAI_API_ORIGIN}/v1`;
-const OPENAI_API_RESPONSES_URL = `${OPENAI_API_BASE_URL}/responses`;
-
-/**
- * The Responses endpoint the adapter would actually POST key-auth traffic to, normalized.
- *
- * Mirrors the adapter's own construction (`src/adapters/openai-responses.ts`): a configured
- * `responsesPath` is appended to the base verbatim, and only the default branch runs the
- * `/v1/responses` suffix normalization. Classifying on the base URL alone would call
- * `baseUrl: "https://api.openai.com"` with `responsesPath: "/other"` official even though that
- * request never reaches the official Responses endpoint.
- */
-function resolvedResponsesEndpoint(provider: OcxProviderConfig): string | undefined {
- try {
- const raw = provider.responsesPath === undefined
- ? openaiResponsesUrl(provider.baseUrl)
- : `${provider.baseUrl.replace(/\/$/, "")}${provider.responsesPath}`;
- return normalizedBaseUrl(raw);
- } catch {
- return undefined;
- }
-}
-
-function isOfficialOpenAiResponsesDestination(provider: OcxProviderConfig): boolean {
- // Exact normalized URL keeps lookalike/suffix hosts out of this set: `api.openai.com.evil.test`
- // resolves to its own origin, never to the official one.
- return resolvedResponsesEndpoint(provider) === OPENAI_API_RESPONSES_URL;
-}
-
-/**
- * Whether this provider can serve `POST /responses/compact`. The canonical ChatGPT
- * backend can, and so can the official OpenAI API — but an arbitrary gateway that
- * merely speaks the Responses wire cannot, and calling it there fails compaction
- * with an unhelpful error instead of falling back to a routed summary (#422).
- */
-export function supportsNativeResponsesCompactEndpoint(
- providerName: string,
- provider: OcxProviderConfig,
-): boolean {
- if (isCanonicalOpenAiForwardProvider(provider)) return true;
- return providerName === OPENAI_API_PROVIDER_ID
- && provider.adapter === "openai-responses"
- && normalizedBaseUrl(provider.baseUrl) === OPENAI_API_BASE_URL;
-}
-
-/**
- * Whether this destination is an OpenAI-operated Responses backend — the canonical ChatGPT Codex
- * surface or the official OpenAI API.
- *
- * Deliberately not keyed on `authMode === "forward"`: a noncanonical forward provider does not
- * receive the caller's credentials (see the forward-header gate in the Responses adapter), so
- * forward auth says nothing about which backend is on the other end.
- */
-export function isOpenAiOperatedResponsesDestination(provider: OcxProviderConfig): boolean {
- if (isCanonicalOpenAiForwardProvider(provider)) return true;
- return provider.adapter === "openai-responses"
- && isOfficialOpenAiResponsesDestination(provider);
-}
-
-/**
- * Whether this destination can decode a native (non-`ocx1:`) compaction blob.
- *
- * Only the backend that minted a blob can decode it. `authMode: "forward"` alone is not a signal:
- * the adapter forwards caller credentials only to the canonical ChatGPT Codex surface, while a
- * noncanonical forward provider receives no caller credentials and may point at any backend.
- *
- * Relay only to an OpenAI-operated destination or a destination whose operator explicitly opts in.
- * Keyed by destination rather than provider id: a blob's issuer is the URL that produced it, not the
- * local config key a replay travels under.
- */
-export function destinationDecodesNativeCompactionBlob(provider: OcxProviderConfig): boolean {
- return isOpenAiOperatedResponsesDestination(provider)
- || provider.decodesNativeCompactionBlobs === true;
-}
-
export interface OpenAiTierMigrationProjection {
config: OcxConfig;
changed: boolean;
From 58dba9e0b2209bd9f76c4d5fb4943df0d6ab710b Mon Sep 17 00:00:00 2001
From: t
Date: Sat, 5 Sep 2026 09:51:09 +0900
Subject: [PATCH 2/2] test(providers): cover the openai-tiers-destination leaf
(split S02 L1/4)
---
.../adapters/openai/openai-provider-option.test.ts | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/tests/adapters/openai/openai-provider-option.test.ts b/tests/adapters/openai/openai-provider-option.test.ts
index fa80f73556..5e1943ceb0 100644
--- a/tests/adapters/openai/openai-provider-option.test.ts
+++ b/tests/adapters/openai/openai-provider-option.test.ts
@@ -1,4 +1,10 @@
import { describe, expect, test } from "bun:test";
+import { readFileSync } from "node:fs";
+import { repoPath } from "../../helpers/repo-root";
+import {
+ isCanonicalOpenAiForwardProvider as destinationIsCanonicalOpenAiForwardProvider,
+ OPENAI_CODEX_PROVIDER_ID as DESTINATION_OPENAI_CODEX_PROVIDER_ID,
+} from "../../../src/providers/openai-tiers-destination";
import { getDefaultConfig } from "../../../src/config";
import { deriveInitProviders, deriveProviderPresets, listRegistryEntries, providerConfigSeed } from "../../../src/providers/derive";
import { getProviderRegistryEntry, providerCodexAccountMode } from "../../../src/providers/registry";
@@ -100,3 +106,10 @@ describe("OpenAI single-provider option foundation", () => {
expect(getDefaultConfig().providers.openai).toMatchObject({ codexAccountMode: "pool" });
});
});
+
+test("destination leaf preserves facade bindings without importing the facade", () => {
+ expect(destinationIsCanonicalOpenAiForwardProvider).toBe(isCanonicalOpenAiForwardProvider);
+ expect(DESTINATION_OPENAI_CODEX_PROVIDER_ID).toBe(OPENAI_CODEX_PROVIDER_ID);
+ const source = readFileSync(repoPath("src/providers/openai-tiers-destination.ts"), "utf8");
+ expect(source).not.toMatch(/(?:from\s*|import\s*(?:\(\s*)?)["']\.\/openai-tiers(?:\.ts)?["']/);
+});