blob: a2c75c7b78b0582c7c92ed1c5c4eec2e1bd15f50 [file]
import { redactSecrets } from '@maka/core';
import type { RuntimeExecutionConnection } from '@maka/core';
import {
GITHUB_COPILOT_API_VERSION,
GITHUB_COPILOT_COMPAT_HEADERS,
} from './subscription-credentials.js';
import { openAiCodexHeaders } from './subscription-auth.js';
export interface SubscriptionModelFetchInput {
connection: RuntimeExecutionConnection;
sessionId: string;
modelId: string;
fetchFn?: typeof fetch;
/** Force-refreshes a remotely invalidated OAuth token for one safe 401 replay. */
refreshOAuthAccessToken?: () => Promise<string | null>;
claude?: {
cloakEnabled?: boolean;
deviceId: string;
accountUuid: string;
};
}
export function buildSubscriptionModelFetch(
input: SubscriptionModelFetchInput,
): typeof fetch | undefined {
if (input.connection.providerType === 'claude-subscription') {
if (input.claude?.cloakEnabled === false) return undefined;
return buildClaudeSubscriptionCloakedFetch(input, requireClaudeCloakMetadata(input.claude));
}
if (input.connection.providerType === 'openai-codex') {
return buildOpenAiCodexFetch(
input.sessionId,
input.fetchFn ?? fetch,
input.refreshOAuthAccessToken,
);
}
if (input.connection.providerType === 'github-copilot') {
return buildGitHubCopilotFetch(input.fetchFn ?? fetch);
}
if (input.connection.providerType === 'xai-oauth' && input.refreshOAuthAccessToken) {
return buildOAuth401ReplayFetch(input.fetchFn ?? fetch, input.refreshOAuthAccessToken);
}
return undefined;
}
function buildGitHubCopilotFetch(fetchFn: typeof fetch): typeof fetch {
return async (url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {
const headers = new Headers(init?.headers);
for (const [name, value] of Object.entries(GITHUB_COPILOT_COMPAT_HEADERS)) {
headers.set(name, value);
}
headers.set('Openai-Intent', 'conversation-edits');
headers.set('X-GitHub-Api-Version', GITHUB_COPILOT_API_VERSION);
headers.set('x-initiator', githubCopilotInitiator(init?.body));
if (githubCopilotBodyHasVision(init?.body)) headers.set('Copilot-Vision-Request', 'true');
return fetchFn(url, { ...init, headers });
};
}
function githubCopilotInitiator(body: BodyInit | null | undefined): 'user' | 'agent' {
if (typeof body !== 'string') return 'user';
try {
const parsed = JSON.parse(body) as { messages?: unknown; input?: unknown };
const items = Array.isArray(parsed.messages)
? parsed.messages
: Array.isArray(parsed.input)
? parsed.input
: [];
const last = items.at(-1);
return isUserInitiatedGitHubCopilotItem(last) ? 'user' : 'agent';
} catch {
return 'user';
}
}
function isUserInitiatedGitHubCopilotItem(value: unknown): boolean {
if (!value || typeof value !== 'object') return false;
const item = value as { role?: unknown; content?: unknown };
if (item.role !== 'user') return false;
if (!Array.isArray(item.content)) return true;
return item.content.some(
(part) =>
part !== null &&
typeof part === 'object' &&
(part as { type?: unknown }).type !== 'tool_result',
);
}
function githubCopilotBodyHasVision(body: BodyInit | null | undefined): boolean {
if (typeof body !== 'string') return false;
try {
return containsGitHubCopilotImage(JSON.parse(body) as unknown);
} catch {
return false;
}
}
function containsGitHubCopilotImage(value: unknown): boolean {
if (Array.isArray(value)) return value.some(containsGitHubCopilotImage);
if (!value || typeof value !== 'object') return false;
const record = value as Record<string, unknown>;
if (record.type === 'image' || record.type === 'image_url' || record.type === 'input_image')
return true;
return Object.values(record).some(containsGitHubCopilotImage);
}
function requireClaudeCloakMetadata(
claude: SubscriptionModelFetchInput['claude'],
): NonNullable<SubscriptionModelFetchInput['claude']> {
if (!claude || !isNonEmptyString(claude.deviceId) || !isNonEmptyString(claude.accountUuid)) {
throw new Error('Claude subscription cloaking requires deviceId and accountUuid metadata.');
}
return claude;
}
function isNonEmptyString(value: unknown): value is string {
return typeof value === 'string' && value.trim().length > 0;
}
function buildOpenAiCodexFetch(
sessionId: string,
fetchFn: typeof fetch,
refreshOAuthAccessToken?: () => Promise<string | null>,
): typeof fetch {
return async (url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {
const headers = new Headers(init?.headers);
headers.set('OpenAI-Beta', 'responses=experimental');
headers.set('originator', 'codex_cli_rs');
headers.set('session_id', sessionId);
headers.set('x-client-request-id', sessionId);
headers.set('content-type', 'application/json');
const rawBody = init?.body;
if (typeof rawBody !== 'string') {
return checkedOpenAiCodexFetch(fetchFn, url, { ...init, headers }, refreshOAuthAccessToken);
}
let parsedBody: Record<string, unknown>;
try {
const parsed = JSON.parse(rawBody) as unknown;
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
return checkedOpenAiCodexFetch(fetchFn, url, { ...init, headers }, refreshOAuthAccessToken);
}
parsedBody = parsed as Record<string, unknown>;
} catch {
return checkedOpenAiCodexFetch(fetchFn, url, { ...init, headers }, refreshOAuthAccessToken);
}
return checkedOpenAiCodexFetch(
fetchFn,
url,
{
...init,
headers,
body: JSON.stringify({
...parsedBody,
instructions: codexInstructionsFromBody(parsedBody),
store: false,
parallel_tool_calls: parsedBody.parallel_tool_calls ?? true,
text: {
...(parsedBody.text !== null && typeof parsedBody.text === 'object'
? (parsedBody.text as Record<string, unknown>)
: {}),
verbosity:
parsedBody.text !== null &&
typeof parsedBody.text === 'object' &&
typeof (parsedBody.text as { verbosity?: unknown }).verbosity === 'string'
? (parsedBody.text as { verbosity: string }).verbosity
: 'medium',
},
}),
},
refreshOAuthAccessToken,
);
};
}
async function checkedOpenAiCodexFetch(
fetchFn: typeof fetch,
url: Parameters<typeof fetch>[0],
init?: Parameters<typeof fetch>[1],
refreshOAuthAccessToken?: () => Promise<string | null>,
): Promise<Response> {
const edgeRetryDelaysMs = [2_000, 10_000, 30_000] as const;
let authorizationReplayUsed = false;
let edgeRetry = 0;
let requestInit = init;
for (;;) {
const response = await fetchFn(url, requestInit);
if (response.ok) return response;
const detail = await response
.clone()
.text()
.catch(() => '');
if (
response.status === 401 &&
!authorizationReplayUsed &&
refreshOAuthAccessToken &&
isReplayableOpenAiCodexRequest(url, requestInit)
) {
authorizationReplayUsed = true;
const accessToken = await refreshOAuthAccessToken().catch(() => null);
if (accessToken) {
await response.body?.cancel().catch(() => undefined);
requestInit = withRefreshedOAuthAuthorization(requestInit, accessToken, true);
continue;
}
}
if (
edgeRetryDelaysMs[edgeRetry] !== undefined &&
isReplayableOpenAiCodexRequest(url, requestInit) &&
isTransientOpenAiCodexEdgeRejection(response, detail)
) {
await abortableDelay(
openAiCodexRetryAfterMs(response, edgeRetryDelaysMs[edgeRetry] ?? 30_000),
effectiveOpenAiCodexRequestSignal(url, requestInit),
);
edgeRetry += 1;
continue;
}
throw new Error(formatOpenAiCodexHttpError(response.status, detail));
}
}
function buildOAuth401ReplayFetch(
fetchFn: typeof fetch,
refreshOAuthAccessToken: () => Promise<string | null>,
): typeof fetch {
return async (url, init) => {
const response = await fetchFn(url, init);
if (response.status !== 401 || !isReplayableOpenAiCodexRequest(url, init)) return response;
const accessToken = await refreshOAuthAccessToken().catch(() => null);
if (!accessToken) return response;
await response.body?.cancel().catch(() => undefined);
return fetchFn(url, withRefreshedOAuthAuthorization(init, accessToken, false));
};
}
function withRefreshedOAuthAuthorization(
init: RequestInit | undefined,
accessToken: string,
codex: boolean,
): RequestInit {
const headers = new Headers(init?.headers);
headers.set('Authorization', `Bearer ${accessToken}`);
if (codex) {
headers.delete('ChatGPT-Account-Id');
for (const [name, value] of Object.entries(openAiCodexHeaders(accessToken))) {
headers.set(name, value);
}
}
return { ...init, headers };
}
function isReplayableOpenAiCodexRequest(
url: Parameters<typeof fetch>[0],
init?: Parameters<typeof fetch>[1],
): boolean {
if (typeof init?.body === 'string') return true;
if (init?.body != null) return false;
return !(url instanceof Request) || url.body === null;
}
function effectiveOpenAiCodexRequestSignal(
url: Parameters<typeof fetch>[0],
init?: Parameters<typeof fetch>[1],
): AbortSignal | null | undefined {
if (init?.signal !== undefined) return init.signal;
return url instanceof Request ? url.signal : undefined;
}
function isTransientOpenAiCodexEdgeRejection(response: Response, detail: string): boolean {
if (response.status !== 403) return false;
const contentType = response.headers.get('content-type')?.toLowerCase() ?? '';
return contentType.includes('text/html') || /^\s*(?:<!doctype html|<html\b)/i.test(detail);
}
function openAiCodexRetryAfterMs(response: Response, fallbackMs: number): number {
const rawRetryAfter = response.headers.get('retry-after');
if (rawRetryAfter === null || rawRetryAfter.trim() === '') return fallbackMs;
const retryAfterSeconds = Number(rawRetryAfter);
if (!Number.isFinite(retryAfterSeconds) || retryAfterSeconds < 0) return fallbackMs;
return Math.min(retryAfterSeconds * 1_000, 30_000);
}
function abortableDelay(ms: number, signal?: AbortSignal | null): Promise<void> {
signal?.throwIfAborted();
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
signal?.removeEventListener('abort', onAbort);
resolve();
}, ms);
const onAbort = () => {
clearTimeout(timer);
reject(signal?.reason);
};
signal?.addEventListener('abort', onAbort, { once: true });
});
}
function codexInstructionsFromBody(body: Record<string, unknown>): string {
if (typeof body.instructions === 'string' && body.instructions.trim()) {
return body.instructions;
}
if (typeof body.system === 'string' && body.system.trim()) {
return body.system;
}
const input = body.input;
if (Array.isArray(input)) {
for (const item of input) {
if (!item || typeof item !== 'object') continue;
const record = item as Record<string, unknown>;
if (record.role !== 'system') continue;
const content = record.content;
if (typeof content === 'string' && content.trim()) return content;
if (!Array.isArray(content)) continue;
const text = content
.map((part) => {
if (!part || typeof part !== 'object') return '';
const value = (part as Record<string, unknown>).text;
return typeof value === 'string' ? value : '';
})
.filter(Boolean)
.join('\n')
.trim();
if (text) return text;
}
}
return 'You are Maka, a helpful AI assistant.';
}
function formatOpenAiCodexHttpError(statusCode: number, detail: string): string {
const compact = redactSecrets(detail).replace(/\s+/g, ' ').trim().slice(0, 240);
return compact
? `Codex OAuth request failed: HTTP ${statusCode} ${compact}`
: `Codex OAuth request failed: HTTP ${statusCode}`;
}
function buildClaudeSubscriptionCloakedFetch(
input: SubscriptionModelFetchInput,
claude: NonNullable<SubscriptionModelFetchInput['claude']>,
): typeof fetch {
const fetchFn = input.fetchFn ?? fetch;
return async (url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {
const rawBody = init?.body;
if (typeof rawBody !== 'string') {
return fetchFn(url, init);
}
let parsedBody: Record<string, unknown>;
try {
const parsed = JSON.parse(rawBody) as unknown;
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
return fetchFn(url, init);
}
parsedBody = parsed as Record<string, unknown>;
} catch {
return fetchFn(url, init);
}
const { buildCloakedRequest } = await import('./subscription-cloaked-request.js');
const upstream = await buildCloakedRequest({
body: parsedBody,
model: input.modelId,
sessionKey: input.sessionId,
streaming: parsedBody.stream === true,
timeoutMs: 600_000,
deviceId: claude.deviceId,
accountUuid: claude.accountUuid,
sessionId: input.sessionId,
});
const headers = new Headers(init?.headers);
for (const [key, value] of Object.entries(upstream.headers)) {
headers.set(key, value);
}
headers.set('content-type', 'application/json');
headers.delete('x-api-key');
return fetchFn(url, {
...init,
headers,
body: JSON.stringify(upstream.body),
});
};
}