@agimon-ai/model-proxy-mcp 0.2.6 → 0.2.8
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/dist/cli.cjs +2 -1
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.mjs +2 -1
- package/dist/cli.mjs.map +1 -0
- package/dist/stdio-B-atmzW4.cjs +2 -1
- package/dist/stdio-B-atmzW4.cjs.map +1 -0
- package/dist/stdio-BxbGlLys.mjs +2 -1
- package/dist/stdio-BxbGlLys.mjs.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio-B-atmzW4.cjs","names":["path","os","DEFAULT_PROVIDER_SETTINGS: Record<string, ProviderRuntimeConfig>","DEFAULT_MODEL_LIST: ProxyModelConfig[]","DEFAULT_SCOPE_SETTINGS: ScopeSettings","consoleLogger: LoggerLike","DEFAULT_SCOPE","DEFAULT_REASONING_EFFORT: ReasoningEffort","MODEL_SLOTS: ModelSlot[]","FILE_ENCODING: BufferEncoding","reasoningEffortSchema","z","selectionSchema","slotConfigSchema","adminConfigUpdateSchema","code: ProfileStoreErrorCode","path","fs","MODEL_SLOTS","nextScopeModels: ScopeSettings['models']","normalizedScopeModels: ScopeSettings['models']","normalized: ScopeModelSelection[]","__filename","__dirname","path","cachedCodexInstructions: string | null","fs","responsesRequest: any","input: any[]","headers: Record<string, string>","messages: any[]","result: any[]","textContent: any[]","logger: LoggerLike","path","fs","state: StreamState","events: string[]","parsed: ParsedOpenAIStream","data: any","usageDetails: any","result: string[]","deduped: string[]","parsed","claudeStream","dataLines: string[]","segments: string[]","usage: Record<string, unknown>","contents: GeminiContent[]","parts: GeminiContentPart[]","AUTHORIZATION_HEADER","code: string","logger: LoggerLike","env: NodeJS.ProcessEnv","os","path","fs","nextCredentials: GeminiOAuthCredentials","payloads: GeminiGenerateContentResponse[]","events: string[]","DEFAULT_HISTORY_PAGE_SIZE","z","code: string","logger: LoggerLike","fs","path","Database","MODEL_SLOT_BY_NAME: Record<string, ModelSlot>","DEFAULT_SCOPE","DEFAULT_SLOT: ModelSlot","MODEL_SLOTS: ModelSlot[]","z","code: string","status: number","upstreamBody: string","attemptLabel: string","logger: LoggerLike","fetchImpl: typeof fetch","DEFAULT_SLOT","resolved: ResolvedSlotConfig | null","message","lastRecoverableFailure: AttemptFailure | null","targets: AttemptTarget[]","auth: CodexForwardAuth","upstreamText","geminiRequest: Parameters<ClaudeToGeminiTransformer['transform']>[0]","chunks: string[]","ZodError","entries: Omit<ConversationHistoryEntry, 'id' | 'createdAt'>[]","payload: unknown","z","modelSlotSchema","Hono","z","Server","ListToolsRequestSchema","CallToolRequestSchema","server: Server","StdioServerTransport"],"sources":["../src/constants/defaults.ts","../src/services/logger.ts","../src/services/ProfileStore.ts","../src/adapters/codex/ClaudeToOpenAITransformer.ts","../src/adapters/codex/CodexAuth.ts","../src/adapters/codex/OpenAIToClaudeTransformer.ts","../src/adapters/gemini/types.ts","../src/adapters/gemini/ClaudeToGeminiTransformer.ts","../src/adapters/gemini/GeminiAuth.ts","../src/adapters/gemini/GeminiToClaudeTransformer.ts","../src/services/ConversationHistoryService.ts","../src/services/GatewayService.ts","../src/server/adminPage.ts","../src/server/http.ts","../src/server/index.ts","../src/transports/stdio.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport type { ProviderRuntimeConfig, ProxyModelConfig, ProxySettings, ScopeSettings } from '../types/index.js';\n\nexport const DEFAULT_SETTINGS_DIR = path.join(os.homedir(), '.model-proxy');\nexport const DEFAULT_MODEL_PROVIDER_PATH = path.join(DEFAULT_SETTINGS_DIR, 'model-provider.yaml');\nexport const DEFAULT_MODEL_LIST_PATH = path.join(DEFAULT_SETTINGS_DIR, 'model-list.yaml');\nexport const DEFAULT_SCOPE_SETTINGS_DIR = path.join(DEFAULT_SETTINGS_DIR, 'scopes');\nexport const DEFAULT_HISTORY_DB_PATH = path.join(DEFAULT_SETTINGS_DIR, 'history.sqlite');\nexport const DEFAULT_AUTH_FILE_PATH = path.join(os.homedir(), '.codex', 'auth.json');\nexport const DEFAULT_HTTP_PORT = 43191;\nexport const DEFAULT_SERVICE_NAME = 'model-proxy-mcp-http';\nexport const DEFAULT_HISTORY_RETENTION_LIMIT = 1000;\n\nexport const DEFAULT_PROVIDER_SETTINGS: Record<string, ProviderRuntimeConfig> = {\n 'chatgpt-codex': {\n type: 'chatgpt-codex',\n endpoint: 'https://chatgpt.com/backend-api/codex/responses',\n authTokenEnvVar: null,\n apiTimeoutMs: null,\n },\n 'zai-anthropic-compat': {\n type: 'anthropic-compatible',\n endpoint: 'https://api.z.ai/api/anthropic/v1/messages',\n authTokenEnvVar: 'ZAI_ANTHROPIC_AUTH_TOKEN',\n apiTimeoutMs: 3000000,\n },\n 'google-gemini-direct': {\n type: 'gemini-direct',\n endpoint: 'https://generativelanguage.googleapis.com',\n authTokenEnvVar: 'GEMINI_API_KEY',\n apiTimeoutMs: 300000,\n authMode: 'auto',\n apiKeyEnvVar: 'GEMINI_API_KEY',\n project: null,\n location: 'global',\n apiVersion: 'v1beta',\n },\n};\n\nexport const DEFAULT_MODEL_LIST: ProxyModelConfig[] = [\n {\n id: 'chatgpt-codex-gpt-5.3-codex',\n label: 'ChatGPT Codex GPT-5.3 Codex',\n provider: 'chatgpt-codex',\n model: 'gpt-5.3-codex',\n reasoningEffort: 'medium',\n enabled: true,\n },\n {\n id: 'chatgpt-codex-gpt-5.3-codex-low',\n label: 'ChatGPT Codex GPT-5.3 Codex Low',\n provider: 'chatgpt-codex',\n model: 'gpt-5.3-codex',\n reasoningEffort: 'low',\n enabled: true,\n },\n {\n id: 'chatgpt-codex-gpt-5.4',\n label: 'ChatGPT Codex GPT-5.4',\n provider: 'chatgpt-codex',\n model: 'gpt-5.4',\n reasoningEffort: 'medium',\n enabled: true,\n },\n {\n id: 'chatgpt-codex-gpt-5.2',\n label: 'ChatGPT Codex GPT-5.2',\n provider: 'chatgpt-codex',\n model: 'gpt-5.2',\n reasoningEffort: 'medium',\n enabled: true,\n },\n {\n id: 'zai-anthropic-compat-glm-4.7',\n label: 'Z.ai GLM-4.7',\n provider: 'zai-anthropic-compat',\n model: 'GLM-4.7',\n reasoningEffort: 'high',\n enabled: true,\n },\n {\n id: 'zai-anthropic-compat-glm-5',\n label: 'Z.ai GLM-5',\n provider: 'zai-anthropic-compat',\n model: 'glm-5',\n reasoningEffort: 'high',\n enabled: true,\n },\n {\n id: 'zai-anthropic-compat-glm-4.5-air',\n label: 'Z.ai GLM-4.5-Air',\n provider: 'zai-anthropic-compat',\n model: 'GLM-4.5-Air',\n reasoningEffort: 'medium',\n enabled: true,\n },\n {\n id: 'google-gemini-direct-gemini-2.5-flash',\n label: 'Google Gemini 2.5 Flash',\n provider: 'google-gemini-direct',\n model: 'gemini-2.5-flash',\n reasoningEffort: 'medium',\n enabled: true,\n },\n {\n id: 'google-gemini-direct-gemini-3-flash-preview',\n label: 'Google Gemini 3 Flash Preview',\n provider: 'google-gemini-direct',\n model: 'gemini-3-flash-preview',\n reasoningEffort: 'medium',\n enabled: true,\n },\n {\n id: 'google-gemini-direct-gemini-3.1-pro-preview',\n label: 'Google Gemini 3.1 Pro Preview',\n provider: 'google-gemini-direct',\n model: 'gemini-3.1-pro-preview',\n reasoningEffort: 'high',\n enabled: true,\n },\n];\n\nexport const DEFAULT_SCOPE_SETTINGS: ScopeSettings = {\n models: {\n default: {\n main: { provider: 'chatgpt-codex', model: 'gpt-5.4', reasoningEffort: 'medium' },\n fallbacks: [{ provider: 'chatgpt-codex', model: 'gpt-5.4', reasoningEffort: 'low' }],\n },\n sonnet: {\n main: { provider: 'chatgpt-codex', model: 'gpt-5.3-codex', reasoningEffort: 'medium' },\n fallbacks: [{ provider: 'chatgpt-codex', model: 'gpt-5.4', reasoningEffort: 'medium' }],\n },\n opus: {\n main: { provider: 'chatgpt-codex', model: 'gpt-5.4', reasoningEffort: 'medium' },\n fallbacks: [{ provider: 'chatgpt-codex', model: 'gpt-5.4', reasoningEffort: 'low' }],\n },\n haiku: {\n main: { provider: 'chatgpt-codex', model: 'gpt-5.3-codex', reasoningEffort: 'low' },\n fallbacks: [{ provider: 'chatgpt-codex', model: 'gpt-5.4', reasoningEffort: 'medium' }],\n },\n subagent: {\n main: { provider: 'chatgpt-codex', model: 'gpt-5.3-codex', reasoningEffort: 'low' },\n fallbacks: [{ provider: 'chatgpt-codex', model: 'gpt-5.4', reasoningEffort: 'medium' }],\n },\n },\n};\n\nexport const DEFAULT_SETTINGS: ProxySettings = {\n providers: DEFAULT_PROVIDER_SETTINGS,\n models: DEFAULT_MODEL_LIST,\n scope: DEFAULT_SCOPE_SETTINGS,\n};\n","import type { LoggerLike } from '../types/index.js';\n\nexport const consoleLogger: LoggerLike = {\n info: (msg, data) => console.error(msg, data ?? ''),\n error: (msg, error) => console.error(msg, error ?? ''),\n debug: () => undefined,\n warn: (msg, data) => console.error(msg, data ?? ''),\n};\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport { z } from 'zod';\nimport {\n DEFAULT_MODEL_LIST,\n DEFAULT_MODEL_LIST_PATH,\n DEFAULT_MODEL_PROVIDER_PATH,\n DEFAULT_PROVIDER_SETTINGS,\n DEFAULT_SCOPE_SETTINGS,\n DEFAULT_SCOPE_SETTINGS_DIR,\n} from '../constants/defaults.js';\nimport type {\n AdminConfig,\n AdminConfigUpdate,\n ModelSlot,\n ProviderRuntimeConfig,\n ProxyConfig,\n ProxyModelConfig,\n ProxyProfile,\n ProxySettings,\n ReasoningEffort,\n ResolvedSlotConfig,\n ScopeModelSelection,\n ScopeSettings,\n} from '../types/index.js';\nimport { consoleLogger } from './logger.js';\n\nconst DEFAULT_SCOPE = 'default';\nconst DEFAULT_ZAI_PROVIDER_ID = 'zai-anthropic-compat';\nconst LEGACY_ZAI_AUTH_ENV = 'ANTHROPIC_AUTH_TOKEN';\nconst DEFAULT_ZAI_AUTH_ENV = 'ZAI_ANTHROPIC_AUTH_TOKEN';\nconst SETTINGS_EXTENSION = '.yaml';\nconst DEFAULT_REASONING_EFFORT: ReasoningEffort = 'medium';\nconst MODEL_SLOTS: ModelSlot[] = ['default', 'sonnet', 'opus', 'haiku', 'subagent'];\nconst LOG_PREFIX = '[model-proxy-mcp]';\nconst FILE_NOT_FOUND_ERROR_CODE = 'ENOENT';\nconst YAML_INDENT = 2;\nconst FILE_ENCODING: BufferEncoding = 'utf8';\nconst PROVIDER_TYPES = ['chatgpt-codex', 'anthropic-compatible', 'gemini-direct'] as const;\nconst PROFILE_STORE_ERROR_CODES = {\n profileNotFound: 'PROFILE_NOT_FOUND',\n settingsReadFailed: 'SETTINGS_READ_FAILED',\n settingsWriteFailed: 'SETTINGS_WRITE_FAILED',\n} as const;\ntype ProfileStoreErrorCode = (typeof PROFILE_STORE_ERROR_CODES)[keyof typeof PROFILE_STORE_ERROR_CODES];\n\nconst reasoningEffortSchema = z.enum(['minimal', 'low', 'medium', 'high']);\nconst providerRuntimeConfigSchema = z.object({\n type: z.enum(PROVIDER_TYPES),\n endpoint: z.url(),\n authTokenEnvVar: z.string().min(1).nullable().optional(),\n apiTimeoutMs: z.number().int().positive().nullable().optional(),\n authMode: z.enum(['auto', 'api-key', 'oauth']).nullable().optional(),\n apiKeyEnvVar: z.string().min(1).nullable().optional(),\n project: z.string().min(1).nullable().optional(),\n location: z.string().min(1).nullable().optional(),\n apiVersion: z.string().min(1).nullable().optional(),\n});\nconst providerRegistrySchema = z.object({\n providers: z.record(z.string().min(1), providerRuntimeConfigSchema),\n});\nconst modelConfigSchema = z.object({\n id: z.string().min(1),\n label: z.string().min(1),\n provider: z.string().min(1),\n model: z.string().min(1),\n reasoningEffort: reasoningEffortSchema.default(DEFAULT_REASONING_EFFORT),\n enabled: z.boolean().default(true),\n});\nconst selectionSchema = z.object({\n provider: z.string().min(1),\n model: z.string().min(1),\n reasoningEffort: reasoningEffortSchema.default(DEFAULT_REASONING_EFFORT),\n thinkingDisabled: z.boolean().optional(),\n});\nconst slotConfigSchema = z.object({\n main: selectionSchema,\n fallbacks: z.array(selectionSchema).default([]),\n});\nconst scopeSettingsSchema = z.object({\n models: z\n .object({\n default: slotConfigSchema.optional(),\n sonnet: slotConfigSchema.optional(),\n opus: slotConfigSchema.optional(),\n haiku: slotConfigSchema.optional(),\n subagent: slotConfigSchema.optional(),\n })\n .default({}),\n});\nconst modelListSchema = z.array(modelConfigSchema);\nconst adminConfigUpdateSchema = z.object({\n models: z\n .object({\n default: slotConfigSchema.nullable().optional(),\n sonnet: slotConfigSchema.nullable().optional(),\n opus: slotConfigSchema.nullable().optional(),\n haiku: slotConfigSchema.nullable().optional(),\n subagent: slotConfigSchema.nullable().optional(),\n })\n .optional(),\n});\n\nexport class ProfileStoreError extends Error {\n constructor(\n message: string,\n readonly code: ProfileStoreErrorCode,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = 'ProfileStoreError';\n }\n}\n\nexport class ProfileStore {\n constructor(\n private readonly providerConfigPath = process.env.MODEL_PROXY_MCP_PROVIDER_PATH || DEFAULT_MODEL_PROVIDER_PATH,\n private readonly modelListPath = process.env.MODEL_PROXY_MCP_MODEL_LIST_PATH ||\n path.join(\n path.dirname(process.env.MODEL_PROXY_MCP_PROVIDER_PATH || DEFAULT_MODEL_PROVIDER_PATH),\n path.basename(DEFAULT_MODEL_LIST_PATH),\n ),\n private readonly scopeSettingsDir = process.env.MODEL_PROXY_MCP_SCOPE_DIR ||\n path.join(\n path.dirname(process.env.MODEL_PROXY_MCP_PROVIDER_PATH || DEFAULT_MODEL_PROVIDER_PATH),\n path.basename(DEFAULT_SCOPE_SETTINGS_DIR),\n ),\n private readonly logger = consoleLogger,\n ) {}\n\n getConfigPath(scope = DEFAULT_SCOPE): string {\n return this.getScopeConfigPath(scope);\n }\n\n async ensureConfig(scope = DEFAULT_SCOPE, seedConfigPath?: string): Promise<ProxyConfig> {\n return this.getConfig(scope, seedConfigPath);\n }\n\n async listScopes(): Promise<string[]> {\n try {\n const entries = await fs.readdir(this.scopeSettingsDir, { withFileTypes: true });\n const scopes = new Set<string>([DEFAULT_SCOPE]);\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith(SETTINGS_EXTENSION)) {\n continue;\n }\n const scopeName = entry.name.slice(0, -SETTINGS_EXTENSION.length);\n if (scopeName) {\n scopes.add(scopeName);\n }\n }\n return Array.from(scopes).sort();\n } catch (error) {\n if (this.isFileNotFoundError(error)) {\n return [DEFAULT_SCOPE];\n }\n\n this.logger.error(`${LOG_PREFIX} Failed to list scopes`, {\n scopeSettingsDir: this.scopeSettingsDir,\n cause: error,\n });\n throw new ProfileStoreError(\n `Failed to list scopes in ${this.scopeSettingsDir}`,\n PROFILE_STORE_ERROR_CODES.settingsReadFailed,\n {\n cause: error,\n },\n );\n }\n }\n\n async getConfig(scope = DEFAULT_SCOPE, seedConfigPath?: string): Promise<ProxyConfig> {\n return this.toProxyConfig(await this.getSettings(scope, seedConfigPath));\n }\n\n async getAdminConfig(scope = DEFAULT_SCOPE): Promise<AdminConfig> {\n const settings = await this.getSettings(scope);\n const profiles = this.toProfiles(settings);\n const slots = Object.fromEntries(\n MODEL_SLOTS.map((slot) => [slot, this.resolveSlotConfig(settings, profiles, slot)]),\n ) as Record<ModelSlot, ResolvedSlotConfig>;\n\n return {\n scope,\n providerConfigPath: this.providerConfigPath,\n modelListPath: this.modelListPath,\n scopeConfigPath: this.getScopeConfigPath(scope),\n providers: settings.providers,\n models: profiles,\n scopeModels: settings.scope.models,\n slots,\n };\n }\n\n async listProfiles(scope = DEFAULT_SCOPE): Promise<ProxyProfile[]> {\n return (await this.getAdminConfig(scope)).models;\n }\n\n async getActiveProfile(scope = DEFAULT_SCOPE, slot: ModelSlot = DEFAULT_SCOPE): Promise<ProxyProfile | null> {\n const config = await this.getAdminConfig(scope);\n const resolvedSlot = config.slots[slot];\n return config.models.find((profile) => profile.id === resolvedSlot.profileId && profile.enabled) ?? null;\n }\n\n async getResolvedSlotConfig(scope = DEFAULT_SCOPE, slot: ModelSlot = DEFAULT_SCOPE): Promise<ResolvedSlotConfig> {\n return (await this.getAdminConfig(scope)).slots[slot];\n }\n\n async setActiveProfile(\n profileId: string,\n scope = DEFAULT_SCOPE,\n slot: ModelSlot = DEFAULT_SCOPE,\n ): Promise<ProxyConfig> {\n const settings = await this.getSettings(scope);\n const profile = this.toProfiles(settings).find((item) => item.id === profileId && item.enabled);\n if (!profile) {\n throw new ProfileStoreError(\n `Profile not found or disabled: ${profileId}`,\n PROFILE_STORE_ERROR_CODES.profileNotFound,\n {\n cause: { profileId, scope, slot },\n },\n );\n }\n\n return this.updateConfig(\n {\n models: {\n [slot]: {\n main: {\n provider: profile.provider,\n model: profile.model,\n reasoningEffort: profile.reasoningEffort,\n thinkingDisabled: settings.scope.models[slot]?.main.thinkingDisabled ?? false,\n },\n fallbacks: settings.scope.models[slot]?.fallbacks ?? [],\n },\n },\n },\n scope,\n );\n }\n\n async upsertProfile(profile: ProxyProfile, scope = DEFAULT_SCOPE): Promise<ProxyConfig> {\n const nextProfile = modelConfigSchema.parse({\n id: profile.id,\n label: profile.label,\n provider: profile.provider,\n model: profile.model,\n reasoningEffort: profile.reasoningEffort,\n enabled: profile.enabled,\n });\n const settings = await this.getSettings(scope);\n const models = settings.models.filter((item) => item.id !== nextProfile.id);\n models.push(nextProfile);\n const nextSettings = this.normalizeSettings({\n providers: settings.providers,\n models,\n scope: settings.scope,\n });\n await this.saveSettings(nextSettings, scope);\n return this.toProxyConfig(nextSettings);\n }\n\n async updateConfig(update: AdminConfigUpdate, scope = DEFAULT_SCOPE): Promise<ProxyConfig> {\n const parsedUpdate = adminConfigUpdateSchema.parse(update);\n const settings = await this.getSettings(scope);\n const nextScopeModels: ScopeSettings['models'] = { ...settings.scope.models };\n\n for (const slot of MODEL_SLOTS) {\n const selection = parsedUpdate.models?.[slot];\n if (selection === undefined) {\n continue;\n }\n if (selection === null) {\n delete nextScopeModels[slot];\n continue;\n }\n nextScopeModels[slot] = selection;\n }\n\n const nextSettings = this.normalizeSettings({\n providers: settings.providers,\n models: settings.models,\n scope: { models: nextScopeModels },\n });\n await this.saveSettings(nextSettings, scope);\n return this.toProxyConfig(nextSettings);\n }\n\n private getScopeConfigPath(scope: string): string {\n return path.join(this.scopeSettingsDir, `${this.sanitizeScope(scope)}${SETTINGS_EXTENSION}`);\n }\n\n private sanitizeScope(scope: string): string {\n return (\n scope\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/--+/g, '-')\n .replace(/^-|-$/g, '') || DEFAULT_SCOPE\n );\n }\n\n private async getSettings(scope: string, seedConfigPath?: string): Promise<ProxySettings> {\n const settings = await this.readSettings(scope, seedConfigPath);\n const normalized = this.normalizeSettings(settings);\n if (JSON.stringify(normalized) !== JSON.stringify(settings)) {\n await this.saveSettings(normalized, scope);\n }\n return normalized;\n }\n\n private async readSettings(scope: string, seedConfigPath?: string): Promise<ProxySettings> {\n const scopeConfigPath = this.getScopeConfigPath(scope);\n const [providerResult, modelListResult, scopeResult] = await Promise.allSettled([\n fs.readFile(this.providerConfigPath, FILE_ENCODING),\n fs.readFile(this.modelListPath, FILE_ENCODING),\n fs.readFile(scopeConfigPath, FILE_ENCODING),\n ]);\n\n try {\n const providerRaw = providerResult.status === 'fulfilled' ? providerResult.value : null;\n const modelListRaw = modelListResult.status === 'fulfilled' ? modelListResult.value : null;\n const scopeRaw = scopeResult.status === 'fulfilled' ? scopeResult.value : null;\n const providerMissing = providerResult.status === 'rejected' && this.isFileNotFoundError(providerResult.reason);\n const modelListMissing =\n modelListResult.status === 'rejected' && this.isFileNotFoundError(modelListResult.reason);\n const scopeMissing = scopeResult.status === 'rejected' && this.isFileNotFoundError(scopeResult.reason);\n\n if (!providerRaw && providerResult.status === 'rejected' && !providerMissing) {\n throw providerResult.reason;\n }\n if (!modelListRaw && modelListResult.status === 'rejected' && !modelListMissing) {\n throw modelListResult.reason;\n }\n if (!scopeRaw && scopeResult.status === 'rejected' && !scopeMissing) {\n throw scopeResult.reason;\n }\n\n const scopeSettings = scopeRaw\n ? scopeSettingsSchema.parse(parseYaml(scopeRaw))\n : await this.loadScopeSeedSettings(scope, seedConfigPath);\n const settings = this.normalizeSettings({\n providers: providerRaw\n ? providerRegistrySchema.parse(parseYaml(providerRaw)).providers\n : structuredClone(DEFAULT_PROVIDER_SETTINGS),\n models: modelListRaw ? modelListSchema.parse(parseYaml(modelListRaw)) : structuredClone(DEFAULT_MODEL_LIST),\n scope: scopeSettings,\n });\n\n if (providerMissing || modelListMissing || scopeMissing) {\n await this.saveSettings(settings, scope);\n }\n\n return settings;\n } catch (error) {\n this.logger.error(`${LOG_PREFIX} Failed to read settings`, {\n scope,\n providerConfigPath: this.providerConfigPath,\n modelListPath: this.modelListPath,\n scopeConfigPath,\n code: PROFILE_STORE_ERROR_CODES.settingsReadFailed,\n cause: error,\n });\n throw new ProfileStoreError(\n `Failed to read settings from ${this.providerConfigPath}, ${this.modelListPath}, and ${scopeConfigPath}`,\n PROFILE_STORE_ERROR_CODES.settingsReadFailed,\n { cause: error },\n );\n }\n }\n\n private isFileNotFoundError(error: unknown): boolean {\n return (error as NodeJS.ErrnoException | undefined)?.code === FILE_NOT_FOUND_ERROR_CODE;\n }\n\n private async loadScopeSeedSettings(scope: string, seedConfigPath?: string): Promise<ScopeSettings> {\n const candidatePaths = [seedConfigPath, this.getDefaultScopeSeedPath(scope)].filter(\n (candidate): candidate is string => Boolean(candidate),\n );\n\n for (const candidatePath of candidatePaths) {\n try {\n const raw = await fs.readFile(candidatePath, FILE_ENCODING);\n return scopeSettingsSchema.parse(parseYaml(raw));\n } catch (error) {\n if (this.isFileNotFoundError(error)) {\n continue;\n }\n\n this.logger.error(`${LOG_PREFIX} Failed to read scope seed settings`, {\n scope,\n seedConfigPath: candidatePath,\n cause: error,\n });\n throw error;\n }\n }\n\n return structuredClone(DEFAULT_SCOPE_SETTINGS);\n }\n\n private getDefaultScopeSeedPath(scope: string): string | null {\n const defaultScopePath = this.getScopeConfigPath(DEFAULT_SCOPE);\n return scope === DEFAULT_SCOPE ? null : defaultScopePath;\n }\n\n private normalizeSettings(settings: ProxySettings): ProxySettings {\n const providers = this.normalizeProviders(\n Object.keys(settings.providers).length > 0 ? settings.providers : structuredClone(DEFAULT_PROVIDER_SETTINGS),\n );\n const models = settings.models.map((model) => modelConfigSchema.parse(model));\n const defaultSelection = this.normalizeSlotSelection(\n settings.scope.models.default?.main ?? null,\n models,\n providers,\n this.getDefaultSelection(models, providers),\n );\n\n const normalizedScopeModels: ScopeSettings['models'] = {\n default: defaultSelection\n ? {\n main: defaultSelection,\n fallbacks: this.normalizeFallbacks(\n settings.scope.models.default?.fallbacks ?? [],\n defaultSelection,\n models,\n providers,\n ),\n }\n : undefined,\n };\n\n for (const slot of MODEL_SLOTS) {\n if (slot === DEFAULT_SCOPE) {\n continue;\n }\n\n const fallback = defaultSelection ?? this.getDefaultSelection(models, providers);\n const selection = this.normalizeSlotSelection(\n settings.scope.models[slot]?.main ?? null,\n models,\n providers,\n fallback,\n );\n normalizedScopeModels[slot] = selection\n ? {\n main: selection,\n fallbacks: this.normalizeFallbacks(\n settings.scope.models[slot]?.fallbacks ?? [],\n selection,\n models,\n providers,\n ),\n }\n : undefined;\n }\n\n return {\n providers,\n models,\n scope: { models: normalizedScopeModels },\n };\n }\n\n private normalizeProviders(providers: Record<string, ProviderRuntimeConfig>): Record<string, ProviderRuntimeConfig> {\n const normalizedProviders = { ...providers };\n const zaiProvider = normalizedProviders[DEFAULT_ZAI_PROVIDER_ID];\n if (zaiProvider?.type === 'anthropic-compatible' && zaiProvider.authTokenEnvVar === LEGACY_ZAI_AUTH_ENV) {\n normalizedProviders[DEFAULT_ZAI_PROVIDER_ID] = {\n ...zaiProvider,\n authTokenEnvVar: DEFAULT_ZAI_AUTH_ENV,\n };\n }\n\n return normalizedProviders;\n }\n\n private getDefaultSelection(\n models: ProxyModelConfig[],\n providers: Record<string, ProviderRuntimeConfig>,\n ): ScopeModelSelection | null {\n const fallbackModel = models.find((model) => model.enabled && providers[model.provider]);\n if (!fallbackModel) {\n return null;\n }\n\n return {\n provider: fallbackModel.provider,\n model: fallbackModel.model,\n reasoningEffort: fallbackModel.reasoningEffort,\n thinkingDisabled: false,\n };\n }\n\n private normalizeSlotSelection(\n selection: ScopeModelSelection | null,\n models: ProxyModelConfig[],\n providers: Record<string, ProviderRuntimeConfig>,\n fallback: ScopeModelSelection | null,\n ): ScopeModelSelection | null {\n if (!selection) {\n return fallback ? { ...fallback } : null;\n }\n\n const provider = providers[selection.provider] ? selection.provider : (fallback?.provider ?? null);\n if (!provider) {\n return null;\n }\n if (provider !== selection.provider) {\n return fallback && providers[fallback.provider] ? { ...fallback } : null;\n }\n\n const catalogEntry = models.find(\n (model) => model.enabled && model.provider === provider && model.model === selection.model,\n );\n\n return {\n provider,\n model: catalogEntry?.model ?? selection.model,\n reasoningEffort: selection.reasoningEffort ?? catalogEntry?.reasoningEffort ?? DEFAULT_REASONING_EFFORT,\n thinkingDisabled: selection.thinkingDisabled ?? false,\n };\n }\n\n private normalizeFallbacks(\n fallbacks: ScopeModelSelection[],\n main: ScopeModelSelection,\n models: ProxyModelConfig[],\n providers: Record<string, ProviderRuntimeConfig>,\n ): ScopeModelSelection[] {\n const normalized: ScopeModelSelection[] = [];\n const seen = new Set([\n `${main.provider}:${main.model}:${main.reasoningEffort}:${main.thinkingDisabled ? 'off' : 'on'}`,\n ]);\n\n for (const fallback of fallbacks) {\n const nextFallback = this.normalizeSlotSelection(fallback, models, providers, null);\n if (!nextFallback) {\n continue;\n }\n\n const key = `${nextFallback.provider}:${nextFallback.model}:${nextFallback.reasoningEffort}:${nextFallback.thinkingDisabled ? 'off' : 'on'}`;\n if (seen.has(key)) {\n continue;\n }\n\n seen.add(key);\n normalized.push(nextFallback);\n }\n\n return normalized;\n }\n\n private toProxyConfig(settings: ProxySettings): ProxyConfig {\n const profiles = this.toProfiles(settings);\n const slotProfileIds = Object.fromEntries(\n MODEL_SLOTS.map((slot) => {\n const resolved = this.resolveSlotConfig(settings, profiles, slot);\n return [slot, resolved.profileId];\n }),\n ) as ProxyConfig['slotProfileIds'];\n\n return {\n activeProfileId: slotProfileIds.default ?? null,\n slotProfileIds,\n providers: settings.providers,\n profiles,\n scope: settings.scope,\n };\n }\n\n private resolveSlotConfig(settings: ProxySettings, profiles: ProxyProfile[], slot: ModelSlot): ResolvedSlotConfig {\n const slotConfig = settings.scope.models[slot] ?? settings.scope.models.default;\n const selection = slotConfig?.main ?? null;\n const profile = selection\n ? profiles.find((item) => item.provider === selection.provider && item.model === selection.model && item.enabled)\n : undefined;\n const provider = selection?.provider ? settings.providers[selection.provider] : undefined;\n\n return {\n slot,\n profileId: profile?.id ?? null,\n label: profile?.label ?? null,\n provider: selection?.provider ?? null,\n providerType: provider?.type ?? null,\n endpoint: provider?.endpoint ?? null,\n model: selection?.model ?? null,\n reasoningEffort: selection?.reasoningEffort ?? profile?.reasoningEffort ?? DEFAULT_REASONING_EFFORT,\n thinkingDisabled: selection?.thinkingDisabled ?? false,\n fallbacks: slotConfig?.fallbacks ?? [],\n };\n }\n\n private toProfiles(settings: ProxySettings): ProxyProfile[] {\n return settings.models.map((model) => ({\n id: model.id,\n label: model.label,\n provider: model.provider,\n providerType: settings.providers[model.provider]?.type ?? null,\n model: model.model,\n endpoint: settings.providers[model.provider]?.endpoint ?? null,\n reasoningEffort: model.reasoningEffort,\n enabled: model.enabled,\n }));\n }\n\n private async saveSettings(settings: ProxySettings, scope = DEFAULT_SCOPE): Promise<void> {\n const scopeConfigPath = this.getScopeConfigPath(scope);\n try {\n const directories = new Set([\n path.dirname(this.providerConfigPath),\n path.dirname(this.modelListPath),\n path.dirname(scopeConfigPath),\n ]);\n await Promise.all(Array.from(directories, (directory) => fs.mkdir(directory, { recursive: true })));\n await Promise.all([\n fs.writeFile(\n this.providerConfigPath,\n stringifyYaml(providerRegistrySchema.parse({ providers: settings.providers }), { indent: YAML_INDENT }),\n FILE_ENCODING,\n ),\n fs.writeFile(\n this.modelListPath,\n stringifyYaml(modelListSchema.parse(settings.models), { indent: YAML_INDENT }),\n FILE_ENCODING,\n ),\n fs.writeFile(\n scopeConfigPath,\n stringifyYaml(scopeSettingsSchema.parse(settings.scope), { indent: YAML_INDENT }),\n FILE_ENCODING,\n ),\n ]);\n } catch (error) {\n this.logger.error(`${LOG_PREFIX} Failed to write settings`, {\n scope,\n providerConfigPath: this.providerConfigPath,\n modelListPath: this.modelListPath,\n scopeConfigPath,\n code: PROFILE_STORE_ERROR_CODES.settingsWriteFailed,\n cause: error,\n });\n throw new ProfileStoreError(\n `Failed to write settings to ${this.providerConfigPath}, ${this.modelListPath}, and ${scopeConfigPath}`,\n PROFILE_STORE_ERROR_CODES.settingsWriteFailed,\n { cause: error },\n );\n }\n }\n}\n","/**\n * Claude to OpenAI Request Transformer\n *\n * Converts Anthropic Claude Messages API requests to OpenAI Responses API format.\n * Handles message structure, system prompts, streaming, and other parameters.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { RequestTransformer, RouterConfig, TransformedRequest } from './types';\n\n// ESM-compatible __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst CODEX_MD_PATH = path.join(__dirname, 'codex.md');\nlet cachedCodexInstructions: string | null = null;\n\nexport class ClaudeToOpenAITransformer implements RequestTransformer {\n private config: RouterConfig;\n private codexInstructions: string;\n\n constructor(config: RouterConfig) {\n this.config = config;\n // Load Codex CLI system prompt\n this.codexInstructions = this.loadCodexInstructions();\n }\n\n /**\n * Load the complete Codex CLI system prompt from codex.md\n */\n private loadCodexInstructions(): string {\n if (cachedCodexInstructions !== null) {\n return cachedCodexInstructions;\n }\n\n try {\n cachedCodexInstructions = fs.readFileSync(CODEX_MD_PATH, 'utf-8');\n return cachedCodexInstructions;\n } catch (error) {\n // Fallback: return empty string if file not found\n console.warn(`Warning: Could not load codex.md from ${CODEX_MD_PATH}`);\n cachedCodexInstructions = '';\n return '';\n }\n }\n\n async transform(_url: string, requestBody: string): Promise<TransformedRequest> {\n try {\n const claudeRequest = JSON.parse(requestBody);\n\n // Log original Claude request body\n this.config.logger?.debug('[ClaudeToOpenAI] ===== ORIGINAL CLAUDE REQUEST =====');\n this.config.logger?.debug('[ClaudeToOpenAI] Original body', {\n body: JSON.stringify(claudeRequest, null, 2),\n });\n\n // Generate conversation/session IDs for Responses API\n const sessionId = this.config.sessionId || randomUUID();\n const conversationId = sessionId;\n\n // Determine reasoning effort:\n // 1. Use session-level override if provided\n // 2. Fall back to model-based detection (Haiku = minimal, others = medium)\n const sessionReasoningEffort = this.config.sessionReasoningEffort;\n const isHaikuModel = claudeRequest.model && claudeRequest.model.toLowerCase().includes('haiku');\n const reasoningEffort = sessionReasoningEffort || (isHaikuModel ? 'minimal' : 'medium');\n\n this.config.logger?.debug('[ClaudeToOpenAI] Model detection and reasoning effort', {\n originalModel: claudeRequest.model,\n isHaikuModel,\n sessionReasoningEffort: sessionReasoningEffort || 'none',\n finalReasoningEffort: reasoningEffort,\n source: sessionReasoningEffort ? 'session override' : 'model-based',\n });\n\n // Transform to Responses API format\n const responsesRequest: any = {\n model: this.config.toModel || 'gpt-5',\n stream: true,\n store: false, // Required by Responses API\n tool_choice: 'auto',\n parallel_tool_calls: false,\n prompt_cache_key: sessionId,\n };\n\n if (!this.config.thinkingDisabled) {\n responsesRequest.reasoning = {\n effort: reasoningEffort, // Use minimal effort for Haiku models\n summary: 'auto',\n };\n responsesRequest.include = ['reasoning.encrypted_content'];\n }\n\n this.config.logger?.debug('[ClaudeToOpenAI] Thinking mode', {\n thinkingDisabled: this.config.thinkingDisabled ?? false,\n });\n\n // Use Codex CLI system prompt as instructions (required for ChatGPT Responses API)\n // Replace Claude-specific model information with ChatGPT model information\n responsesRequest.instructions = this.adaptInstructionsForChatGPT(this.codexInstructions);\n\n // Convert messages to input array format, prepending Claude system messages to first user message\n const input: any[] = [];\n\n // Extract Claude system messages and prepend to first user message\n let claudeSystemPrompt = '';\n if (claudeRequest.system) {\n const systemMessages = this.extractSystemMessages(claudeRequest.system);\n // Add defensive check to ensure systemMessages is an array\n if (systemMessages && Array.isArray(systemMessages) && systemMessages.length > 0) {\n claudeSystemPrompt = systemMessages.map((msg: any) => msg.content).join('\\n\\n');\n }\n }\n\n // Filter out Claude Code-specific instructions from user messages\n claudeSystemPrompt = this.removeClaudeCodeInstructions(claudeSystemPrompt);\n\n if (claudeSystemPrompt) {\n input.push({\n type: 'message',\n role: 'user',\n content: [\n {\n type: 'input_text',\n text: claudeSystemPrompt,\n },\n ],\n });\n }\n\n if (claudeRequest.messages && Array.isArray(claudeRequest.messages)) {\n for (const msg of claudeRequest.messages) {\n const converted = this.convertMessageToInput(msg);\n if (Array.isArray(converted)) {\n // convertMessageToInput can return multiple messages (for tool results)\n input.push(...converted);\n } else if (converted) {\n input.push(converted);\n }\n }\n }\n responsesRequest.input = input;\n\n // Handle tools/function calling\n if (claudeRequest.tools && Array.isArray(claudeRequest.tools)) {\n this.config.logger?.debug('[ClaudeToOpenAI] Original Claude tools', {\n tools: JSON.stringify(claudeRequest.tools, null, 2),\n });\n const convertedTools = this.convertTools(claudeRequest.tools);\n this.config.logger?.debug('[ClaudeToOpenAI] Converted tools', {\n tools: JSON.stringify(convertedTools, null, 2),\n });\n\n // Only add tools if there are valid ones after conversion\n if (convertedTools.length > 0) {\n responsesRequest.tools = convertedTools;\n this.config.logger?.debug('[ClaudeToOpenAI] Added tools to responsesRequest', {\n toolCount: convertedTools.length,\n });\n // Verify tools were actually set\n this.config.logger?.debug('[ClaudeToOpenAI] Verify responsesRequest.tools exists', {\n hasTools: !!responsesRequest.tools,\n toolsLength: responsesRequest.tools?.length,\n keys: Object.keys(responsesRequest),\n });\n } else {\n this.config.logger?.warn('[ClaudeToOpenAI] No valid tools after conversion, omitting tools field');\n }\n } else {\n this.config.logger?.debug('[ClaudeToOpenAI] No tools in Claude request', {\n hasTools: !!claudeRequest.tools,\n isArray: Array.isArray(claudeRequest.tools),\n });\n }\n\n // Responses API endpoint\n const targetUrl = this.config.toEndpoint || 'https://chatgpt.com/backend-api/codex/responses';\n\n // Build headers for Responses API\n const headers: Record<string, string> = {\n version: '0.46.0',\n 'openai-beta': 'responses=experimental',\n conversation_id: conversationId,\n session_id: sessionId,\n accept: 'text/event-stream',\n 'content-type': 'application/json',\n 'user-agent': 'codex_cli_rs/0.46.0 (Mac OS 15.6.0; arm64) iTerm.app/3.6.2',\n originator: 'codex_cli_rs',\n };\n\n const resolvedAuth = this.config.resolvedAuth;\n if (resolvedAuth?.accessToken) {\n this.config.logger?.debug('[ClaudeToOpenAI] Raw access token', {\n token: `${resolvedAuth.accessToken.substring(0, 30)}...`,\n });\n headers.authorization = resolvedAuth.accessToken.startsWith('Bearer ')\n ? resolvedAuth.accessToken\n : `Bearer ${resolvedAuth.accessToken}`;\n if (resolvedAuth.accountId) {\n headers['chatgpt-account-id'] = resolvedAuth.accountId;\n }\n } else if (this.config.toApiKey) {\n headers.authorization = `Bearer ${this.config.toApiKey}`;\n }\n\n if (headers.authorization?.startsWith('Bearer ')) {\n this.config.logger?.debug('[ClaudeToOpenAI] Added Bearer auth header');\n }\n\n // Debug logging\n this.config.logger?.debug('[ClaudeToOpenAI] ===== REQUEST DETAILS =====');\n this.config.logger?.debug('[ClaudeToOpenAI] Target URL', { targetUrl });\n this.config.logger?.debug('[ClaudeToOpenAI] Headers', {\n headers: {\n ...headers,\n authorization: headers.authorization ? `${headers.authorization.substring(0, 30)}...` : undefined,\n },\n });\n this.config.logger?.debug('[ClaudeToOpenAI] Body', {\n body: JSON.stringify(responsesRequest, null, 2),\n });\n this.config.logger?.debug('[ClaudeToOpenAI] ===============================');\n\n // Log final transformed body\n this.config.logger?.debug('[ClaudeToOpenAI] ===== FINAL TRANSFORMED REQUEST =====');\n this.config.logger?.debug('[ClaudeToOpenAI] Pre-final check - responsesRequest.tools', {\n hasTools: !!responsesRequest.tools,\n toolsLength: responsesRequest.tools?.length,\n keys: Object.keys(responsesRequest),\n });\n this.config.logger?.debug('[ClaudeToOpenAI] Final body', {\n body: JSON.stringify(responsesRequest, null, 2),\n });\n this.config.logger?.debug('[ClaudeToOpenAI] ===== END FINAL TRANSFORMED REQUEST =====');\n\n return {\n url: targetUrl,\n body: JSON.stringify(responsesRequest),\n headers,\n };\n } catch (error) {\n throw new Error(`Failed to transform Claude request to OpenAI: ${error}`);\n }\n }\n\n /**\n * Adapt Codex instructions for ChatGPT by replacing Claude-specific model information\n */\n private adaptInstructionsForChatGPT(instructions: string): string {\n let adapted = instructions;\n\n // Replace Claude model references with ChatGPT model references\n adapted = adapted.replace(\n /You are powered by the model named Sonnet 4\\.5\\. The exact model ID is claude-sonnet-4-5-\\d+\\./g,\n 'You are powered by ChatGPT (GPT-5 reasoning model).',\n );\n\n // Replace knowledge cutoff date\n adapted = adapted.replace(\n /Assistant knowledge cutoff is January 2025/g,\n 'Assistant knowledge cutoff is October 2023',\n );\n\n // Replace any other Claude-specific references\n adapted = adapted.replace(/\\bClaude\\b/g, 'ChatGPT');\n adapted = adapted.replace(/\\bAnthropic\\b/g, 'OpenAI');\n\n return adapted;\n }\n\n /**\n * Remove Claude Code-specific instructions from system messages\n * These should not be sent to ChatGPT as user messages\n */\n private removeClaudeCodeInstructions(text: string): string {\n // Remove Claude Code introduction and instructions\n const claudeCodePatterns = [\n /You are Claude Code, Anthropic's official CLI for Claude\\.[\\s\\S]*?claude_code_docs_map\\.md/,\n /You are Claude Code[\\s\\S]*?using Claude Code\\n/,\n ];\n\n let filtered = text;\n for (const pattern of claudeCodePatterns) {\n filtered = filtered.replace(pattern, '');\n }\n\n // Clean up excessive whitespace\n filtered = filtered.replace(/\\n{3,}/g, '\\n\\n').trim();\n\n return filtered;\n }\n\n /**\n * Extract and convert system messages from Claude format\n */\n private extractSystemMessages(system: any): any[] {\n const messages: any[] = [];\n\n if (typeof system === 'string') {\n messages.push({ role: 'system', content: system });\n } else if (Array.isArray(system)) {\n for (const item of system) {\n if (typeof item === 'string') {\n messages.push({ role: 'system', content: item });\n } else if (item.type === 'text' && item.text) {\n messages.push({ role: 'system', content: item.text });\n }\n }\n } else if (system.type === 'text' && system.text) {\n messages.push({ role: 'system', content: system.text });\n }\n\n return messages;\n }\n\n /**\n * Convert a single Claude message to Responses API input format\n * Returns a single message or array of messages (for tool results)\n */\n private convertMessageToInput(msg: any): any | any[] | null {\n if (!msg.role || !msg.content) return null;\n\n const textType = msg.role === 'assistant' ? 'output_text' : 'input_text';\n\n // Handle content array - check for tool results, tool uses, and images\n if (Array.isArray(msg.content)) {\n const result: any[] = [];\n let textContent: any[] = [];\n\n const flushTextContent = (): void => {\n if (textContent.length === 0) {\n return;\n }\n\n result.push({\n type: 'message',\n role: msg.role,\n content: textContent,\n });\n textContent = [];\n };\n\n for (const block of msg.content) {\n if (block.type === 'tool_result') {\n flushTextContent();\n // Convert to function_call_output\n const resultText = typeof block.content === 'string' ? block.content : JSON.stringify(block.content);\n result.push({\n type: 'function_call_output',\n call_id: block.tool_use_id,\n output: resultText,\n });\n } else if (block.type === 'text') {\n textContent.push({\n type: textType,\n text: block.text || '',\n });\n } else if (block.type === 'image') {\n // Convert Claude image format to OpenAI Codex format\n if (block.source && block.source.type === 'base64' && block.source.data) {\n const mediaType = block.source.media_type || 'image/jpeg';\n const imageUrl = `data:${mediaType};base64,${block.source.data}`;\n textContent.push({\n type: 'input_image',\n image_url: imageUrl,\n });\n this.config.logger?.debug('[ClaudeToOpenAI] Converted image block', {\n mediaType,\n dataLength: block.source.data.length,\n });\n } else {\n this.config.logger?.warn('[ClaudeToOpenAI] Unsupported image format', {\n source: block.source,\n });\n }\n } else if (block.type === 'tool_use') {\n flushTextContent();\n // Convert tool_use to function_call (for assistant messages in conversation history)\n result.push({\n type: 'function_call',\n call_id: block.id,\n name: block.name,\n arguments: JSON.stringify(block.input || {}),\n });\n }\n }\n\n flushTextContent();\n\n // Return array if we have multiple items, single item if just one, null if none\n if (result.length > 1) {\n return result;\n }\n if (result.length === 1) {\n return result[0];\n }\n\n return null;\n }\n\n if (typeof msg.content === 'string') {\n // Convert string content to content array format\n return {\n type: 'message',\n role: msg.role,\n content: [\n {\n type: textType,\n text: msg.content,\n },\n ],\n };\n }\n\n return null;\n }\n\n /**\n * Convert Claude tools to ChatGPT Responses API format\n *\n * The Responses API uses a flat structure with type at the top level:\n * { type: \"function\", name: \"...\", description: \"...\", parameters: {...} }\n */\n private convertTools(tools: any[]): any[] {\n // Add defensive check for undefined/null tools\n if (!tools || !Array.isArray(tools)) {\n return [];\n }\n\n return tools\n .filter((tool) => {\n // Validate that tool has required fields\n if (!tool || typeof tool !== 'object') {\n return false;\n }\n if (!tool.name) {\n return false;\n }\n return true;\n })\n .map((tool) => {\n // ChatGPT Responses API expects flat structure with type as a sibling field\n return {\n type: 'function',\n name: tool.name,\n description: tool.description || '',\n parameters: tool.input_schema || tool.parameters || {},\n };\n });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { consoleLogger } from '../../services/logger.js';\nimport type { LoggerLike } from '../../types/index.js';\n\ninterface CodexTokens {\n id_token: string;\n access_token: string;\n refresh_token: string;\n account_id: string;\n}\n\ninterface CodexAuthFile {\n OPENAI_API_KEY: string | null;\n tokens: CodexTokens;\n last_refresh: string | null;\n}\n\nexport interface ResolvedCodexAuth {\n accessToken: string | null;\n accountId: string | null;\n}\n\ninterface JWTPayload {\n exp?: number;\n iat?: number;\n [key: string]: unknown;\n}\n\nexport class CodexAuth {\n private static readonly TOKEN_REFRESH_URL = 'https://auth.openai.com/oauth/token';\n private static readonly CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';\n\n constructor(\n private readonly logger: LoggerLike = consoleLogger,\n private readonly authFilePath = path.join(process.env.HOME || '', '.codex', 'auth.json'),\n ) {}\n\n getAuthFilePath(): string {\n return this.authFilePath;\n }\n\n async getAuthStatus(): Promise<{\n configured: boolean;\n accountId?: string | null;\n authFilePath: string;\n lastRefresh?: string | null;\n }> {\n const authData = this.readAuthFile();\n return {\n configured: Boolean(authData?.tokens?.refresh_token),\n accountId: authData?.tokens?.account_id ?? null,\n authFilePath: this.authFilePath,\n lastRefresh: authData?.last_refresh ?? null,\n };\n }\n\n async getAccountId(): Promise<string | null> {\n const auth = await this.resolveAuth();\n return auth.accountId;\n }\n\n async getAccessToken(): Promise<string | null> {\n const auth = await this.resolveAuth();\n return auth.accessToken;\n }\n\n async resolveAuth(): Promise<ResolvedCodexAuth> {\n const authData = this.readAuthFile();\n if (!authData?.tokens) {\n this.logger.warn('[CodexAuth] No tokens found in auth file');\n return { accessToken: null, accountId: null };\n }\n\n const currentAccountId = authData.tokens.account_id || null;\n let accessToken = authData.tokens.access_token;\n if (accessToken.startsWith('Bearer ')) {\n accessToken = accessToken.slice(7);\n }\n\n if (!this.isTokenExpired(accessToken)) {\n return { accessToken, accountId: currentAccountId };\n }\n\n const refreshed = await this.refreshAccessToken(authData.tokens.refresh_token);\n if (!refreshed) {\n return { accessToken: null, accountId: currentAccountId };\n }\n\n this.saveTokens(refreshed);\n return {\n accessToken: refreshed.access_token,\n accountId: refreshed.account_id || currentAccountId,\n };\n }\n\n private readAuthFile(): CodexAuthFile | null {\n try {\n if (!fs.existsSync(this.authFilePath)) {\n return null;\n }\n return JSON.parse(fs.readFileSync(this.authFilePath, 'utf8')) as CodexAuthFile;\n } catch (error) {\n this.logger.error('[CodexAuth] Failed to read auth file', error);\n return null;\n }\n }\n\n private isTokenExpired(token: string): boolean {\n const payload = this.decodeJWT(token);\n if (!payload?.exp) {\n return true;\n }\n\n const expiresAt = payload.exp * 1000;\n return expiresAt - Date.now() < 5 * 60 * 1000;\n }\n\n private decodeJWT(token: string): JWTPayload | null {\n try {\n const [, payload] = token.split('.');\n if (!payload) {\n return null;\n }\n return JSON.parse(Buffer.from(payload, 'base64url').toString('utf8')) as JWTPayload;\n } catch (error) {\n this.logger.error('[CodexAuth] Failed to decode JWT', error);\n return null;\n }\n }\n\n private async refreshAccessToken(refreshToken: string): Promise<CodexTokens | null> {\n try {\n const response = await fetch(CodexAuth.TOKEN_REFRESH_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: CodexAuth.CLIENT_ID,\n }),\n });\n\n if (!response.ok) {\n this.logger.error('[CodexAuth] Token refresh failed', await response.text());\n return null;\n }\n\n const data = (await response.json()) as {\n id_token?: string;\n access_token?: string;\n refresh_token?: string;\n account_id?: string;\n };\n\n return {\n id_token: data.id_token ?? '',\n access_token: (data.access_token ?? '').replace(/^Bearer\\s+/i, ''),\n refresh_token: data.refresh_token || refreshToken,\n account_id: data.account_id ?? '',\n };\n } catch (error) {\n this.logger.error('[CodexAuth] Failed to refresh token', error);\n return null;\n }\n }\n\n private saveTokens(tokens: CodexTokens): void {\n try {\n const authData = this.readAuthFile();\n if (!authData) {\n return;\n }\n\n authData.tokens = tokens;\n authData.last_refresh = new Date().toISOString();\n fs.writeFileSync(this.authFilePath, JSON.stringify(authData, null, 2), 'utf8');\n } catch (error) {\n this.logger.error('[CodexAuth] Failed to save tokens', error);\n }\n }\n}\n","/**\n * OpenAI to Claude Response Transformer\n *\n * Converts OpenAI Chat Completions API streaming responses (SSE format)\n * to Anthropic Claude Messages API streaming format.\n *\n * OpenAI SSE events: data: {\"choices\":[{\"delta\":{\"content\":\"text\"}}]}\n * Claude SSE events: event: content_block_delta\\ndata: {\"delta\":{\"type\":\"text\",\"text\":\"text\"}}\n */\n\nimport { ulid } from 'ulidx';\nimport type { LoggerLike } from '../../types/index.js';\nimport type { ResponseTransformer } from './types';\n\ninterface ParsedOpenAIStream {\n textSegments: string[];\n thinkingSegments: string[];\n toolCalls: Map<number, { id: string; name: string; argumentChunks: string[] }>;\n streamedReasoningKeys: Set<string>;\n streamedTextKeys: Set<string>;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cachedTokens?: number;\n reasoningTokens?: number;\n reasoningEffort?: string;\n stopReason?: string | null;\n errorMessage?: string;\n}\n\ninterface StreamState {\n encoder: InstanceType<typeof TextEncoder>;\n messageId: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cachedTokens?: number;\n reasoningTokens?: number;\n reasoningEffort?: string;\n stopReason?: string | null;\n messageStarted: boolean;\n messageStopped: boolean;\n thinkingBlockStarted: boolean;\n textBlockStarted: boolean;\n emittedThinking: boolean;\n emittedText: boolean;\n lastThinkingChunk: string | null;\n lastTextChunk: string | null;\n streamedReasoningKeys: Set<string>;\n streamedTextKeys: Set<string>;\n emittedToolCallIndexes: Set<number>;\n toolCalls: Map<number, { id: string; name: string; argumentChunks: string[] }>;\n}\n\nexport class OpenAIToClaudeTransformer implements ResponseTransformer {\n private logger?: LoggerLike;\n private readonly thinkingDisabled: boolean;\n\n constructor(logger?: LoggerLike, thinkingDisabled = false) {\n this.logger = logger;\n this.thinkingDisabled = thinkingDisabled;\n }\n\n private formatSseEvent(event: string, data: unknown): string {\n return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n }\n\n transform(responseBody: string): string {\n try {\n if (!responseBody || responseBody.trim() === '') {\n return this.createEmptyClaudeResponse();\n }\n\n if (!responseBody.includes('data:')) {\n return this.convertNonStreamingResponse(responseBody);\n }\n\n const result = this.convertStreamingResponse(responseBody);\n return result;\n } catch (error) {\n this.logger?.error('[OpenAIToClaude] ERROR in transform', error as Error);\n return this.createEmptyClaudeResponse();\n }\n }\n\n transformStream(upstreamBody: ReadableStream<Uint8Array>): ReadableStream<Uint8Array> {\n const state: StreamState = {\n encoder: new TextEncoder(),\n messageId: `msg_${ulid()}`,\n model: 'gpt-5',\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n reasoningEffort: undefined,\n stopReason: 'end_turn',\n messageStarted: false,\n messageStopped: false,\n thinkingBlockStarted: false,\n textBlockStarted: false,\n emittedThinking: false,\n emittedText: false,\n lastThinkingChunk: null,\n lastTextChunk: null,\n streamedReasoningKeys: new Set<string>(),\n streamedTextKeys: new Set<string>(),\n emittedToolCallIndexes: new Set<number>(),\n toolCalls: new Map<number, { id: string; name: string; argumentChunks: string[] }>(),\n };\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n return new ReadableStream<Uint8Array>({\n start: async (controller) => {\n const reader = upstreamBody.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n buffer = this.processBufferedEvents(buffer, state, controller);\n }\n\n buffer += decoder.decode();\n buffer = this.processBufferedEvents(buffer, state, controller, true);\n\n if (!state.messageStopped) {\n if (!state.messageStarted) {\n controller.enqueue(state.encoder.encode(this.createEmptyClaudeResponse()));\n } else {\n this.finishStreamingResponse(controller, state);\n }\n }\n } catch (error) {\n this.logger?.error('[OpenAIToClaude] ERROR in transformStream', error as Error);\n if (!state.messageStopped) {\n if (!state.messageStarted) {\n controller.enqueue(state.encoder.encode(this.createClaudeErrorStream('Unexpected API error')));\n } else {\n this.emitStreamingError(controller, state, 'Unexpected API error');\n }\n }\n } finally {\n controller.close();\n reader.releaseLock();\n }\n },\n });\n }\n\n /**\n * Create a valid empty Claude streaming response to prevent parsing errors\n */\n private createEmptyClaudeResponse(): string {\n const messageId = `msg_${ulid()}`;\n const events: string[] = [];\n\n events.push('event: message_start');\n events.push(\n `data: ${JSON.stringify({\n type: 'message_start',\n message: {\n id: messageId,\n type: 'message',\n role: 'assistant',\n content: [],\n model: 'gpt-5',\n stop_reason: null,\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n },\n })}`,\n );\n events.push('');\n\n events.push('event: message_stop');\n events.push('data: {\"type\":\"message_stop\"}');\n events.push('');\n\n return events.join('\\n');\n }\n\n private convertStreamingResponse(sseText: string): string {\n const parsed = this.parseOpenAIStream(sseText);\n const claudeStream = this.createClaudeStreamFromParsed(parsed);\n const fallbackMessage = parsed.errorMessage || 'Empty streaming response from provider';\n return this.ensureValidClaudeStream(claudeStream, fallbackMessage);\n }\n\n private parseOpenAIStream(sseText: string): ParsedOpenAIStream {\n const parsed: ParsedOpenAIStream = {\n textSegments: [],\n thinkingSegments: [],\n toolCalls: new Map<number, { id: string; name: string; argumentChunks: string[] }>(),\n streamedReasoningKeys: new Set<string>(),\n streamedTextKeys: new Set<string>(),\n model: 'gpt-5',\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n reasoningEffort: undefined,\n stopReason: undefined,\n errorMessage: undefined,\n };\n\n const lines = sseText.split('\\n');\n let currentEvent = '';\n const isResponsesApi =\n /event:\\s*response\\./i.test(sseText) ||\n /\"type\"\\s*:\\s*\"response\\./i.test(sseText) ||\n /\"response\"\\s*:\\s*\\{/i.test(sseText);\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) continue;\n\n if (line.startsWith('event:')) {\n currentEvent = line.slice(6).trim();\n continue;\n }\n\n if (!line.startsWith('data:')) continue;\n const dataContent = line.slice(5).trim();\n if (!dataContent || dataContent === '[DONE]') continue;\n\n let data: any;\n try {\n data = JSON.parse(dataContent);\n } catch {\n continue;\n }\n\n if (data?.error) {\n parsed.errorMessage =\n data.error?.message ||\n data.error?.error ||\n (typeof data.error === 'string' ? data.error : 'Unexpected API error');\n break;\n }\n\n if (isResponsesApi || currentEvent.startsWith('response.')) {\n this.handleResponsesEvent(currentEvent, data, parsed);\n } else {\n this.handleChatCompletionChunk(data, parsed);\n }\n }\n\n return parsed;\n }\n\n private handleResponsesEvent(eventName: string, data: any, parsed: ParsedOpenAIStream): void {\n const eventType = typeof data?.type === 'string' ? data.type : eventName;\n\n if (data?.model && typeof data.model === 'string') {\n parsed.model = data.model;\n }\n\n if (data?.usage) {\n parsed.inputTokens = data.usage.input_tokens ?? data.usage.prompt_tokens ?? parsed.inputTokens;\n parsed.outputTokens = data.usage.output_tokens ?? data.usage.completion_tokens ?? parsed.outputTokens;\n }\n\n switch (eventType) {\n case 'response.created':\n if (data?.response?.model) {\n parsed.model = data.response.model;\n }\n break;\n case 'response.reasoning.delta':\n case 'response.reasoning_summary_text.delta':\n case 'response.function_call_arguments.delta':\n case 'response.function_call_arguments.done':\n case 'response.in_progress':\n case 'response.output_item.added':\n case 'response.output_item.done':\n case 'response.content_part.added':\n case 'response.content_part.done':\n case 'response.reasoning_summary_part.added':\n case 'response.reasoning_summary_part.done':\n case 'response.reasoning_summary_text.done':\n case 'response.output_text.delta':\n case 'response.output_text.done':\n case 'response.delta':\n // For buffered conversion, ignore incremental Responses API events and\n // rely on the final response.completed/response.done envelope only.\n break;\n case 'response.completed':\n case 'response.done':\n this.collectCompletedResponse(data, parsed);\n break;\n case 'response.error':\n parsed.errorMessage = data?.error?.message || data?.message || 'Unexpected API error';\n break;\n default:\n if (data?.delta) {\n this.collectTextFromNode(data.delta, parsed.textSegments);\n if (data.delta.tool_calls) {\n this.collectToolCalls(data.delta.tool_calls, parsed.toolCalls);\n }\n }\n break;\n }\n }\n\n private handleChatCompletionChunk(chunk: any, parsed: ParsedOpenAIStream): void {\n if (!chunk) return;\n\n if (chunk.model && typeof chunk.model === 'string') {\n parsed.model = chunk.model;\n }\n\n if (chunk.usage) {\n parsed.inputTokens = chunk.usage.prompt_tokens ?? parsed.inputTokens;\n parsed.outputTokens = chunk.usage.completion_tokens ?? parsed.outputTokens;\n }\n\n if (!Array.isArray(chunk.choices)) return;\n\n for (const choice of chunk.choices) {\n if (choice?.delta) {\n this.collectTextFromNode(choice.delta, parsed.textSegments);\n if (choice.delta.tool_calls) {\n this.collectToolCalls(choice.delta.tool_calls, parsed.toolCalls);\n }\n }\n\n if (choice?.message?.content) {\n this.collectTextFromNode(choice.message.content, parsed.textSegments);\n }\n\n if (choice?.finish_reason) {\n parsed.stopReason = this.mapFinishReason(choice.finish_reason);\n }\n }\n }\n\n private collectCompletedResponse(data: any, parsed: ParsedOpenAIStream): void {\n let collectedMessageOutput = false;\n if (data?.response?.model) {\n parsed.model = data.response.model;\n }\n if (data?.response?.usage) {\n parsed.inputTokens = data.response.usage.input_tokens ?? data.response.usage.prompt_tokens ?? parsed.inputTokens;\n parsed.outputTokens =\n data.response.usage.output_tokens ?? data.response.usage.completion_tokens ?? parsed.outputTokens;\n\n if (data.response.usage.input_tokens_details?.cached_tokens) {\n parsed.cachedTokens = data.response.usage.input_tokens_details.cached_tokens;\n }\n if (data.response.usage.output_tokens_details?.reasoning_tokens) {\n parsed.reasoningTokens = data.response.usage.output_tokens_details.reasoning_tokens;\n }\n }\n\n if (data?.response?.reasoning?.effort) {\n parsed.reasoningEffort = data.response.reasoning.effort;\n }\n if (Array.isArray(data?.response?.tool_calls)) {\n this.collectToolCalls(data.response.tool_calls, parsed.toolCalls);\n }\n\n if (Array.isArray(data?.response?.output)) {\n for (const [index, output] of data.response.output.entries()) {\n if (output?.type === 'reasoning') {\n const outputData = { output_index: index, item: output };\n if (\n !this.shouldEmitTerminalContent(\n outputData,\n parsed.streamedReasoningKeys,\n 'reasoning',\n parsed.thinkingSegments.length > 0,\n )\n ) {\n continue;\n }\n if (Array.isArray(output?.summary)) {\n for (const summaryItem of output.summary) {\n if (summaryItem?.type === 'summary_text' && summaryItem?.text) {\n parsed.thinkingSegments.push(summaryItem.text);\n }\n }\n }\n } else if (output?.type === 'message') {\n const outputData = { output_index: index, item: output };\n if (\n !this.shouldEmitTerminalContent(outputData, parsed.streamedTextKeys, 'text', parsed.textSegments.length > 0)\n ) {\n continue;\n }\n if (Array.isArray(output?.content)) {\n for (const contentItem of output.content) {\n if ((contentItem?.type === 'output_text' || contentItem?.type === 'text') && contentItem?.text) {\n parsed.textSegments.push(contentItem.text);\n collectedMessageOutput = true;\n }\n }\n }\n } else if (output?.type === 'function_call') {\n const toolCallData = {\n index: parsed.toolCalls.size,\n id: output.id || `tool_${ulid()}`,\n function: {\n name: output.name,\n arguments: output.arguments,\n },\n };\n this.collectToolCalls([toolCallData], parsed.toolCalls);\n }\n }\n }\n\n if (data?.response?.output_text && !collectedMessageOutput) {\n const outputData = { output_index: 0 };\n if (this.shouldEmitTerminalContent(outputData, parsed.streamedTextKeys, 'text', parsed.textSegments.length > 0)) {\n this.collectTextFromNode(data.response.output_text, parsed.textSegments);\n }\n }\n parsed.stopReason = this.mapResponseStatusToStopReason(data?.response?.status);\n }\n\n private collectTextFromNode(node: any, collector: string[]): void {\n if (node == null) return;\n\n if (typeof node === 'string') {\n if (node.length > 0) collector.push(node);\n return;\n }\n\n if (Array.isArray(node)) {\n for (const item of node) {\n this.collectTextFromNode(item, collector);\n }\n return;\n }\n\n if (typeof node !== 'object') {\n return;\n }\n\n if (typeof node.text === 'string') {\n collector.push(node.text);\n }\n\n if (typeof node.output_text === 'string') {\n collector.push(node.output_text);\n }\n\n if (typeof node.value === 'string') {\n collector.push(node.value);\n }\n\n if (typeof node.delta === 'string') {\n collector.push(node.delta);\n } else if (node.delta) {\n this.collectTextFromNode(node.delta, collector);\n }\n\n if (node.token && typeof node.token.text === 'string') {\n collector.push(node.token.text);\n }\n\n const nestedKeys = ['content', 'output', 'output_text', 'message', 'choices', 'segments'];\n for (const key of nestedKeys) {\n if (node[key] !== undefined) {\n if (key === 'choices' && Array.isArray(node[key])) {\n for (const choice of node[key]) {\n if (choice?.message?.content) {\n this.collectTextFromNode(choice.message.content, collector);\n }\n if (choice?.delta) {\n this.collectTextFromNode(choice.delta, collector);\n }\n }\n } else {\n this.collectTextFromNode(node[key], collector);\n }\n }\n }\n }\n\n private collectToolCalls(\n rawToolCalls: any,\n toolCallMap: Map<number, { id: string; name: string; argumentChunks: string[] }>,\n ): void {\n if (!rawToolCalls) return;\n\n const callsArray = Array.isArray(rawToolCalls) ? rawToolCalls : [rawToolCalls];\n\n for (const call of callsArray) {\n if (!call) continue;\n\n const index = typeof call.index === 'number' ? call.index : toolCallMap.size;\n const existing = toolCallMap.get(index) || {\n id: '',\n name: '',\n argumentChunks: [],\n };\n\n if (typeof call.id === 'string' && !existing.id) {\n existing.id = call.id;\n }\n\n const functionName = call.function?.name ?? call.name;\n if (typeof functionName === 'string' && functionName.length > 0) {\n existing.name = functionName;\n }\n\n const functionArgs = call.function?.arguments ?? call.arguments;\n if (typeof functionArgs === 'string' && functionArgs.length > 0) {\n existing.argumentChunks.push(functionArgs);\n }\n\n toolCallMap.set(index, existing);\n }\n }\n\n private collectResponsesToolCallDelta(\n data: any,\n toolCallMap: Map<number, { id: string; name: string; argumentChunks: string[] }>,\n ): void {\n const outputIndex = typeof data?.output_index === 'number' ? data.output_index : toolCallMap.size;\n const existing = toolCallMap.get(outputIndex) || {\n id: '',\n name: '',\n argumentChunks: [],\n };\n\n const toolId = data?.item_id ?? data?.id;\n if (typeof toolId === 'string' && !existing.id) {\n existing.id = toolId;\n }\n\n const functionName = data?.name ?? data?.item?.name ?? data?.item?.call_id;\n if (typeof functionName === 'string' && functionName.length > 0) {\n existing.name = functionName;\n }\n\n const delta = data?.delta ?? data?.arguments ?? data?.item?.arguments;\n if (typeof delta === 'string' && delta.length > 0) {\n existing.argumentChunks.push(delta);\n }\n\n toolCallMap.set(outputIndex, existing);\n }\n\n private collectResponsesOutputItem(data: any, parsed: ParsedOpenAIStream, dedupeTerminal = false): void {\n const item = data?.item;\n if (item?.type === 'message') {\n if (\n dedupeTerminal &&\n !this.shouldEmitTerminalContent(data, parsed.streamedTextKeys, 'text', parsed.textSegments.length > 0)\n ) {\n return;\n }\n this.collectTextFromNode(item.content, parsed.textSegments);\n return;\n }\n\n if (item?.type === 'reasoning') {\n if (\n dedupeTerminal &&\n !this.shouldEmitTerminalContent(\n data,\n parsed.streamedReasoningKeys,\n 'reasoning',\n parsed.thinkingSegments.length > 0,\n )\n ) {\n return;\n }\n this.collectTextFromNode(item.summary ?? item.content, parsed.thinkingSegments);\n return;\n }\n\n this.collectResponsesToolCallDelta(data, parsed.toolCalls);\n }\n\n private parseToolCallInput(argumentsText: string): Record<string, unknown> {\n if (!argumentsText) {\n return {};\n }\n\n try {\n const parsed = JSON.parse(argumentsText);\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};\n } catch {\n return {};\n }\n }\n\n private createClaudeStreamFromParsed(parsed: ParsedOpenAIStream): string {\n if (parsed.errorMessage) {\n return this.createClaudeErrorStream(parsed.errorMessage);\n }\n\n const thinkingSegments = this.thinkingDisabled\n ? []\n : this.mergeAndChunkSegments(this.dedupeSegments(parsed.thinkingSegments));\n const textSegments = this.mergeAndChunkSegments(this.dedupeSegments(parsed.textSegments));\n\n const seenToolCalls = new Set<string>();\n const toolCalls = Array.from(parsed.toolCalls.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([index, value]) => ({\n index,\n id: value.id,\n name: value.name,\n arguments: this.normalizeToolCallArguments(value.argumentChunks),\n }))\n .filter((call) => {\n if (!call.name) {\n return false;\n }\n\n const key = `${call.id}\\u0000${call.name}\\u0000${call.arguments}`;\n if (seenToolCalls.has(key)) {\n return false;\n }\n\n seenToolCalls.add(key);\n return true;\n });\n\n if (thinkingSegments.length === 0 && textSegments.length === 0 && toolCalls.length === 0) {\n return this.createClaudeErrorStream('Empty streaming response from provider');\n }\n\n const messageId = `msg_${ulid()}`;\n const model = parsed.model || 'gpt-5';\n const events: string[] = [];\n\n events.push('event: message_start');\n events.push(\n `data: ${JSON.stringify({\n type: 'message_start',\n message: {\n id: messageId,\n type: 'message',\n role: 'assistant',\n content: [],\n model,\n stop_reason: null,\n stop_sequence: null,\n usage: { input_tokens: parsed.inputTokens ?? 0, output_tokens: 0 },\n },\n })}`,\n );\n events.push('');\n\n let blockIndex = 0;\n\n if (thinkingSegments.length > 0) {\n events.push('event: content_block_start');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_start',\n index: blockIndex,\n content_block: { type: 'thinking', thinking: '' },\n })}`,\n );\n events.push('');\n\n for (const chunk of thinkingSegments) {\n if (!chunk) continue;\n events.push('event: content_block_delta');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_delta',\n index: blockIndex,\n delta: { type: 'thinking_delta', thinking: chunk },\n })}`,\n );\n events.push('');\n }\n\n events.push('event: content_block_stop');\n events.push(`data: ${JSON.stringify({ type: 'content_block_stop', index: blockIndex })}`);\n events.push('');\n blockIndex += 1;\n }\n\n if (textSegments.length > 0) {\n events.push('event: content_block_start');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_start',\n index: blockIndex,\n content_block: { type: 'text', text: '' },\n })}`,\n );\n events.push('');\n\n for (const chunk of textSegments) {\n if (!chunk) continue;\n events.push('event: content_block_delta');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_delta',\n index: blockIndex,\n delta: { type: 'text_delta', text: chunk },\n })}`,\n );\n events.push('');\n }\n\n events.push('event: content_block_stop');\n events.push(`data: ${JSON.stringify({ type: 'content_block_stop', index: blockIndex })}`);\n events.push('');\n blockIndex += 1;\n }\n\n for (const toolCall of toolCalls) {\n const toolIndex = blockIndex + toolCall.index;\n const toolId = toolCall.id || `tool_${ulid()}`;\n\n events.push('event: content_block_start');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_start',\n index: toolIndex,\n content_block: {\n type: 'tool_use',\n id: toolId,\n name: toolCall.name,\n input: {},\n },\n })}`,\n );\n events.push('');\n\n if (toolCall.arguments) {\n events.push('event: content_block_delta');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_delta',\n index: toolIndex,\n delta: { type: 'input_json_delta', partial_json: toolCall.arguments },\n })}`,\n );\n events.push('');\n }\n\n events.push('event: content_block_stop');\n events.push(`data: ${JSON.stringify({ type: 'content_block_stop', index: toolIndex })}`);\n events.push('');\n }\n\n const stopReason = parsed.stopReason || 'end_turn';\n const outputTokens = parsed.outputTokens ?? 0;\n const usageDetails: any = { output_tokens: outputTokens };\n\n if (parsed.cachedTokens || parsed.reasoningTokens || parsed.reasoningEffort) {\n usageDetails.metadata = {};\n\n if (parsed.cachedTokens) {\n usageDetails.metadata.cached_tokens = parsed.cachedTokens;\n }\n if (parsed.reasoningTokens) {\n usageDetails.metadata.reasoning_tokens = parsed.reasoningTokens;\n }\n if (parsed.reasoningEffort) {\n usageDetails.metadata.reasoning_effort = parsed.reasoningEffort;\n }\n }\n\n events.push('event: message_delta');\n events.push(\n `data: ${JSON.stringify({\n type: 'message_delta',\n delta: { stop_reason: stopReason, stop_sequence: null },\n usage: usageDetails,\n })}`,\n );\n events.push('');\n\n events.push('event: message_stop');\n events.push('data: {\"type\":\"message_stop\"}');\n events.push('');\n\n return events.join('\\n');\n }\n\n private mergeAndChunkSegments(segments: string[], chunkSize = 2000): string[] {\n if (!segments || segments.length === 0) return [];\n const combined = this.collapseRepeatedWholeText(segments.join(''));\n if (!combined) return [];\n\n const result: string[] = [];\n for (let i = 0; i < combined.length; i += chunkSize) {\n result.push(combined.slice(i, i + chunkSize));\n }\n return result;\n }\n\n private dedupeSegments(segments: string[]): string[] {\n if (segments.length < 2) {\n return segments;\n }\n\n const deduped: string[] = [];\n for (const segment of segments) {\n if (!segment) {\n continue;\n }\n if (deduped.at(-1) === segment) {\n continue;\n }\n deduped.push(segment);\n }\n return deduped;\n }\n\n private normalizeToolCallArguments(argumentChunks: string[]): string {\n if (argumentChunks.length === 0) {\n return '';\n }\n\n return this.sanitizeToolCallArgumentsJson(\n this.collapseRepeatedWholeText(this.dedupeSegments(argumentChunks).join('')),\n );\n }\n\n private sanitizeToolCallArgumentsJson(argumentsText: string): string {\n if (!argumentsText) {\n return '';\n }\n\n try {\n const parsed = JSON.parse(argumentsText);\n const sanitized = this.stripEmptyStringValues(parsed);\n return JSON.stringify(sanitized);\n } catch {\n return argumentsText;\n }\n }\n\n private stripEmptyStringValues(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => this.stripEmptyStringValues(item));\n }\n\n if (!value || typeof value !== 'object') {\n return value;\n }\n\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, nestedValue]) => nestedValue !== '')\n .map(([key, nestedValue]) => [key, this.stripEmptyStringValues(nestedValue)]),\n );\n }\n\n private collapseRepeatedWholeText(text: string): string {\n if (!text || text.length < 2) {\n return text;\n }\n\n for (let repeatCount = 4; repeatCount >= 2; repeatCount -= 1) {\n if (text.length % repeatCount !== 0) {\n continue;\n }\n const unit = text.slice(0, text.length / repeatCount);\n if (unit && unit.repeat(repeatCount) === text) {\n return unit;\n }\n }\n\n return text;\n }\n\n private markStreamedContentKey(data: any, collector: Set<string>, kind: 'text' | 'reasoning'): void {\n const key = this.getResponseContentKey(data, kind);\n if (key) {\n collector.add(key);\n }\n }\n\n private shouldEmitTerminalContent(\n data: any,\n streamedKeys: Set<string>,\n kind: 'text' | 'reasoning',\n hasEmittedContent: boolean,\n ): boolean {\n const key = this.getResponseContentKey(data, kind);\n return key ? !streamedKeys.has(key) : !hasEmittedContent;\n }\n\n private getResponseContentKey(data: any, kind: 'text' | 'reasoning'): string | null {\n const itemId = data?.item_id ?? data?.item?.id ?? data?.id;\n const outputIndex = typeof data?.output_index === 'number' ? data.output_index : null;\n const contentIndex = typeof data?.content_index === 'number' ? data.content_index : null;\n\n if (typeof itemId === 'string' && itemId.length > 0) {\n return `${kind}:item:${itemId}:${contentIndex ?? 'na'}`;\n }\n\n if (outputIndex !== null) {\n return `${kind}:output:${outputIndex}:${contentIndex ?? 'na'}`;\n }\n\n return null;\n }\n\n private mapResponseStatusToStopReason(status?: string | null): string {\n if (!status) return 'end_turn';\n const mapping: Record<string, string> = {\n completed: 'end_turn',\n completed_with_error: 'error',\n completed_with_streaming_error: 'error',\n cancelled: 'error',\n errored: 'error',\n };\n return mapping[status] || 'end_turn';\n }\n\n /**\n * Convert non-streaming OpenAI response to Claude format\n */\n private convertNonStreamingResponse(responseBody: string): string {\n try {\n const openAIResponse = JSON.parse(responseBody);\n\n if (openAIResponse?.error) {\n const errorMessage =\n openAIResponse.error?.message ||\n openAIResponse.error?.error ||\n (typeof openAIResponse.error === 'string' ? openAIResponse.error : 'Unexpected API error');\n return this.createClaudeErrorResponse(errorMessage);\n }\n\n const responsesApiPayload =\n openAIResponse?.response && typeof openAIResponse.response === 'object'\n ? openAIResponse.response\n : openAIResponse;\n const isResponsesApiPayload =\n typeof responsesApiPayload?.type === 'string'\n ? responsesApiPayload.type.startsWith('response')\n : Array.isArray(responsesApiPayload?.output) || responsesApiPayload?.output_text !== undefined;\n if (isResponsesApiPayload) {\n const parsed: ParsedOpenAIStream = {\n textSegments: [],\n thinkingSegments: [],\n toolCalls: new Map<number, { id: string; name: string; argumentChunks: string[] }>(),\n streamedReasoningKeys: new Set<string>(),\n streamedTextKeys: new Set<string>(),\n model: 'gpt-5',\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n reasoningEffort: undefined,\n stopReason: undefined,\n errorMessage: undefined,\n };\n this.collectCompletedResponse({ response: responsesApiPayload }, parsed);\n const claudeStream = this.createClaudeStreamFromParsed(parsed);\n return this.ensureValidClaudeStream(claudeStream, 'Empty response from provider');\n }\n\n const choice = openAIResponse.choices?.[0];\n\n if (!choice) {\n return this.createClaudeErrorStream('Empty response from provider');\n }\n const parsed: ParsedOpenAIStream = {\n textSegments: [],\n thinkingSegments: [],\n toolCalls: new Map<number, { id: string; name: string; argumentChunks: string[] }>(),\n streamedReasoningKeys: new Set<string>(),\n streamedTextKeys: new Set<string>(),\n model: openAIResponse.model || 'gpt-4-turbo',\n inputTokens: openAIResponse.usage?.prompt_tokens || 0,\n outputTokens: openAIResponse.usage?.completion_tokens || 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n reasoningEffort: undefined,\n stopReason: this.mapFinishReason(choice.finish_reason),\n errorMessage: undefined,\n };\n this.collectTextFromNode(choice.message?.content, parsed.textSegments);\n const claudeStream = this.createClaudeStreamFromParsed(parsed);\n return this.ensureValidClaudeStream(claudeStream, 'Empty response from provider');\n } catch (error) {\n this.logger?.error('Failed to transform OpenAI response to Claude format', error as Error);\n const fallbackMessage =\n typeof responseBody === 'string' && responseBody.trim() ? responseBody.trim() : 'Unexpected API error';\n return this.createClaudeErrorStream(fallbackMessage);\n }\n }\n\n /**\n * Map OpenAI finish_reason to Claude stop_reason\n */\n private mapFinishReason(finishReason: string | undefined): string | null {\n if (!finishReason) return null;\n\n const mapping: Record<string, string> = {\n stop: 'end_turn',\n length: 'max_tokens',\n function_call: 'tool_use',\n tool_calls: 'tool_use',\n content_filter: 'stop_sequence',\n };\n\n return mapping[finishReason] || 'end_turn';\n }\n\n private createClaudeErrorResponse(message: string): string {\n const messageId = `msg_${ulid()}`;\n const text = message || 'Unexpected API error';\n\n return JSON.stringify({\n id: messageId,\n type: 'message',\n role: 'assistant',\n content: [\n {\n type: 'text',\n text,\n },\n ],\n model: 'gpt-5',\n stop_reason: 'error',\n stop_sequence: null,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n });\n }\n\n private createClaudeErrorStream(message: string): string {\n const messageId = `msg_${ulid()}`;\n const text = message || 'Unexpected API error';\n const events: string[] = [];\n\n events.push('event: message_start');\n events.push(\n `data: ${JSON.stringify({\n type: 'message_start',\n message: {\n id: messageId,\n type: 'message',\n role: 'assistant',\n content: [],\n model: 'gpt-5',\n stop_reason: null,\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n },\n })}`,\n );\n events.push('');\n\n events.push('event: content_block_start');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_start',\n index: 0,\n content_block: { type: 'text', text: '' },\n })}`,\n );\n events.push('');\n\n events.push('event: content_block_delta');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_delta',\n index: 0,\n delta: { type: 'text_delta', text },\n })}`,\n );\n events.push('');\n\n events.push('event: content_block_stop');\n events.push(\n `data: ${JSON.stringify({\n type: 'content_block_stop',\n index: 0,\n })}`,\n );\n events.push('');\n\n events.push('event: message_delta');\n events.push(\n `data: ${JSON.stringify({\n type: 'message_delta',\n delta: { stop_reason: 'error', stop_sequence: null },\n usage: { output_tokens: 0 },\n })}`,\n );\n events.push('');\n\n events.push('event: message_stop');\n events.push('data: {\"type\":\"message_stop\"}');\n events.push('');\n\n return events.join('\\n');\n }\n\n private ensureValidClaudeStream(stream: string, errorMessage: string): string {\n if (!stream || !stream.includes('event: message_start')) {\n return this.createClaudeErrorStream(errorMessage);\n }\n return stream;\n }\n\n private processBufferedEvents(\n buffer: string,\n state: StreamState,\n controller: ReadableStreamDefaultController<Uint8Array>,\n flush = false,\n ): string {\n const normalized = buffer.replace(/\\r\\n/g, '\\n');\n const chunks = normalized.split('\\n\\n');\n const remainder = flush ? '' : (chunks.pop() ?? '');\n\n for (const chunk of chunks) {\n this.processSseChunk(chunk, state, controller);\n }\n\n if (flush && remainder.trim()) {\n this.processSseChunk(remainder, state, controller);\n }\n\n return remainder;\n }\n\n private processSseChunk(\n chunk: string,\n state: StreamState,\n controller: ReadableStreamDefaultController<Uint8Array>,\n ): void {\n const lines = chunk.split('\\n');\n let eventName = '';\n const dataLines: string[] = [];\n\n for (const rawLine of lines) {\n const line = rawLine.replace(/\\r$/, '');\n if (line.startsWith('event:')) {\n eventName = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trim());\n }\n }\n\n const dataContent = dataLines.join('\\n').trim();\n if (!dataContent || dataContent === '[DONE]') {\n return;\n }\n\n try {\n const data = JSON.parse(dataContent);\n const eventType = typeof data?.type === 'string' ? data.type : eventName;\n const isResponsesApi = eventType.startsWith('response.') || eventName.startsWith('response.');\n\n if (data?.error || eventType === 'response.error') {\n const message =\n data?.error?.message ||\n data?.error?.error ||\n data?.message ||\n (typeof data?.error === 'string' ? data.error : 'Unexpected API error');\n this.emitStreamingError(controller, state, message);\n return;\n }\n\n if (isResponsesApi) {\n this.processResponsesStreamingEvent(eventType, data, state, controller);\n return;\n }\n\n this.processChatCompletionStreamingChunk(data, state, controller);\n } catch {\n // Ignore malformed partial events.\n }\n }\n\n private processResponsesStreamingEvent(\n eventType: string,\n data: any,\n state: StreamState,\n controller: ReadableStreamDefaultController<Uint8Array>,\n ): void {\n if (data?.model && typeof data.model === 'string') {\n state.model = data.model;\n }\n\n switch (eventType) {\n case 'response.created':\n if (typeof data?.response?.model === 'string') {\n state.model = data.response.model;\n }\n break;\n case 'response.reasoning.delta':\n case 'response.reasoning_summary_text.delta': {\n const segments: string[] = [];\n this.markStreamedContentKey(data, state.streamedReasoningKeys, 'reasoning');\n this.collectTextFromNode(data?.delta ?? data?.text ?? data?.summary_text, segments);\n for (const segment of segments) {\n this.emitThinkingDelta(controller, state, segment);\n }\n break;\n }\n case 'response.output_text.delta':\n case 'response.delta': {\n const segments: string[] = [];\n this.markStreamedContentKey(data, state.streamedTextKeys, 'text');\n this.collectTextFromNode(data?.delta ?? data?.output_text, segments);\n for (const segment of segments) {\n this.emitTextDelta(controller, state, segment);\n }\n if (data?.delta?.tool_calls) {\n this.collectToolCalls(data.delta.tool_calls, state.toolCalls);\n }\n break;\n }\n case 'response.function_call_arguments.delta':\n case 'response.function_call_arguments.done':\n case 'response.output_item.added':\n case 'response.output_item.done':\n if (data?.item?.type === 'message') {\n if (this.shouldEmitTerminalContent(data, state.streamedTextKeys, 'text', state.emittedText)) {\n const segments: string[] = [];\n this.collectTextFromNode(data.item.content, segments);\n const combinedText = segments.join('');\n if (combinedText && combinedText === state.lastTextChunk) {\n break;\n }\n for (const segment of segments) {\n this.emitTextDelta(controller, state, segment);\n }\n }\n } else if (data?.item?.type === 'reasoning') {\n if (this.shouldEmitTerminalContent(data, state.streamedReasoningKeys, 'reasoning', state.emittedThinking)) {\n const segments: string[] = [];\n this.collectTextFromNode(data.item.summary ?? data.item.content, segments);\n const combinedThinking = segments.join('');\n if (combinedThinking && combinedThinking === state.lastThinkingChunk) {\n break;\n }\n for (const segment of segments) {\n this.emitThinkingDelta(controller, state, segment);\n }\n }\n } else {\n this.collectResponsesToolCallDelta(data, state.toolCalls);\n }\n break;\n case 'response.output_text.done':\n case 'response.content_part.done': {\n if (state.textBlockStarted) {\n break;\n }\n if (this.shouldEmitTerminalContent(data, state.streamedTextKeys, 'text', state.emittedText)) {\n const segments: string[] = [];\n this.collectTextFromNode(data?.delta ?? data?.output_text ?? data?.text ?? data?.part, segments);\n const combinedText = segments.join('');\n if (combinedText && combinedText === state.lastTextChunk) {\n break;\n }\n for (const segment of segments) {\n this.emitTextDelta(controller, state, segment);\n }\n }\n break;\n }\n case 'response.completed':\n case 'response.done': {\n const parsed: ParsedOpenAIStream = {\n textSegments: [],\n thinkingSegments: [],\n toolCalls: new Map<number, { id: string; name: string; argumentChunks: string[] }>(state.toolCalls),\n streamedReasoningKeys: new Set<string>(state.streamedReasoningKeys),\n streamedTextKeys: new Set<string>(state.streamedTextKeys),\n model: state.model,\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n cachedTokens: state.cachedTokens,\n reasoningTokens: state.reasoningTokens,\n reasoningEffort: state.reasoningEffort,\n stopReason: state.stopReason,\n };\n this.collectCompletedResponse(data, parsed);\n state.model = parsed.model;\n state.inputTokens = parsed.inputTokens;\n state.outputTokens = parsed.outputTokens;\n state.cachedTokens = parsed.cachedTokens;\n state.reasoningTokens = parsed.reasoningTokens;\n state.reasoningEffort = parsed.reasoningEffort;\n state.stopReason = parsed.stopReason;\n state.toolCalls = parsed.toolCalls;\n\n if (!state.emittedThinking) {\n for (const segment of parsed.thinkingSegments) {\n this.emitThinkingDelta(controller, state, segment);\n }\n }\n if (!state.emittedText) {\n for (const segment of parsed.textSegments) {\n this.emitTextDelta(controller, state, segment);\n }\n }\n\n this.emitPendingToolCalls(controller, state);\n this.finishStreamingResponse(controller, state);\n break;\n }\n default:\n break;\n }\n }\n\n private processChatCompletionStreamingChunk(\n chunk: any,\n state: StreamState,\n controller: ReadableStreamDefaultController<Uint8Array>,\n ): void {\n if (!chunk) {\n return;\n }\n\n if (typeof chunk.model === 'string') {\n state.model = chunk.model;\n }\n\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens ?? state.inputTokens;\n state.outputTokens = chunk.usage.completion_tokens ?? state.outputTokens;\n }\n\n if (!Array.isArray(chunk.choices)) {\n return;\n }\n\n for (const choice of chunk.choices) {\n const segments: string[] = [];\n this.collectTextFromNode(choice?.delta ?? choice?.message?.content, segments);\n for (const segment of segments) {\n this.emitTextDelta(controller, state, segment);\n }\n\n if (choice?.delta?.tool_calls) {\n this.collectToolCalls(choice.delta.tool_calls, state.toolCalls);\n }\n\n if (choice?.finish_reason) {\n state.stopReason = this.mapFinishReason(choice.finish_reason);\n }\n }\n }\n\n private emitPendingToolCalls(controller: ReadableStreamDefaultController<Uint8Array>, state: StreamState): void {\n const toolCalls = Array.from(state.toolCalls.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([index, value]) => ({\n index,\n id: value.id || `tool_${ulid()}`,\n name: value.name,\n arguments: value.argumentChunks.join(''),\n }))\n .filter((call) => call.name && !state.emittedToolCallIndexes.has(call.index));\n\n for (const toolCall of toolCalls) {\n this.stopOpenContentBlocks(controller, state);\n const index = this.getNextToolBlockIndex(toolCall.index);\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('content_block_start', {\n type: 'content_block_start',\n index,\n content_block: {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.name,\n input: {},\n },\n }) +\n (toolCall.arguments\n ? this.formatSseEvent('content_block_delta', {\n type: 'content_block_delta',\n index,\n delta: { type: 'input_json_delta', partial_json: toolCall.arguments },\n })\n : '') +\n this.formatSseEvent('content_block_stop', {\n type: 'content_block_stop',\n index,\n }),\n ),\n );\n state.emittedToolCallIndexes.add(toolCall.index);\n }\n }\n\n private emitThinkingDelta(\n controller: ReadableStreamDefaultController<Uint8Array>,\n state: StreamState,\n text: string,\n ): void {\n if (this.thinkingDisabled || !text) {\n return;\n }\n\n this.ensureMessageStarted(controller, state);\n if (state.textBlockStarted) {\n this.stopTextBlock(controller, state);\n }\n if (!state.thinkingBlockStarted) {\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('content_block_start', {\n type: 'content_block_start',\n index: 0,\n content_block: { type: 'thinking', thinking: '' },\n }),\n ),\n );\n state.thinkingBlockStarted = true;\n }\n\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('content_block_delta', {\n type: 'content_block_delta',\n index: 0,\n delta: { type: 'thinking_delta', thinking: text },\n }),\n ),\n );\n state.emittedThinking = true;\n state.lastThinkingChunk = text;\n }\n\n private emitTextDelta(\n controller: ReadableStreamDefaultController<Uint8Array>,\n state: StreamState,\n text: string,\n ): void {\n if (!text) {\n return;\n }\n\n this.ensureMessageStarted(controller, state);\n if (!state.textBlockStarted) {\n if (state.thinkingBlockStarted) {\n this.stopThinkingBlock(controller, state);\n }\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('content_block_start', {\n type: 'content_block_start',\n index: this.getTextBlockIndex(),\n content_block: { type: 'text', text: '' },\n }),\n ),\n );\n state.textBlockStarted = true;\n }\n\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('content_block_delta', {\n type: 'content_block_delta',\n index: this.getTextBlockIndex(),\n delta: { type: 'text_delta', text },\n }),\n ),\n );\n state.emittedText = true;\n state.lastTextChunk = text;\n }\n\n private emitStreamingError(\n controller: ReadableStreamDefaultController<Uint8Array>,\n state: StreamState,\n message: string,\n ): void {\n if (!state.messageStarted) {\n controller.enqueue(state.encoder.encode(this.createClaudeErrorStream(message)));\n state.messageStarted = true;\n state.messageStopped = true;\n return;\n }\n\n if (!state.textBlockStarted && !state.thinkingBlockStarted) {\n this.emitTextDelta(controller, state, message);\n }\n state.stopReason = 'error';\n this.finishStreamingResponse(controller, state);\n }\n\n private finishStreamingResponse(controller: ReadableStreamDefaultController<Uint8Array>, state: StreamState): void {\n if (state.messageStopped) {\n return;\n }\n\n this.stopOpenContentBlocks(controller, state);\n\n const usage: Record<string, unknown> = {\n output_tokens: state.outputTokens ?? 0,\n };\n\n if (state.cachedTokens || state.reasoningTokens || state.reasoningEffort) {\n usage.metadata = {} as Record<string, unknown>;\n const metadata = usage.metadata as Record<string, unknown>;\n if (state.cachedTokens) {\n metadata.cached_tokens = state.cachedTokens;\n }\n if (state.reasoningTokens) {\n metadata.reasoning_tokens = state.reasoningTokens;\n }\n if (state.reasoningEffort) {\n metadata.reasoning_effort = state.reasoningEffort;\n }\n }\n\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('message_delta', {\n type: 'message_delta',\n delta: { stop_reason: state.stopReason || 'end_turn', stop_sequence: null },\n usage,\n }) + this.formatSseEvent('message_stop', { type: 'message_stop' }),\n ),\n );\n state.messageStopped = true;\n }\n\n private ensureMessageStarted(controller: ReadableStreamDefaultController<Uint8Array>, state: StreamState): void {\n if (state.messageStarted) {\n return;\n }\n\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('message_start', {\n type: 'message_start',\n message: {\n id: state.messageId,\n type: 'message',\n role: 'assistant',\n content: [],\n model: state.model,\n stop_reason: null,\n stop_sequence: null,\n usage: { input_tokens: state.inputTokens ?? 0, output_tokens: 0 },\n },\n }),\n ),\n );\n state.messageStarted = true;\n }\n\n private stopOpenContentBlocks(controller: ReadableStreamDefaultController<Uint8Array>, state: StreamState): void {\n this.stopTextBlock(controller, state);\n this.stopThinkingBlock(controller, state);\n }\n\n private stopThinkingBlock(controller: ReadableStreamDefaultController<Uint8Array>, state: StreamState): void {\n if (!state.thinkingBlockStarted) {\n return;\n }\n\n controller.enqueue(\n state.encoder.encode(this.formatSseEvent('content_block_stop', { type: 'content_block_stop', index: 0 })),\n );\n state.thinkingBlockStarted = false;\n }\n\n private stopTextBlock(controller: ReadableStreamDefaultController<Uint8Array>, state: StreamState): void {\n if (!state.textBlockStarted) {\n return;\n }\n\n controller.enqueue(\n state.encoder.encode(\n this.formatSseEvent('content_block_stop', { type: 'content_block_stop', index: this.getTextBlockIndex() }),\n ),\n );\n state.textBlockStarted = false;\n }\n\n private getTextBlockIndex(): number {\n return this.thinkingDisabled ? 0 : 1;\n }\n\n private getNextToolBlockIndex(offset: number): number {\n const base = this.thinkingDisabled ? 1 : 2;\n return base + offset;\n }\n}\n","export const GEMINI_API_KEY_ENV_FALLBACK = 'GEMINI_API_KEY';\nexport const GEMINI_CLI_HOME_ENV = 'GEMINI_CLI_HOME';\nexport const GEMINI_DEFAULT_API_VERSION = 'v1beta';\nexport const GEMINI_DEFAULT_BASE_URL = 'https://generativelanguage.googleapis.com';\nexport const GEMINI_DEFAULT_AUTH_MODE = 'auto';\nexport const GEMINI_PERSONAL_OAUTH_AUTH_TYPE = 'oauth-personal';\nexport const GEMINI_CODE_ASSIST_ENDPOINT = 'https://cloudcode-pa.googleapis.com';\nexport const GEMINI_CODE_ASSIST_API_VERSION = 'v1internal';\nexport const GEMINI_DEFAULT_LOCATION = 'global';\nexport const GEMINI_SETTINGS_FILE = 'settings.json';\nexport const GEMINI_OAUTH_FILE = 'oauth_creds.json';\nexport const GEMINI_STREAM_QUERY_PARAM = 'alt=sse';\nexport const GEMINI_USER_ROLE = 'user';\nexport const GEMINI_MODEL_ROLE = 'model';\nexport const GEMINI_MODEL_PREFIX = 'models/';\nexport const GEMINI_SSE_DONE_EVENT = 'data: [DONE]';\n\nexport interface GeminiAuthHeaders {\n headers: Record<string, string>;\n authMode: 'api-key' | 'oauth';\n authSource: 'env' | 'gemini-home';\n authType?: string | null;\n}\n\nexport interface GeminiOAuthCredentials {\n access_token?: string;\n refresh_token?: string;\n token_type?: string;\n scope?: string;\n expiry_date?: number;\n}\n\nexport interface GeminiCliSettings {\n security?: {\n auth?: {\n selectedType?: string;\n };\n };\n}\n\nexport interface GeminiTextPart {\n text: string;\n}\n\nexport interface GeminiFunctionCallPart {\n functionCall: {\n name: string;\n args?: Record<string, unknown>;\n };\n}\n\nexport interface GeminiFunctionResponsePart {\n functionResponse: {\n name: string;\n response?: Record<string, unknown>;\n };\n}\n\nexport type GeminiContentPart = GeminiTextPart | GeminiFunctionCallPart | GeminiFunctionResponsePart;\n\nexport interface GeminiContent {\n role: 'user' | 'model';\n parts: GeminiContentPart[];\n}\n\nexport interface GeminiFunctionDeclaration {\n name: string;\n description?: string;\n parameters?: Record<string, unknown>;\n}\n\nexport interface GeminiGenerateContentRequest {\n contents: GeminiContent[];\n system_instruction?: {\n parts: GeminiTextPart[];\n };\n tools?: Array<{\n function_declarations: GeminiFunctionDeclaration[];\n }>;\n tool_config?: {\n function_calling_config?: {\n mode: 'AUTO' | 'ANY' | 'NONE';\n };\n };\n generationConfig?: {\n temperature?: number;\n maxOutputTokens?: number;\n stopSequences?: string[];\n };\n}\n\nexport interface GeminiCandidate {\n content?: GeminiContent;\n finishReason?: string;\n}\n\nexport interface GeminiGenerateContentResponse {\n candidates?: GeminiCandidate[];\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n };\n modelVersion?: string;\n}\n","import type { ReasoningEffort } from '../../types/index.js';\nimport {\n GEMINI_MODEL_PREFIX,\n GEMINI_MODEL_ROLE,\n GEMINI_USER_ROLE,\n type GeminiContent,\n type GeminiContentPart,\n type GeminiFunctionDeclaration,\n type GeminiGenerateContentRequest,\n} from './types.js';\n\nconst DEFAULT_MAX_OUTPUT_TOKENS = 4096;\nconst MINIMAL_REASONING_MAX_OUTPUT_TOKENS = 2048;\nconst TOOL_MODE_AUTO = 'AUTO';\nconst TOOL_MODE_NONE = 'NONE';\nconst GEMINI_SUPPORTED_SCHEMA_KEYS = new Set([\n 'type',\n 'format',\n 'description',\n 'nullable',\n 'enum',\n 'items',\n 'maxItems',\n 'minItems',\n 'properties',\n 'required',\n 'propertyOrdering',\n 'maxProperties',\n 'minProperties',\n 'minimum',\n 'maximum',\n 'minLength',\n 'maxLength',\n 'pattern',\n 'example',\n 'anyOf',\n 'title',\n]);\n\ninterface ClaudeMessageBlockText {\n type: 'text';\n text: string;\n}\n\ninterface ClaudeMessageBlockToolUse {\n type: 'tool_use';\n id: string;\n name: string;\n input?: Record<string, unknown>;\n}\n\ninterface ClaudeMessageBlockToolResult {\n type: 'tool_result';\n tool_use_id: string;\n content?: string | unknown;\n}\n\ntype ClaudeMessageBlock = ClaudeMessageBlockText | ClaudeMessageBlockToolUse | ClaudeMessageBlockToolResult;\n\ninterface ClaudeMessage {\n role?: string;\n content?: string | ClaudeMessageBlock[];\n}\n\ninterface ClaudeToolDefinition {\n name: string;\n description?: string;\n input_schema?: Record<string, unknown>;\n}\n\ninterface ParsedClaudeRequest {\n model?: string;\n system?: unknown;\n messages: ClaudeMessage[];\n tools?: ClaudeToolDefinition[];\n max_tokens?: number;\n}\n\nexport interface GeminiRequestTransformResult {\n body: GeminiGenerateContentRequest;\n modelPath: string;\n}\n\nexport class ClaudeToGeminiTransformer {\n transform(\n request: ParsedClaudeRequest,\n resolvedModel: string,\n reasoningEffort: ReasoningEffort,\n thinkingDisabled = false,\n ): GeminiRequestTransformResult {\n const contents = this.toGeminiContents(request.messages);\n const systemInstruction = this.toSystemInstruction(request.system);\n const tools = this.toGeminiTools(request.tools);\n\n return {\n modelPath: this.toGeminiModelPath(resolvedModel),\n body: {\n contents,\n system_instruction: systemInstruction,\n tools,\n tool_config: {\n function_calling_config: {\n mode: tools.length > 0 ? TOOL_MODE_AUTO : TOOL_MODE_NONE,\n },\n },\n generationConfig: {\n maxOutputTokens: this.resolveMaxOutputTokens(request.max_tokens, reasoningEffort, thinkingDisabled),\n },\n },\n };\n }\n\n private toGeminiModelPath(model: string): string {\n return model.startsWith(GEMINI_MODEL_PREFIX) ? model : `${GEMINI_MODEL_PREFIX}${model}`;\n }\n\n private toSystemInstruction(system: unknown): { parts: Array<{ text: string }> } | undefined {\n const texts = this.extractTextParts(system);\n if (texts.length === 0) {\n return undefined;\n }\n\n return {\n parts: texts.map((text) => ({ text })),\n };\n }\n\n private toGeminiContents(messages: ClaudeMessage[]): GeminiContent[] {\n const contents: GeminiContent[] = [];\n\n for (const message of messages) {\n const parts = this.toGeminiParts(message.content);\n if (parts.length === 0) {\n continue;\n }\n\n contents.push({\n role: message.role === 'assistant' ? GEMINI_MODEL_ROLE : GEMINI_USER_ROLE,\n parts,\n });\n }\n\n return contents;\n }\n\n private toGeminiParts(content: ClaudeMessage['content']): GeminiContentPart[] {\n if (typeof content === 'string') {\n return content.trim() ? [{ text: content }] : [];\n }\n\n if (!Array.isArray(content)) {\n return [];\n }\n\n const parts: GeminiContentPart[] = [];\n for (const block of content) {\n if (block.type === 'text' && block.text) {\n parts.push({ text: block.text });\n }\n if (block.type === 'tool_use') {\n parts.push({\n functionCall: {\n name: block.name,\n args: block.input,\n },\n });\n }\n if (block.type === 'tool_result') {\n parts.push({\n functionResponse: {\n name: block.tool_use_id,\n response: {\n content: typeof block.content === 'string' ? block.content : JSON.stringify(block.content ?? {}),\n },\n },\n });\n }\n }\n\n return parts;\n }\n\n private toGeminiTools(\n tools: ClaudeToolDefinition[] | undefined,\n ): Array<{ function_declarations: GeminiFunctionDeclaration[] }> {\n if (!tools || tools.length === 0) {\n return [];\n }\n\n return [\n {\n function_declarations: tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: this.toGeminiParameters(tool.input_schema),\n })),\n },\n ];\n }\n\n private toGeminiParameters(schema: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!schema) {\n return undefined;\n }\n\n return this.sanitizeGeminiSchema(schema) as Record<string, unknown> | undefined;\n }\n\n private sanitizeGeminiSchema(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => this.sanitizeGeminiSchema(item));\n }\n\n if (!value || typeof value !== 'object') {\n return value;\n }\n\n const sanitizedEntries = Object.entries(value).flatMap(([key, nestedValue]) => {\n if (!GEMINI_SUPPORTED_SCHEMA_KEYS.has(key)) {\n return [];\n }\n\n if (key === 'properties' && nestedValue && typeof nestedValue === 'object' && !Array.isArray(nestedValue)) {\n const propertyEntries = Object.entries(nestedValue).map(([propertyName, propertySchema]) => [\n propertyName,\n this.sanitizeGeminiSchema(propertySchema),\n ]);\n\n return [[key, Object.fromEntries(propertyEntries)]];\n }\n\n return [[key, this.sanitizeGeminiSchema(nestedValue)]];\n });\n\n return Object.fromEntries(sanitizedEntries);\n }\n\n private extractTextParts(value: unknown): string[] {\n if (typeof value === 'string') {\n return value.trim() ? [value] : [];\n }\n\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value\n .map((item) => {\n if (typeof item === 'string') {\n return item;\n }\n if (item && typeof item === 'object' && 'text' in item && typeof item.text === 'string') {\n return item.text;\n }\n return null;\n })\n .filter((item): item is string => Boolean(item?.trim()));\n }\n\n private resolveMaxOutputTokens(\n maxTokens: number | undefined,\n reasoningEffort: ReasoningEffort,\n thinkingDisabled: boolean,\n ): number {\n if (typeof maxTokens === 'number' && maxTokens > 0) {\n return maxTokens;\n }\n\n if (thinkingDisabled) {\n return MINIMAL_REASONING_MAX_OUTPUT_TOKENS;\n }\n\n return reasoningEffort === 'minimal' ? MINIMAL_REASONING_MAX_OUTPUT_TOKENS : DEFAULT_MAX_OUTPUT_TOKENS;\n }\n}\n","import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { consoleLogger } from '../../services/logger.js';\nimport type { LoggerLike, ProviderRuntimeConfig } from '../../types/index.js';\nimport {\n GEMINI_API_KEY_ENV_FALLBACK,\n GEMINI_CLI_HOME_ENV,\n GEMINI_DEFAULT_AUTH_MODE,\n GEMINI_OAUTH_FILE,\n GEMINI_SETTINGS_FILE,\n type GeminiAuthHeaders,\n type GeminiCliSettings,\n type GeminiOAuthCredentials,\n} from './types.js';\n\nconst GEMINI_CONFIG_DIRECTORY = '.gemini';\nconst AUTHORIZATION_HEADER = 'Authorization';\nconst API_KEY_HEADER = 'x-goog-api-key';\nconst BEARER_PREFIX = 'Bearer ';\nconst GEMINI_AUTH_CONFIG_ERROR = 'GEMINI_AUTH_CONFIG_ERROR';\nconst OAUTH_REFRESH_ENDPOINT = 'https://oauth2.googleapis.com/token';\nconst OAUTH_REFRESH_GRANT_TYPE = 'refresh_token';\nconst OAUTH_CLIENT_ID = '681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com';\nconst OAUTH_CLIENT_SECRET = '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';\nconst OAUTH_EXPIRY_SKEW_MS = 60_000;\n\nexport class GeminiAuthError extends Error {\n constructor(\n message: string,\n readonly code: string,\n ) {\n super(message);\n this.name = 'GeminiAuthError';\n }\n}\n\nexport class GeminiAuth {\n constructor(\n private readonly logger: LoggerLike = consoleLogger,\n private readonly env: NodeJS.ProcessEnv = process.env,\n ) {}\n\n async resolveHeaders(provider: ProviderRuntimeConfig): Promise<GeminiAuthHeaders> {\n const authMode = provider.authMode ?? GEMINI_DEFAULT_AUTH_MODE;\n\n if (authMode === 'api-key') {\n return this.resolveApiKeyHeaders(provider);\n }\n\n if (authMode === 'oauth') {\n return this.resolveOAuthHeaders();\n }\n\n return (await this.tryResolveApiKeyHeaders(provider)) ?? this.resolveOAuthHeaders();\n }\n\n getGeminiDirectory(): string {\n const homeDirectory = this.env[GEMINI_CLI_HOME_ENV] || os.homedir();\n return path.join(homeDirectory, GEMINI_CONFIG_DIRECTORY);\n }\n\n getSettingsPath(): string {\n return path.join(this.getGeminiDirectory(), GEMINI_SETTINGS_FILE);\n }\n\n getOAuthPath(): string {\n return path.join(this.getGeminiDirectory(), GEMINI_OAUTH_FILE);\n }\n\n private async tryResolveApiKeyHeaders(provider: ProviderRuntimeConfig): Promise<GeminiAuthHeaders | null> {\n try {\n return await this.resolveApiKeyHeaders(provider);\n } catch {\n return null;\n }\n }\n\n private async resolveApiKeyHeaders(provider: ProviderRuntimeConfig): Promise<GeminiAuthHeaders> {\n const apiKeyEnvVar = provider.apiKeyEnvVar ?? provider.authTokenEnvVar ?? GEMINI_API_KEY_ENV_FALLBACK;\n const apiKey = this.env[apiKeyEnvVar]?.trim();\n if (!apiKey) {\n throw new GeminiAuthError(`Missing Gemini API key. Set ${apiKeyEnvVar}.`, GEMINI_AUTH_CONFIG_ERROR);\n }\n\n return {\n headers: {\n [API_KEY_HEADER]: apiKey,\n },\n authMode: 'api-key',\n authSource: 'env',\n };\n }\n\n private async resolveOAuthHeaders(): Promise<GeminiAuthHeaders> {\n const settings = await this.readSettings();\n const credentials = await this.readOAuthCredentials();\n const resolvedCredentials = await this.refreshOAuthCredentialsIfNeeded(credentials);\n const selectedType = settings?.security?.auth?.selectedType ?? null;\n const resolvedAccessToken = resolvedCredentials.access_token?.trim();\n if (!resolvedAccessToken) {\n throw new GeminiAuthError(\n `Missing Gemini OAuth credentials. Expected ${this.getOAuthPath()} or ${GEMINI_API_KEY_ENV_FALLBACK}.`,\n GEMINI_AUTH_CONFIG_ERROR,\n );\n }\n\n return {\n headers: {\n [AUTHORIZATION_HEADER]: `${BEARER_PREFIX}${resolvedAccessToken}`,\n },\n authMode: 'oauth',\n authSource: 'gemini-home',\n authType: selectedType,\n };\n }\n\n private async readOAuthCredentials(): Promise<GeminiOAuthCredentials> {\n try {\n const raw = await fs.readFile(this.getOAuthPath(), 'utf8');\n return JSON.parse(raw) as GeminiOAuthCredentials;\n } catch (error) {\n this.logger.warn('[GeminiAuth] Failed to read oauth credentials', {\n oauthPath: this.getOAuthPath(),\n cause: error,\n });\n throw new GeminiAuthError(\n `Unable to read Gemini OAuth credentials from ${this.getOAuthPath()}.`,\n GEMINI_AUTH_CONFIG_ERROR,\n );\n }\n }\n\n private async readSettings(): Promise<GeminiCliSettings | null> {\n try {\n const raw = await fs.readFile(this.getSettingsPath(), 'utf8');\n return JSON.parse(raw) as GeminiCliSettings;\n } catch (error) {\n if ((error as NodeJS.ErrnoException | undefined)?.code === 'ENOENT') {\n return null;\n }\n\n this.logger.warn('[GeminiAuth] Failed to read settings', {\n settingsPath: this.getSettingsPath(),\n cause: error,\n });\n return null;\n }\n }\n\n private async refreshOAuthCredentialsIfNeeded(credentials: GeminiOAuthCredentials): Promise<GeminiOAuthCredentials> {\n if (!this.shouldRefreshCredentials(credentials)) {\n return credentials;\n }\n\n const refreshToken = credentials.refresh_token?.trim();\n if (!refreshToken) {\n return credentials;\n }\n\n const body = new URLSearchParams({\n client_id: OAUTH_CLIENT_ID,\n client_secret: OAUTH_CLIENT_SECRET,\n grant_type: OAUTH_REFRESH_GRANT_TYPE,\n refresh_token: refreshToken,\n });\n\n const response = await fetch(OAUTH_REFRESH_ENDPOINT, {\n method: 'POST',\n headers: {\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body,\n });\n\n if (!response.ok) {\n this.logger.warn('[GeminiAuth] Failed to refresh oauth credentials', {\n status: response.status,\n oauthPath: this.getOAuthPath(),\n });\n return credentials;\n }\n\n const payload = (await response.json()) as {\n access_token?: string;\n expires_in?: number;\n token_type?: string;\n scope?: string;\n };\n\n const nextCredentials: GeminiOAuthCredentials = {\n ...credentials,\n access_token: payload.access_token ?? credentials.access_token,\n token_type: payload.token_type ?? credentials.token_type,\n scope: payload.scope ?? credentials.scope,\n expiry_date:\n typeof payload.expires_in === 'number' ? Date.now() + payload.expires_in * 1000 : credentials.expiry_date,\n };\n\n await fs.writeFile(this.getOAuthPath(), `${JSON.stringify(nextCredentials, null, 2)}\\n`, 'utf8');\n return nextCredentials;\n }\n\n private shouldRefreshCredentials(credentials: GeminiOAuthCredentials): boolean {\n const accessToken = credentials.access_token?.trim();\n const expiryDate = credentials.expiry_date;\n\n if (!accessToken) {\n return true;\n }\n\n if (typeof expiryDate !== 'number') {\n return false;\n }\n\n return expiryDate <= Date.now() + OAUTH_EXPIRY_SKEW_MS;\n }\n}\n","import { ulid } from 'ulidx';\nimport type { GeminiGenerateContentResponse } from './types.js';\n\nconst SSE_EVENT_PREFIX = 'event: ';\nconst SSE_DATA_PREFIX = 'data: ';\nconst MESSAGE_START_EVENT = 'message_start';\nconst CONTENT_BLOCK_START_EVENT = 'content_block_start';\nconst CONTENT_BLOCK_DELTA_EVENT = 'content_block_delta';\nconst CONTENT_BLOCK_STOP_EVENT = 'content_block_stop';\nconst MESSAGE_DELTA_EVENT = 'message_delta';\nconst MESSAGE_STOP_EVENT = 'message_stop';\nconst CONTENT_BLOCK_TYPE = 'text';\nconst TEXT_DELTA_TYPE = 'text_delta';\nconst STOP_REASON_END_TURN = 'end_turn';\nconst STOP_REASON_TOOL_USE = 'tool_use';\nconst DONE_SENTINEL = '[DONE]';\n\nexport class GeminiToClaudeTransformer {\n transformBuffered(responseBody: string, model: string): string {\n const parsed = JSON.parse(responseBody) as GeminiGenerateContentResponse;\n return this.toClaudeStream([parsed], model);\n }\n\n transformStreaming(responseBody: string, model: string): string {\n const payloads: GeminiGenerateContentResponse[] = [];\n\n for (const chunk of responseBody.split('\\n\\n')) {\n const dataLine = chunk\n .split('\\n')\n .find((line) => line.startsWith(SSE_DATA_PREFIX))\n ?.slice(SSE_DATA_PREFIX.length)\n .trim();\n if (!dataLine || dataLine === DONE_SENTINEL) {\n continue;\n }\n payloads.push(JSON.parse(dataLine) as GeminiGenerateContentResponse);\n }\n\n return this.toClaudeStream(payloads, model);\n }\n\n private toClaudeStream(payloads: GeminiGenerateContentResponse[], model: string): string {\n const text = payloads\n .flatMap((payload) => payload.candidates ?? [])\n .flatMap((candidate) => candidate.content?.parts ?? [])\n .map((part) => ('text' in part && typeof part.text === 'string' ? part.text : ''))\n .join('');\n\n const finishReason = payloads\n .map((payload) => payload.candidates?.[0]?.finishReason)\n .find((value) => typeof value === 'string');\n\n const usage = payloads.find((payload) => payload.usageMetadata)?.usageMetadata;\n const messageId = `msg_${ulid()}`;\n const events: string[] = [];\n\n events.push(`${SSE_EVENT_PREFIX}${MESSAGE_START_EVENT}`);\n events.push(\n `${SSE_DATA_PREFIX}${JSON.stringify({\n type: MESSAGE_START_EVENT,\n message: {\n id: messageId,\n type: 'message',\n role: 'assistant',\n content: [],\n model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens: usage?.promptTokenCount ?? 0,\n output_tokens: 0,\n },\n },\n })}`,\n );\n events.push('');\n\n events.push(`${SSE_EVENT_PREFIX}${CONTENT_BLOCK_START_EVENT}`);\n events.push(\n `${SSE_DATA_PREFIX}${JSON.stringify({\n type: CONTENT_BLOCK_START_EVENT,\n index: 0,\n content_block: { type: CONTENT_BLOCK_TYPE, text: '' },\n })}`,\n );\n events.push('');\n\n if (text) {\n events.push(`${SSE_EVENT_PREFIX}${CONTENT_BLOCK_DELTA_EVENT}`);\n events.push(\n `${SSE_DATA_PREFIX}${JSON.stringify({\n type: CONTENT_BLOCK_DELTA_EVENT,\n index: 0,\n delta: { type: TEXT_DELTA_TYPE, text },\n })}`,\n );\n events.push('');\n }\n\n events.push(`${SSE_EVENT_PREFIX}${CONTENT_BLOCK_STOP_EVENT}`);\n events.push(`${SSE_DATA_PREFIX}${JSON.stringify({ type: CONTENT_BLOCK_STOP_EVENT, index: 0 })}`);\n events.push('');\n\n events.push(`${SSE_EVENT_PREFIX}${MESSAGE_DELTA_EVENT}`);\n events.push(\n `${SSE_DATA_PREFIX}${JSON.stringify({\n type: MESSAGE_DELTA_EVENT,\n delta: { stop_reason: this.mapStopReason(finishReason), stop_sequence: null },\n usage: { output_tokens: usage?.candidatesTokenCount ?? 0 },\n })}`,\n );\n events.push('');\n\n events.push(`${SSE_EVENT_PREFIX}${MESSAGE_STOP_EVENT}`);\n events.push(`${SSE_DATA_PREFIX}${JSON.stringify({ type: MESSAGE_STOP_EVENT })}`);\n events.push('');\n\n return events.join('\\n');\n }\n\n private mapStopReason(finishReason: string | undefined): string {\n if (!finishReason) {\n return STOP_REASON_END_TURN;\n }\n\n return finishReason === 'STOP' ? STOP_REASON_END_TURN : STOP_REASON_TOOL_USE;\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport Database from 'better-sqlite3';\nimport { ulid } from 'ulidx';\nimport { z } from 'zod';\nimport { DEFAULT_HISTORY_DB_PATH, DEFAULT_HISTORY_RETENTION_LIMIT } from '../constants/defaults.js';\nimport type {\n ConversationHistoryEntry,\n ConversationHistoryPage,\n ConversationHistoryStats,\n LoggerLike,\n ModelSlot,\n} from '../types/index.js';\nimport { consoleLogger } from './logger.js';\n\ninterface HistoryRow {\n sequence: number;\n id: string;\n scope: string;\n request_id: string;\n direction: 'request' | 'response' | 'error';\n role: string | null;\n message_type: string;\n model: string | null;\n slot: ModelSlot;\n payload_json: string;\n created_at: string;\n}\n\ntype NewHistoryEntry = Omit<ConversationHistoryEntry, 'id' | 'createdAt'> & { id?: string; createdAt?: string };\n\nconst DEFAULT_HISTORY_PAGE_SIZE = 50;\nconst MIN_HISTORY_PAGE_SIZE = 1;\nconst MAX_HISTORY_PAGE_SIZE = 200;\nconst HISTORY_TABLE = 'conversation_history';\nconst HISTORY_SCOPE_SEQUENCE_INDEX = 'conversation_history_scope_sequence_idx';\nconst HISTORY_SCOPE_REQUEST_INDEX = 'conversation_history_scope_request_idx';\nconst HISTORY_ERROR_CODES = {\n appendFailed: 'HISTORY_APPEND_FAILED',\n listFailed: 'HISTORY_LIST_FAILED',\n clearFailed: 'HISTORY_CLEAR_FAILED',\n statsFailed: 'HISTORY_STATS_FAILED',\n initFailed: 'HISTORY_INIT_FAILED',\n} as const;\nconst historyCursorSchema = z\n .string()\n .transform((value) => Number(value))\n .refine((value) => Number.isInteger(value) && value > 0, 'Cursor must be a positive integer');\n\n/**\n * Error raised for conversation history persistence failures.\n */\nexport class ConversationHistoryServiceError extends Error {\n constructor(\n message: string,\n readonly code: string,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = 'ConversationHistoryServiceError';\n }\n}\n\n/**\n * Persists scoped conversation history using SQLite and enforces bounded retention.\n *\n * Environment variables:\n * - `MODEL_PROXY_MCP_DB_PATH`\n */\nexport class ConversationHistoryService {\n private sqlite: Database.Database | null = null;\n\n /**\n * Creates a SQLite-backed history store.\n *\n * `dbPath` defaults to `MODEL_PROXY_MCP_DB_PATH` or `~/.model-proxy/history.sqlite`.\n * `retentionLimit` is enforced per scope after each insert batch.\n * `logger` receives structured operational failures.\n */\n constructor(\n private readonly dbPath = process.env.MODEL_PROXY_MCP_DB_PATH || DEFAULT_HISTORY_DB_PATH,\n private readonly retentionLimit = DEFAULT_HISTORY_RETENTION_LIMIT,\n private readonly logger: LoggerLike = consoleLogger,\n ) {}\n\n /**\n * Eagerly initializes the SQLite database and schema.\n */\n async ensureInitialized(): Promise<void> {\n await this.getDb();\n }\n\n /**\n * Inserts normalized history entries and prunes overflow per scope.\n */\n async appendEntries(entries: NewHistoryEntry[]): Promise<void> {\n if (entries.length === 0) {\n return;\n }\n\n try {\n const db = await this.getDb();\n const insert = db.prepare(`\n INSERT INTO conversation_history (\n id, scope, request_id, direction, role, message_type, model, slot, payload_json, created_at\n ) VALUES (\n @id, @scope, @request_id, @direction, @role, @message_type, @model, @slot, @payload_json, @created_at\n )\n `);\n const transaction = db.transaction((scopeEntries: NewHistoryEntry[]) => {\n for (const entry of scopeEntries) {\n insert.run({\n id: entry.id ?? ulid(),\n scope: entry.scope,\n request_id: entry.requestId,\n direction: entry.direction,\n role: entry.role,\n message_type: entry.messageType,\n model: entry.model,\n slot: entry.slot,\n payload_json: entry.payloadJson,\n created_at: entry.createdAt ?? new Date().toISOString(),\n });\n }\n });\n\n const entriesByScope = new Map<string, NewHistoryEntry[]>();\n for (const entry of entries) {\n const bucket = entriesByScope.get(entry.scope) ?? [];\n bucket.push(entry);\n entriesByScope.set(entry.scope, bucket);\n }\n\n for (const scopeEntries of entriesByScope.values()) {\n transaction(scopeEntries);\n }\n\n for (const scope of entriesByScope.keys()) {\n await this.pruneScope(scope);\n }\n } catch (error) {\n this.logger.error('[model-proxy-mcp] Failed to append history', {\n code: HISTORY_ERROR_CODES.appendFailed,\n dbPath: this.dbPath,\n cause: error,\n });\n throw new ConversationHistoryServiceError(\n 'Failed to append conversation history',\n HISTORY_ERROR_CODES.appendFailed,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Lists conversation history for a scope ordered from newest to oldest.\n */\n async listHistory(\n scope: string,\n limit = DEFAULT_HISTORY_PAGE_SIZE,\n cursor?: string,\n ): Promise<ConversationHistoryPage> {\n try {\n const db = await this.getDb();\n const parsedCursor = cursor ? historyCursorSchema.parse(cursor) : undefined;\n const boundedLimit = Math.max(MIN_HISTORY_PAGE_SIZE, Math.min(limit, MAX_HISTORY_PAGE_SIZE));\n\n const rows = parsedCursor\n ? (db\n .prepare(\n `\n SELECT sequence, id, scope, request_id, direction, role, message_type, model, slot, payload_json, created_at\n FROM ${HISTORY_TABLE}\n WHERE scope = ? AND sequence < ?\n ORDER BY sequence DESC\n LIMIT ?\n `,\n )\n .all(scope, parsedCursor, boundedLimit + 1) as HistoryRow[])\n : (db\n .prepare(\n `\n SELECT sequence, id, scope, request_id, direction, role, message_type, model, slot, payload_json, created_at\n FROM ${HISTORY_TABLE}\n WHERE scope = ?\n ORDER BY sequence DESC\n LIMIT ?\n `,\n )\n .all(scope, boundedLimit + 1) as HistoryRow[]);\n\n const total = Number(\n (\n db.prepare(`SELECT COUNT(*) as count FROM ${HISTORY_TABLE} WHERE scope = ?`).get(scope) as {\n count: number;\n }\n ).count,\n );\n const nextRow = rows.length > boundedLimit ? rows.pop() : undefined;\n\n return {\n items: rows.map((row) => this.toEntry(row)),\n nextCursor: nextRow ? String(nextRow.sequence) : null,\n total,\n };\n } catch (error) {\n this.logger.error('[model-proxy-mcp] Failed to list history', {\n code: HISTORY_ERROR_CODES.listFailed,\n scope,\n cause: error,\n });\n throw new ConversationHistoryServiceError('Failed to list conversation history', HISTORY_ERROR_CODES.listFailed, {\n cause: error,\n });\n }\n }\n\n /**\n * Clears all history rows for a single scope and returns the deleted count.\n */\n async clearScope(scope: string): Promise<number> {\n try {\n const db = await this.getDb();\n const result = db.prepare(`DELETE FROM ${HISTORY_TABLE} WHERE scope = ?`).run(scope);\n return result.changes;\n } catch (error) {\n this.logger.error('[model-proxy-mcp] Failed to clear history', {\n code: HISTORY_ERROR_CODES.clearFailed,\n scope,\n cause: error,\n });\n throw new ConversationHistoryServiceError(\n 'Failed to clear conversation history',\n HISTORY_ERROR_CODES.clearFailed,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Returns retention stats for a scope.\n */\n async getStats(scope: string): Promise<ConversationHistoryStats> {\n try {\n const db = await this.getDb();\n const row = db\n .prepare(\n `\n SELECT COUNT(*) as count, MIN(created_at) as oldest, MAX(created_at) as newest\n FROM ${HISTORY_TABLE}\n WHERE scope = ?\n `,\n )\n .get(scope) as { count: number; oldest: string | null; newest: string | null };\n\n return {\n scope,\n retentionLimit: this.retentionLimit,\n totalMessages: Number(row.count),\n oldestCreatedAt: row.oldest,\n newestCreatedAt: row.newest,\n };\n } catch (error) {\n this.logger.error('[model-proxy-mcp] Failed to read history stats', {\n code: HISTORY_ERROR_CODES.statsFailed,\n scope,\n cause: error,\n });\n throw new ConversationHistoryServiceError('Failed to read history stats', HISTORY_ERROR_CODES.statsFailed, {\n cause: error,\n });\n }\n }\n\n /**\n * Lists known scopes discovered from stored conversation history.\n */\n async listScopes(): Promise<string[]> {\n try {\n const db = await this.getDb();\n return (\n db.prepare(`SELECT DISTINCT scope FROM ${HISTORY_TABLE} ORDER BY scope ASC`).all() as Array<{ scope: string }>\n ).map((row) => row.scope);\n } catch (error) {\n this.logger.error('[model-proxy-mcp] Failed to list history scopes', {\n code: HISTORY_ERROR_CODES.listFailed,\n cause: error,\n });\n return [];\n }\n }\n\n /**\n * Removes the oldest rows for a scope when it exceeds retention.\n */\n private async pruneScope(scope: string): Promise<void> {\n const db = await this.getDb();\n const row = db.prepare(`SELECT COUNT(*) as count FROM ${HISTORY_TABLE} WHERE scope = ?`).get(scope) as {\n count: number;\n };\n const overflow = Number(row.count) - this.retentionLimit;\n if (overflow <= 0) {\n return;\n }\n\n db.prepare(\n `\n DELETE FROM ${HISTORY_TABLE}\n WHERE sequence IN (\n SELECT sequence\n FROM ${HISTORY_TABLE}\n WHERE scope = ?\n ORDER BY sequence ASC\n LIMIT ?\n )\n `,\n ).run(scope, overflow);\n }\n\n /**\n * Lazily initializes the SQLite connection and schema.\n */\n private async getDb(): Promise<Database.Database> {\n if (this.sqlite) {\n return this.sqlite;\n }\n\n try {\n await fs.mkdir(path.dirname(this.dbPath), { recursive: true });\n this.sqlite = new Database(this.dbPath);\n this.sqlite.pragma('journal_mode = WAL');\n this.sqlite.exec(`\n CREATE TABLE IF NOT EXISTS ${HISTORY_TABLE} (\n sequence INTEGER PRIMARY KEY AUTOINCREMENT,\n id TEXT NOT NULL UNIQUE,\n scope TEXT NOT NULL,\n request_id TEXT NOT NULL,\n direction TEXT NOT NULL,\n role TEXT,\n message_type TEXT NOT NULL,\n model TEXT,\n slot TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n created_at TEXT NOT NULL\n )\n `);\n this.sqlite.exec(\n `CREATE INDEX IF NOT EXISTS ${HISTORY_SCOPE_SEQUENCE_INDEX} ON ${HISTORY_TABLE} (scope, sequence DESC)`,\n );\n this.sqlite.exec(\n `CREATE INDEX IF NOT EXISTS ${HISTORY_SCOPE_REQUEST_INDEX} ON ${HISTORY_TABLE} (scope, request_id)`,\n );\n return this.sqlite;\n } catch (error) {\n this.logger.error('[model-proxy-mcp] Failed to initialize history database', {\n code: HISTORY_ERROR_CODES.initFailed,\n dbPath: this.dbPath,\n cause: error,\n });\n throw new ConversationHistoryServiceError(\n 'Failed to initialize history database',\n HISTORY_ERROR_CODES.initFailed,\n {\n cause: error,\n },\n );\n }\n }\n\n /**\n * Maps a SQLite row into the public history DTO.\n */\n private toEntry(row: HistoryRow): ConversationHistoryEntry {\n return {\n id: row.id,\n scope: row.scope,\n requestId: row.request_id,\n direction: row.direction,\n role: row.role,\n messageType: row.message_type,\n model: row.model,\n slot: row.slot,\n payloadJson: row.payload_json,\n createdAt: row.created_at,\n };\n }\n}\n","import { createHash } from 'node:crypto';\nimport { ulid } from 'ulidx';\nimport { ZodError, z } from 'zod';\nimport { ClaudeToOpenAITransformer } from '../adapters/codex/ClaudeToOpenAITransformer.js';\nimport { CodexAuth } from '../adapters/codex/CodexAuth.js';\nimport { OpenAIToClaudeTransformer } from '../adapters/codex/OpenAIToClaudeTransformer.js';\nimport type { RouterConfig } from '../adapters/codex/types.js';\nimport { ClaudeToGeminiTransformer } from '../adapters/gemini/ClaudeToGeminiTransformer.js';\nimport { GeminiAuth, GeminiAuthError } from '../adapters/gemini/GeminiAuth.js';\nimport { GeminiToClaudeTransformer } from '../adapters/gemini/GeminiToClaudeTransformer.js';\nimport {\n GEMINI_CODE_ASSIST_API_VERSION,\n GEMINI_CODE_ASSIST_ENDPOINT,\n GEMINI_DEFAULT_API_VERSION,\n GEMINI_PERSONAL_OAUTH_AUTH_TYPE,\n type GeminiAuthHeaders,\n type GeminiGenerateContentRequest,\n type GeminiGenerateContentResponse,\n} from '../adapters/gemini/types.js';\nimport { DEFAULT_AUTH_FILE_PATH, DEFAULT_SERVICE_NAME } from '../constants/defaults.js';\nimport type {\n AdminConfig,\n AdminConfigUpdate,\n ConversationHistoryEntry,\n ConversationHistoryPage,\n ConversationHistoryStats,\n GatewayStatus,\n LoggerLike,\n ModelSlot,\n ProviderRuntimeConfig,\n ProxyProfile,\n ResolvedSlotConfig,\n} from '../types/index.js';\nimport { ConversationHistoryService } from './ConversationHistoryService.js';\nimport { ProfileStore } from './ProfileStore.js';\nimport { consoleLogger } from './logger.js';\n\ninterface ForwardedResponse {\n status: number;\n body: string;\n headers: Record<string, string>;\n}\n\ninterface AttemptHistoryPayload {\n upstreamText: string;\n claudeBody: string;\n}\n\ninterface CodexBufferedResult {\n response: ForwardedResponse;\n history: AttemptHistoryPayload;\n}\n\ninterface CodexForwardAuth {\n accessToken: string | null;\n accountId: string | null;\n}\n\nconst MODEL_SLOT_BY_NAME: Record<string, ModelSlot> = {\n 'ccproxy-default': 'default',\n 'ccproxy-sonnet': 'sonnet',\n 'ccproxy-opus': 'opus',\n 'ccproxy-haiku': 'haiku',\n 'ccproxy-subagent': 'subagent',\n};\n\nconst DEFAULT_SCOPE = 'default';\nconst DEFAULT_SLOT: ModelSlot = 'default';\nconst DEFAULT_HISTORY_PAGE_SIZE = 50;\nconst MODEL_SLOTS: ModelSlot[] = ['default', 'sonnet', 'opus', 'haiku', 'subagent'];\nconst CLAUDE_MESSAGES_ENDPOINT = 'https://api.anthropic.com/v1/messages';\nconst DEFAULT_ANTHROPIC_VERSION = '2023-06-01';\nconst ANTHROPIC_COMPATIBLE_PROVIDER = 'anthropic-compatible';\nconst CHATGPT_CODEX_PROVIDER = 'chatgpt-codex';\nconst GEMINI_DIRECT_PROVIDER = 'gemini-direct';\nconst DEFAULT_UPSTREAM_AUTH_ENV = 'ANTHROPIC_AUTH_TOKEN';\nconst FALLBACK_UPSTREAM_AUTH_ENV = 'MODEL_PROXY_MCP_UPSTREAM_AUTH_TOKEN';\nconst FALLBACK_UPSTREAM_TIMEOUT_ENV = 'MODEL_PROXY_MCP_UPSTREAM_TIMEOUT_MS';\nconst CONFIGURED_UPSTREAM_AUTH_ENV_NAME = 'MODEL_PROXY_MCP_UPSTREAM_AUTH_ENV';\nconst DEFAULT_API_TIMEOUT_ENV = 'API_TIMEOUT_MS';\nconst ERROR_RESPONSE_CONTENT_TYPE = 'application/json; charset=utf-8';\nconst JSON_CONTENT_TYPE = 'application/json';\nconst SSE_CONTENT_TYPE = 'text/event-stream; charset=utf-8';\nconst RESPONSE_CONTENT_TYPE_HEADER = 'content-type';\nconst RESPONSE_CACHE_CONTROL_HEADER = 'cache-control';\nconst RESPONSE_CONNECTION_HEADER = 'connection';\nconst AUTHORIZATION_HEADER = 'authorization';\nconst X_API_KEY_HEADER = 'x-api-key';\nconst ACCEPT_HEADER = 'accept';\nconst ANTHROPIC_VERSION_HEADER = 'anthropic-version';\nconst ANTHROPIC_BETA_HEADER = 'anthropic-beta';\nconst HEADER_NO_CACHE = 'no-cache';\nconst HEADER_KEEP_ALIVE = 'keep-alive';\nconst API_ERROR_TYPE = 'api_error';\nconst RAW_REQUEST_MESSAGE_TYPE = 'raw-request';\nconst RESPONSE_STREAM_MESSAGE_TYPE = 'response-stream';\nconst ERROR_MESSAGE_TYPE = 'error';\nconst REQUEST_DIRECTION = 'request';\nconst RESPONSE_DIRECTION = 'response';\nconst ERROR_DIRECTION = 'error';\nconst SYSTEM_ROLE = 'system';\nconst ASSISTANT_ROLE = 'assistant';\nconst MESSAGE_MESSAGE_TYPE = 'message';\nconst RESPONSE_ITEM_MESSAGE_TYPE = 'response-item';\nconst MODEL_NOT_FOUND = 'MODEL_NOT_FOUND';\nconst REQUEST_FORWARD_FAILED = 'REQUEST_FORWARD_FAILED';\nconst REQUEST_VALIDATION_FAILED = 'REQUEST_VALIDATION_FAILED';\nconst REQUEST_PAYLOAD_PREVIEW_LIMIT = 240;\nconst HTTP_STATUS_OK = 200;\nconst GEMINI_GENERATE_CONTENT_METHOD = 'generateContent';\nconst CODE_ASSIST_LOAD_METHOD = 'loadCodeAssist';\nconst CODE_ASSIST_IDE_TYPE = 'IDE_UNSPECIFIED';\nconst CODE_ASSIST_PLATFORM = 'PLATFORM_UNSPECIFIED';\nconst CODE_ASSIST_PLUGIN_TYPE = 'GEMINI';\nconst CLAUDE_REQUEST_SCHEMA = z.object({\n model: z.string().optional(),\n system: z.unknown().optional(),\n messages: z.array(z.unknown()).default([]),\n tools: z.array(z.unknown()).optional(),\n max_tokens: z.number().int().positive().optional(),\n stream: z.boolean().optional(),\n});\n\n/**\n * Base error type for gateway operations with HTTP status and domain code metadata.\n */\nclass GatewayServiceError extends Error {\n constructor(\n message: string,\n readonly code: string,\n readonly status: number,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/**\n * Raised when an inbound Claude request payload is invalid.\n */\nclass GatewayValidationError extends GatewayServiceError {}\n/**\n * Raised when the active proxy configuration cannot satisfy a request.\n */\nclass GatewayConfigError extends GatewayServiceError {}\n/**\n * Raised when upstream authentication is missing or invalid.\n */\nclass GatewayAuthError extends GatewayServiceError {}\n/**\n * Raised when an upstream request fails in a way that might be recoverable by trying fallbacks.\n */\nclass GatewayUpstreamError extends GatewayServiceError {\n constructor(\n message: string,\n status: number,\n readonly upstreamBody: string,\n readonly attemptLabel: string,\n options?: ErrorOptions,\n ) {\n super(message, REQUEST_FORWARD_FAILED, status, options);\n }\n}\n\ninterface AttemptTarget {\n resolved: ResolvedSlotConfig;\n provider: ProviderRuntimeConfig;\n label: string;\n}\n\ninterface AttemptSuccess {\n response: ForwardedResponse;\n history: AttemptHistoryPayload;\n}\n\ninterface CodexForwardAuth {\n accessToken: string | null;\n accountId: string | null;\n}\n\ninterface AttemptFailure {\n error: GatewayServiceError;\n payloadForHistory: string;\n}\n\ninterface AttemptResult {\n ok: true;\n success: AttemptSuccess;\n}\n\ninterface AttemptErrorResult {\n ok: false;\n failure: AttemptFailure;\n}\n\ntype ProviderAttemptResult = AttemptResult | AttemptErrorResult;\n\nconst HTTP_STATUS_INTERNAL_SERVER_ERROR = 500;\nconst RECOVERABLE_UPSTREAM_STATUSES = new Set([408, 429, 500, 502, 503, 504]);\n\n/**\n * Coordinates settings-backed model selection, request forwarding, and scoped history persistence.\n */\nexport class GatewayService {\n private readonly codeAssistProjectCache = new Map<string, string>();\n\n constructor(\n private readonly profileStore = new ProfileStore(),\n private readonly codexAuth = new CodexAuth(consoleLogger, DEFAULT_AUTH_FILE_PATH),\n private readonly logger: LoggerLike = consoleLogger,\n private readonly fetchImpl: typeof fetch = fetch,\n private readonly historyService = new ConversationHistoryService(),\n ) {}\n\n /**\n * Lists all configured profiles for the given scope.\n */\n async listProfiles(scope = DEFAULT_SCOPE): Promise<ProxyProfile[]> {\n return this.profileStore.listProfiles(scope);\n }\n\n /**\n * Eagerly seeds the scoped settings file so startup always has a backing config.\n */\n async ensureConfig(scope = DEFAULT_SCOPE): Promise<Awaited<ReturnType<ProfileStore['ensureConfig']>>> {\n await this.historyService.ensureInitialized();\n return this.profileStore.ensureConfig(scope);\n }\n\n /**\n * Returns the resolved admin config used by the live HTTP server and UI.\n */\n async getAdminConfig(scope = DEFAULT_SCOPE): Promise<AdminConfig> {\n return this.profileStore.getAdminConfig(scope);\n }\n\n /**\n * Updates the resolved admin config.\n */\n async updateAdminConfig(update: AdminConfigUpdate, scope = DEFAULT_SCOPE): Promise<AdminConfig> {\n await this.profileStore.updateConfig(update, scope);\n return this.profileStore.getAdminConfig(scope);\n }\n\n /**\n * Returns the currently selected profile for a scope/slot pair.\n */\n async getActiveProfile(scope = DEFAULT_SCOPE, slot: ModelSlot = DEFAULT_SLOT): Promise<ProxyProfile | null> {\n return this.profileStore.getActiveProfile(scope, slot);\n }\n\n /**\n * Creates or updates a profile in the scoped settings file.\n */\n async upsertProfile(\n profile: ProxyProfile,\n scope = DEFAULT_SCOPE,\n ): Promise<Awaited<ReturnType<ProfileStore['upsertProfile']>>> {\n return this.profileStore.upsertProfile(profile, scope);\n }\n\n /**\n * Selects the active profile by profile id for the requested slot.\n */\n async setActiveProfile(\n profileId: string,\n scope = DEFAULT_SCOPE,\n slot: ModelSlot = DEFAULT_SLOT,\n ): Promise<Awaited<ReturnType<ProfileStore['setActiveProfile']>>> {\n return this.profileStore.setActiveProfile(profileId, scope, slot);\n }\n\n /**\n * Returns the active profile currently used for routing requests.\n */\n async getCurrentModel(scope = DEFAULT_SCOPE, slot: ModelSlot = DEFAULT_SLOT): Promise<ProxyProfile | null> {\n return this.profileStore.getActiveProfile(scope, slot);\n }\n\n /**\n * Switches the selected model by model name.\n */\n async switchModel(\n model: string,\n scope = DEFAULT_SCOPE,\n slot: ModelSlot = DEFAULT_SLOT,\n ): Promise<Awaited<ReturnType<ProfileStore['updateConfig']>>> {\n const profiles = await this.profileStore.listProfiles(scope);\n const current = await this.profileStore.getResolvedSlotConfig(scope, slot);\n const profile =\n profiles.find((item) => item.model === model && item.provider === current.provider && item.enabled) ??\n profiles.find((item) => item.model === model && item.enabled);\n if (!profile) {\n throw new GatewayConfigError(`Model not found or disabled: ${model}`, MODEL_NOT_FOUND, 400, {\n cause: { model, scope, slot },\n });\n }\n\n return this.profileStore.updateConfig(\n {\n models: {\n [slot]: {\n main: {\n provider: profile.provider,\n model: profile.model,\n reasoningEffort: profile.reasoningEffort,\n },\n fallbacks: (await this.profileStore.getAdminConfig(scope)).scopeModels[slot]?.fallbacks ?? [],\n },\n },\n },\n scope,\n );\n }\n\n /**\n * Lists persisted history for a scope.\n */\n async listHistory(\n scope = DEFAULT_SCOPE,\n limit = DEFAULT_HISTORY_PAGE_SIZE,\n cursor?: string,\n ): Promise<ConversationHistoryPage> {\n return this.historyService.listHistory(scope, limit, cursor);\n }\n\n /**\n * Clears persisted history for a scope.\n */\n async clearHistory(scope = DEFAULT_SCOPE): Promise<{ deleted: number }> {\n const deleted = await this.historyService.clearScope(scope);\n return { deleted };\n }\n\n /**\n * Lists known scopes from config files and stored history.\n */\n async listScopes(): Promise<string[]> {\n const [configScopes, historyScopes] = await Promise.all([\n this.profileStore.listScopes(),\n this.historyService.listScopes(),\n ]);\n\n return Array.from(new Set([...configScopes, ...historyScopes, DEFAULT_SCOPE])).sort();\n }\n\n /**\n * Returns persisted history stats for a scope.\n */\n async getHistoryStats(scope = DEFAULT_SCOPE): Promise<ConversationHistoryStats> {\n return this.historyService.getStats(scope);\n }\n\n /**\n * Returns the current gateway status, auth state, and active slot routing.\n */\n async getStatus(scope = DEFAULT_SCOPE, port?: number, pid?: number): Promise<GatewayStatus> {\n const config = await this.profileStore.getConfig(scope);\n const activeSlot = await this.profileStore.getResolvedSlotConfig(scope, DEFAULT_SLOT);\n const authStatus = await this.codexAuth.getAuthStatus();\n const slotModels = Object.fromEntries(\n await Promise.all(\n MODEL_SLOTS.map(async (slot) => {\n const resolved = await this.profileStore.getResolvedSlotConfig(scope, slot);\n return [\n slot,\n {\n profileId: resolved.profileId,\n provider: resolved.provider,\n model: resolved.model,\n reasoningEffort: resolved.reasoningEffort,\n thinkingDisabled: resolved.thinkingDisabled ?? false,\n },\n ];\n }),\n ),\n ) as GatewayStatus['slotModels'];\n\n return {\n running: true,\n port,\n pid,\n scope,\n activeProfileId: config.activeProfileId,\n activeModel: activeSlot.model ?? undefined,\n activeReasoningEffort: activeSlot.reasoningEffort,\n slotModels,\n auth: authStatus,\n profiles: config.profiles,\n };\n }\n\n /**\n * Returns the OpenAI-compatible model listing served by the proxy.\n */\n async getModels(scope = DEFAULT_SCOPE): Promise<{\n object: string;\n data: Array<{ id: string; object: string; created: number; owned_by: string; metadata: Record<string, string> }>;\n }> {\n const profiles = await this.profileStore.listProfiles(scope);\n return {\n object: 'list',\n data: profiles.map((profile) => ({\n id: profile.model,\n object: 'model',\n created: 0,\n owned_by: `${profile.provider}:${profile.id}`,\n metadata: {\n profileId: profile.id,\n reasoningEffort: profile.reasoningEffort,\n },\n })),\n };\n }\n\n /**\n * Forwards a Claude-compatible request to the configured upstream Codex endpoint.\n */\n async forwardClaudeRequest(\n requestBody: string,\n scope = DEFAULT_SCOPE,\n requestHeaders: Headers = new Headers(),\n ): Promise<ForwardedResponse> {\n const requestId = ulid();\n let slot = DEFAULT_SLOT;\n let resolved: ResolvedSlotConfig | null = null;\n\n try {\n const parsed = this.parseClaudeRequest(requestBody);\n const adminConfig = await this.profileStore.getAdminConfig(scope);\n slot = this.resolveSlot(parsed.model, adminConfig);\n resolved = this.resolveRequestedModel(parsed.model, adminConfig, slot);\n if (!resolved.model) {\n const message = `No active model configured for scope '${scope}' and slot '${slot}'`;\n await this.recordError(scope, slot, resolved, requestId, message, requestBody);\n return this.createErrorResponse(400, message);\n }\n\n const attemptTargets = this.buildAttemptTargets(adminConfig, resolved, slot);\n if (attemptTargets.length === 0) {\n const message = `No provider configured for scope '${scope}' and slot '${slot}'`;\n await this.recordError(scope, slot, resolved, requestId, message, requestBody);\n return this.createErrorResponse(400, message);\n }\n\n await this.recordRequest(scope, slot, attemptTargets[0].resolved, requestId, parsed, requestBody);\n\n let lastRecoverableFailure: AttemptFailure | null = null;\n for (const target of attemptTargets) {\n const result = await this.forwardSingleAttempt(target, parsed, requestBody, scope, slot, requestHeaders);\n if (result.ok) {\n await this.recordResponse(\n scope,\n slot,\n target.resolved,\n requestId,\n result.success.history.upstreamText,\n result.success.history.claudeBody,\n );\n return result.success.response;\n }\n\n const { error, payloadForHistory } = result.failure;\n if (!this.isRecoverableUpstreamError(error)) {\n this.logger.error('[model-proxy-mcp] Non-recoverable model attempt failed', {\n scope,\n slot,\n model: target.resolved.model,\n code: error.code,\n status: error.status,\n message: error.message,\n });\n await this.recordError(scope, slot, target.resolved, requestId, error.message, payloadForHistory);\n return this.createErrorResponse(error.status, error.message);\n }\n\n lastRecoverableFailure = result.failure;\n this.logger.warn('[model-proxy-mcp] Recoverable model attempt failed; trying fallback', {\n scope,\n slot,\n model: target.resolved.model,\n code: error.code,\n status: error.status,\n message: error.message,\n });\n await this.recordError(\n scope,\n slot,\n target.resolved,\n requestId,\n `Attempt failed for ${target.label}: ${error.message}`,\n payloadForHistory,\n );\n }\n\n if (lastRecoverableFailure) {\n await this.recordError(\n scope,\n slot,\n resolved,\n requestId,\n lastRecoverableFailure.error.message,\n lastRecoverableFailure.payloadForHistory,\n );\n return this.createErrorResponse(lastRecoverableFailure.error.status, lastRecoverableFailure.error.message);\n }\n\n const message = 'No model attempt could be executed';\n await this.recordError(scope, slot, resolved, requestId, message, requestBody);\n return this.createErrorResponse(HTTP_STATUS_INTERNAL_SERVER_ERROR, message);\n } catch (error) {\n const gatewayError =\n error instanceof GatewayServiceError\n ? error\n : new GatewayServiceError('Failed to process Claude proxy request', REQUEST_FORWARD_FAILED, 500, {\n cause: error,\n });\n this.logger.error('[model-proxy-mcp] Request forwarding failed', {\n scope,\n slot,\n code: gatewayError.code,\n message: gatewayError.message,\n cause: gatewayError.cause,\n });\n await this.recordError(scope, slot, resolved, requestId, gatewayError.message, requestBody);\n return this.createErrorResponse(gatewayError.status, gatewayError.message);\n }\n }\n\n private buildAttemptTargets(adminConfig: AdminConfig, primary: ResolvedSlotConfig, slot: ModelSlot): AttemptTarget[] {\n const targets: AttemptTarget[] = [];\n const dedupe = new Set<string>();\n const candidates = [primary, ...primary.fallbacks.map((fallback) => ({ ...primary, ...fallback, slot }))];\n\n for (const candidate of candidates) {\n const providerId = candidate.provider;\n const modelId = candidate.model;\n if (!providerId || !modelId) {\n continue;\n }\n const provider = adminConfig.providers[providerId];\n if (!provider) {\n continue;\n }\n const key = `${providerId}:${modelId}:${candidate.reasoningEffort}:${candidate.thinkingDisabled ? 'off' : 'on'}`;\n if (dedupe.has(key)) {\n continue;\n }\n dedupe.add(key);\n targets.push({\n resolved: {\n ...candidate,\n slot,\n provider: providerId,\n model: modelId,\n providerType: provider.type,\n endpoint: provider.endpoint,\n reasoningEffort: candidate.reasoningEffort,\n thinkingDisabled: candidate.thinkingDisabled ?? false,\n fallbacks: [],\n },\n provider,\n label: `${providerId}/${modelId}`,\n });\n }\n\n return targets;\n }\n\n private async forwardSingleAttempt(\n target: AttemptTarget,\n parsedRequest: z.infer<typeof CLAUDE_REQUEST_SCHEMA>,\n requestBody: string,\n scope: string,\n slot: ModelSlot,\n requestHeaders: Headers,\n ): Promise<ProviderAttemptResult> {\n try {\n if (target.resolved.providerType === ANTHROPIC_COMPATIBLE_PROVIDER) {\n return {\n ok: true,\n success: await this.forwardAnthropicCompatibleRequest(\n requestBody,\n scope,\n slot,\n target.resolved,\n target.provider,\n requestHeaders,\n ),\n };\n }\n\n if (target.resolved.providerType === GEMINI_DIRECT_PROVIDER) {\n return {\n ok: true,\n success: await this.forwardGeminiDirectRequest(\n parsedRequest,\n scope,\n slot,\n target.resolved,\n target.provider,\n requestHeaders,\n ),\n };\n }\n\n return {\n ok: true,\n success: await this.forwardCodexRequest(requestBody, scope, slot, target.resolved, target.provider),\n };\n } catch (error) {\n const gatewayError =\n error instanceof GatewayServiceError\n ? error\n : new GatewayServiceError('Failed to process Claude proxy request', REQUEST_FORWARD_FAILED, 500, {\n cause: error,\n });\n const payloadForHistory = error instanceof GatewayUpstreamError ? error.upstreamBody : requestBody;\n return { ok: false, failure: { error: gatewayError, payloadForHistory } };\n }\n }\n\n private isRecoverableUpstreamError(error: GatewayServiceError): boolean {\n return error instanceof GatewayUpstreamError && RECOVERABLE_UPSTREAM_STATUSES.has(error.status);\n }\n\n private createCodexSessionId(scope: string, slot: ModelSlot, resolved: ResolvedSlotConfig): string {\n const sessionKey = [\n DEFAULT_SERVICE_NAME,\n 'codex',\n scope,\n slot,\n resolved.provider ?? 'unknown-provider',\n resolved.model ?? 'unknown-model',\n ].join(':');\n\n return createHash('sha256').update(sessionKey).digest('hex');\n }\n\n private createGeminiSessionId(scope: string, slot: ModelSlot, resolved: ResolvedSlotConfig): string {\n const sessionKey = [\n DEFAULT_SERVICE_NAME,\n 'gemini-code-assist',\n scope,\n slot,\n resolved.provider ?? 'unknown-provider',\n resolved.model ?? 'unknown-model',\n ].join(':');\n\n return createHash('sha256').update(sessionKey).digest('hex');\n }\n\n private createCodeAssistProjectCacheKey(authHeaders: GeminiAuthHeaders): string {\n const configuredProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT_ID || '';\n const headerEntries = Object.entries(authHeaders.headers).sort(([left], [right]) => left.localeCompare(right));\n return JSON.stringify({\n authMode: authHeaders.authMode,\n authSource: authHeaders.authSource,\n authType: authHeaders.authType ?? null,\n configuredProject,\n headers: headerEntries,\n });\n }\n\n private async forwardCodexRequest(\n requestBody: string,\n scope: string,\n slot: ModelSlot,\n resolved: ResolvedSlotConfig,\n provider: ProviderRuntimeConfig,\n ): Promise<AttemptSuccess> {\n const resolvedModel = resolved.model;\n if (!resolvedModel) {\n throw new GatewayConfigError(`No active model configured for slot '${slot}'`, MODEL_NOT_FOUND, 400);\n }\n\n const auth: CodexForwardAuth = await this.codexAuth.resolveAuth();\n const providerApiKey = provider.apiKeyEnvVar ? process.env[provider.apiKeyEnvVar] : undefined;\n if (!auth.accessToken && !providerApiKey) {\n throw new GatewayAuthError('Missing Codex auth. Sign in with the official Codex CLI first.', 'AUTH_MISSING', 401);\n }\n\n const transformerConfig: RouterConfig = {\n toProvider: CHATGPT_CODEX_PROVIDER,\n toModel: resolvedModel,\n toEndpoint: resolved.endpoint ?? CLAUDE_MESSAGES_ENDPOINT,\n toApiKey: providerApiKey,\n sessionId: this.createCodexSessionId(scope, slot, resolved),\n sessionReasoningEffort: resolved.reasoningEffort,\n thinkingDisabled: resolved.thinkingDisabled ?? false,\n logger: this.logger,\n resolvedAuth: auth,\n };\n const transformer = new ClaudeToOpenAITransformer(transformerConfig);\n const responseTransformer = new OpenAIToClaudeTransformer(this.logger, resolved.thinkingDisabled ?? false);\n\n const transformed = await transformer.transform(CLAUDE_MESSAGES_ENDPOINT, requestBody);\n const upstreamResponse = await this.fetchImpl(transformed.url, {\n method: 'POST',\n headers: transformed.headers,\n body: transformed.body,\n });\n\n if (!upstreamResponse.ok) {\n const upstreamText = await upstreamResponse.text();\n this.logger.error('[model-proxy-mcp] Upstream request failed', {\n scope,\n slot,\n profileId: resolved.profileId,\n model: resolved.model,\n status: upstreamResponse.status,\n body: upstreamText,\n });\n throw new GatewayUpstreamError(\n upstreamText || 'Codex upstream request failed',\n upstreamResponse.status,\n upstreamText,\n `${resolved.provider}/${resolved.model}`,\n );\n }\n\n const upstreamText = await upstreamResponse.text();\n const body = responseTransformer.transform(upstreamText);\n return {\n response: {\n status: HTTP_STATUS_OK,\n body,\n headers: this.createSuccessHeaders(scope, slot),\n },\n history: {\n upstreamText,\n claudeBody: body,\n },\n } satisfies CodexBufferedResult;\n }\n\n /**\n * Forwards a Claude-compatible request to the Gemini GenerateContent REST API and translates the result back to Claude SSE.\n */\n private async forwardGeminiDirectRequest(\n parsedRequest: z.infer<typeof CLAUDE_REQUEST_SCHEMA>,\n scope: string,\n slot: ModelSlot,\n resolved: ResolvedSlotConfig,\n provider: ProviderRuntimeConfig,\n _requestHeaders: Headers,\n ): Promise<AttemptSuccess> {\n try {\n const resolvedModel = resolved.model;\n if (!resolvedModel) {\n throw new GatewayConfigError(\n `No active Gemini model configured for scope '${scope}' and slot '${slot}'`,\n MODEL_NOT_FOUND,\n 400,\n );\n }\n\n const auth = new GeminiAuth(this.logger);\n const authHeaders = await auth.resolveHeaders(provider);\n const requestTransformer = new ClaudeToGeminiTransformer();\n const responseTransformer = new GeminiToClaudeTransformer();\n const geminiRequest: Parameters<ClaudeToGeminiTransformer['transform']>[0] = {\n model: parsedRequest.model,\n system: parsedRequest.system,\n messages: parsedRequest.messages as Parameters<ClaudeToGeminiTransformer['transform']>[0]['messages'],\n tools: parsedRequest.tools as Parameters<ClaudeToGeminiTransformer['transform']>[0]['tools'],\n max_tokens: parsedRequest.max_tokens,\n };\n const transformed = requestTransformer.transform(\n geminiRequest,\n resolvedModel,\n resolved.reasoningEffort,\n resolved.thinkingDisabled ?? false,\n );\n if (authHeaders.authType === GEMINI_PERSONAL_OAUTH_AUTH_TYPE) {\n return await this.forwardGeminiCodeAssistRequest(\n transformed.body,\n scope,\n slot,\n resolved,\n authHeaders,\n responseTransformer,\n );\n }\n\n const url = this.createGeminiRequestUrl(provider, transformed.modelPath, GEMINI_GENERATE_CONTENT_METHOD);\n const headers = new Headers(authHeaders.headers);\n headers.set(RESPONSE_CONTENT_TYPE_HEADER, JSON_CONTENT_TYPE);\n headers.set(ACCEPT_HEADER, JSON_CONTENT_TYPE);\n\n const timeoutMs = provider.apiTimeoutMs ?? this.resolveUpstreamTimeoutMs();\n const upstreamResponse = await this.fetchImpl(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(transformed.body),\n signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined,\n });\n\n const upstreamText = await upstreamResponse.text();\n if (!upstreamResponse.ok) {\n this.logger.error('[model-proxy-mcp] Gemini upstream request failed', {\n scope,\n slot,\n profileId: resolved.profileId,\n model: resolved.model,\n status: upstreamResponse.status,\n body: upstreamText,\n authMode: authHeaders.authMode,\n authSource: authHeaders.authSource,\n });\n throw new GatewayUpstreamError(\n upstreamText || 'Gemini upstream request failed',\n upstreamResponse.status,\n upstreamText,\n `${resolved.provider}/${resolved.model}`,\n );\n }\n\n const body = responseTransformer.transformBuffered(upstreamText, resolvedModel);\n\n return {\n response: {\n status: HTTP_STATUS_OK,\n body,\n headers: this.createSuccessHeaders(scope, slot),\n },\n history: {\n upstreamText,\n claudeBody: body,\n },\n };\n } catch (error) {\n if (error instanceof GeminiAuthError) {\n throw new GatewayAuthError(error.message, error.code, 401, { cause: error });\n }\n throw error;\n }\n }\n\n private async forwardGeminiCodeAssistRequest(\n transformedBody: GeminiGenerateContentRequest,\n scope: string,\n slot: ModelSlot,\n resolved: ResolvedSlotConfig,\n authHeaders: GeminiAuthHeaders,\n responseTransformer: GeminiToClaudeTransformer,\n ): Promise<AttemptSuccess> {\n const projectId = await this.resolveCodeAssistProjectId(authHeaders);\n const url = this.createCodeAssistUrl(GEMINI_GENERATE_CONTENT_METHOD);\n const headers = new Headers(authHeaders.headers);\n headers.set(RESPONSE_CONTENT_TYPE_HEADER, JSON_CONTENT_TYPE);\n headers.set(ACCEPT_HEADER, JSON_CONTENT_TYPE);\n\n const requestBody = {\n model: resolved.model,\n project: projectId,\n user_prompt_id: ulid(),\n request: this.toCodeAssistGenerateContentRequest(\n transformedBody,\n this.createGeminiSessionId(scope, slot, resolved),\n ),\n };\n\n const upstreamResponse = await this.fetchImpl(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n\n const upstreamText = await upstreamResponse.text();\n if (!upstreamResponse.ok) {\n this.logger.error('[model-proxy-mcp] Gemini Code Assist request failed', {\n scope,\n slot,\n profileId: resolved.profileId,\n model: resolved.model,\n status: upstreamResponse.status,\n body: upstreamText,\n authMode: authHeaders.authMode,\n authSource: authHeaders.authSource,\n authType: authHeaders.authType,\n });\n throw new GatewayUpstreamError(\n upstreamText || 'Gemini Code Assist request failed',\n upstreamResponse.status,\n upstreamText,\n `${resolved.provider}/${resolved.model}`,\n );\n }\n\n const normalizedResponse = this.normalizeCodeAssistBufferedResponse(upstreamText);\n const body = responseTransformer.transformBuffered(normalizedResponse, resolved.model ?? 'gemini');\n\n return {\n response: {\n status: HTTP_STATUS_OK,\n body,\n headers: this.createSuccessHeaders(scope, slot),\n },\n history: {\n upstreamText,\n claudeBody: body,\n },\n };\n }\n\n /**\n * Builds response headers shared by successful SSE responses.\n */\n private createSuccessHeaders(scope: string, slot: ModelSlot): Record<string, string> {\n return {\n [RESPONSE_CONTENT_TYPE_HEADER]: SSE_CONTENT_TYPE,\n [RESPONSE_CACHE_CONTROL_HEADER]: HEADER_NO_CACHE,\n [RESPONSE_CONNECTION_HEADER]: HEADER_KEEP_ALIVE,\n 'x-model-proxy-service': DEFAULT_SERVICE_NAME,\n 'x-model-proxy-scope': scope,\n 'x-model-proxy-slot': slot,\n };\n }\n\n /**\n * Builds the target Gemini REST endpoint for buffered or streaming requests.\n */\n private createGeminiRequestUrl(\n provider: ProviderRuntimeConfig,\n modelPath: string,\n method: typeof GEMINI_GENERATE_CONTENT_METHOD,\n ): string {\n const baseUrl = provider.endpoint.replace(/\\/$/, '');\n const apiVersion = provider.apiVersion ?? GEMINI_DEFAULT_API_VERSION;\n return new URL(`${baseUrl}/${apiVersion}/${modelPath}:${method}`).toString();\n }\n\n private createCodeAssistUrl(method: typeof GEMINI_GENERATE_CONTENT_METHOD | typeof CODE_ASSIST_LOAD_METHOD): string {\n return new URL(`${GEMINI_CODE_ASSIST_ENDPOINT}/${GEMINI_CODE_ASSIST_API_VERSION}:${method}`).toString();\n }\n\n private async resolveCodeAssistProjectId(authHeaders: GeminiAuthHeaders): Promise<string> {\n const cacheKey = this.createCodeAssistProjectCacheKey(authHeaders);\n const cachedProjectId = this.codeAssistProjectCache.get(cacheKey);\n if (cachedProjectId) {\n return cachedProjectId;\n }\n\n const headers = new Headers(authHeaders.headers);\n headers.set(RESPONSE_CONTENT_TYPE_HEADER, JSON_CONTENT_TYPE);\n\n const configuredProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT_ID || undefined;\n const response = await this.fetchImpl(this.createCodeAssistUrl(CODE_ASSIST_LOAD_METHOD), {\n method: 'POST',\n headers,\n body: JSON.stringify({\n cloudaicompanionProject: configuredProject,\n metadata: {\n ideType: CODE_ASSIST_IDE_TYPE,\n platform: CODE_ASSIST_PLATFORM,\n pluginType: CODE_ASSIST_PLUGIN_TYPE,\n duetProject: configuredProject,\n },\n }),\n });\n\n const responseText = await response.text();\n if (!response.ok) {\n throw new GatewayUpstreamError(\n responseText || 'Failed to load Gemini Code Assist project context',\n response.status,\n responseText,\n 'google-gemini-direct/loadCodeAssist',\n );\n }\n\n const payload = JSON.parse(responseText) as { cloudaicompanionProject?: string };\n const projectId = payload.cloudaicompanionProject || configuredProject;\n if (!projectId) {\n throw new GatewayAuthError(\n 'Gemini Code Assist did not return a usable project ID.',\n 'GEMINI_PROJECT_MISSING',\n 401,\n );\n }\n\n this.codeAssistProjectCache.set(cacheKey, projectId);\n return projectId;\n }\n\n private toCodeAssistGenerateContentRequest(\n body: GeminiGenerateContentRequest,\n sessionId: string,\n ): Record<string, unknown> {\n return {\n contents: body.contents,\n systemInstruction: body.system_instruction,\n tools: body.tools,\n toolConfig: body.tool_config,\n generationConfig: body.generationConfig,\n session_id: sessionId,\n };\n }\n\n private normalizeCodeAssistBufferedResponse(responseBody: string): string {\n const parsed = JSON.parse(responseBody) as {\n response?: GeminiGenerateContentResponse;\n traceId?: string;\n };\n\n return JSON.stringify(this.extractCodeAssistResponse(parsed));\n }\n\n private normalizeCodeAssistStreamingResponse(responseBody: string): string {\n const chunks: string[] = [];\n\n for (const event of responseBody.split('\\n\\n')) {\n const dataLine = event\n .split('\\n')\n .find((line) => line.startsWith('data:'))\n ?.slice(5)\n .trim();\n if (!dataLine || dataLine === '[DONE]') {\n continue;\n }\n\n const parsed = JSON.parse(dataLine) as { response?: GeminiGenerateContentResponse; traceId?: string };\n chunks.push(`data: ${JSON.stringify(this.extractCodeAssistResponse(parsed))}`);\n chunks.push('');\n }\n\n return chunks.join('\\n');\n }\n\n private extractCodeAssistResponse(payload: {\n response?: GeminiGenerateContentResponse;\n traceId?: string;\n }): GeminiGenerateContentResponse {\n return {\n candidates: payload.response?.candidates ?? [],\n usageMetadata: payload.response?.usageMetadata,\n modelVersion: payload.response?.modelVersion,\n };\n }\n\n /**\n * Resolves the logical slot from a Claude model name or configured model mapping.\n */\n private resolveSlot(model: string | undefined, adminConfig: AdminConfig): ModelSlot {\n if (!model) {\n return DEFAULT_SLOT;\n }\n\n const mappedSlot = MODEL_SLOT_BY_NAME[model];\n if (mappedSlot) {\n return mappedSlot;\n }\n\n for (const slot of MODEL_SLOTS) {\n if (adminConfig.slots[slot].model === model) {\n return slot;\n }\n }\n\n return DEFAULT_SLOT;\n }\n\n /**\n * Reconciles a request-specified concrete model with the resolved slot configuration.\n */\n private resolveRequestedModel(\n model: string | undefined,\n adminConfig: AdminConfig,\n slot: ModelSlot,\n ): ResolvedSlotConfig {\n const resolved = adminConfig.slots[slot];\n if (!model || MODEL_SLOT_BY_NAME[model]) {\n return resolved;\n }\n\n const profile =\n adminConfig.models.find((item) => item.model === model && item.provider === resolved.provider && item.enabled) ??\n adminConfig.models.find((item) => item.model === model && item.enabled);\n if (!profile && resolved.model !== model) {\n throw new GatewayConfigError(`Model not found or disabled: ${model}`, MODEL_NOT_FOUND, 400, {\n cause: { model, slot, scope: adminConfig.scope },\n });\n }\n\n return {\n ...resolved,\n profileId: profile?.id ?? null,\n label: profile?.label ?? null,\n provider: profile?.provider ?? resolved.provider,\n providerType: profile?.providerType ?? resolved.providerType,\n endpoint: profile?.endpoint ?? resolved.endpoint,\n model: profile?.model ?? model,\n reasoningEffort: profile?.reasoningEffort ?? resolved.reasoningEffort,\n thinkingDisabled: resolved.thinkingDisabled ?? false,\n };\n }\n\n /**\n * Forwards a Claude-compatible request to an Anthropic-compatible upstream such as Z.ai.\n */\n private async forwardAnthropicCompatibleRequest(\n requestBody: string,\n scope: string,\n slot: ModelSlot,\n resolved: ResolvedSlotConfig,\n provider: ProviderRuntimeConfig,\n requestHeaders: Headers,\n ): Promise<AttemptSuccess> {\n const token = this.getAnthropicCompatibleAuthToken(provider.authTokenEnvVar);\n if (!token) {\n const message = `Missing upstream auth token for ${ANTHROPIC_COMPATIBLE_PROVIDER}. Set ${provider.authTokenEnvVar || DEFAULT_UPSTREAM_AUTH_ENV}.`;\n throw new GatewayAuthError(message, 'UPSTREAM_AUTH_MISSING', 401);\n }\n\n const payload = this.sanitizeClaudePayloadForAnthropic({\n ...CLAUDE_REQUEST_SCHEMA.parse(JSON.parse(requestBody)),\n model: resolved.model,\n });\n\n const headers = new Headers();\n headers.set(ACCEPT_HEADER, requestHeaders.get(ACCEPT_HEADER) ?? SSE_CONTENT_TYPE);\n headers.set(RESPONSE_CONTENT_TYPE_HEADER, JSON_CONTENT_TYPE);\n headers.set(ANTHROPIC_VERSION_HEADER, requestHeaders.get(ANTHROPIC_VERSION_HEADER) ?? DEFAULT_ANTHROPIC_VERSION);\n headers.set(X_API_KEY_HEADER, token);\n headers.set(AUTHORIZATION_HEADER, `Bearer ${token}`);\n\n const anthropicBeta = requestHeaders.get(ANTHROPIC_BETA_HEADER);\n if (anthropicBeta) {\n headers.set(ANTHROPIC_BETA_HEADER, anthropicBeta);\n }\n\n const timeoutMs = provider.apiTimeoutMs ?? this.resolveUpstreamTimeoutMs();\n const upstreamResponse = await this.fetchImpl(provider.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined,\n });\n\n const upstreamText = await upstreamResponse.text();\n if (!upstreamResponse.ok) {\n this.logger.error('[model-proxy-mcp] Anthropic-compatible upstream request failed', {\n scope,\n slot,\n profileId: resolved.profileId,\n model: resolved.model,\n status: upstreamResponse.status,\n body: upstreamText,\n });\n throw new GatewayUpstreamError(\n upstreamText || 'Anthropic-compatible upstream request failed',\n upstreamResponse.status,\n upstreamText,\n `${resolved.provider}/${resolved.model}`,\n );\n }\n\n return {\n response: {\n status: upstreamResponse.status,\n body: upstreamText,\n headers: {\n [RESPONSE_CONTENT_TYPE_HEADER]:\n upstreamResponse.headers.get(RESPONSE_CONTENT_TYPE_HEADER) ?? SSE_CONTENT_TYPE,\n [RESPONSE_CACHE_CONTROL_HEADER]:\n upstreamResponse.headers.get(RESPONSE_CACHE_CONTROL_HEADER) ?? HEADER_NO_CACHE,\n [RESPONSE_CONNECTION_HEADER]: upstreamResponse.headers.get(RESPONSE_CONNECTION_HEADER) ?? HEADER_KEEP_ALIVE,\n 'x-model-proxy-service': DEFAULT_SERVICE_NAME,\n 'x-model-proxy-scope': scope,\n 'x-model-proxy-slot': slot,\n },\n },\n history: {\n upstreamText,\n claudeBody: upstreamText,\n },\n };\n }\n\n /**\n * Resolves the environment-provided auth token for Anthropic-compatible upstreams.\n */\n private getAnthropicCompatibleAuthToken(configuredEnvVar?: string | null): string | null {\n const envVarName = configuredEnvVar || process.env[CONFIGURED_UPSTREAM_AUTH_ENV_NAME] || DEFAULT_UPSTREAM_AUTH_ENV;\n return process.env[envVarName] || process.env[FALLBACK_UPSTREAM_AUTH_ENV] || null;\n }\n\n /**\n * Resolves the request timeout for upstream Anthropic-compatible calls.\n */\n private resolveUpstreamTimeoutMs(): number | null {\n const rawTimeout = process.env[DEFAULT_API_TIMEOUT_ENV] || process.env[FALLBACK_UPSTREAM_TIMEOUT_ENV];\n if (!rawTimeout) {\n return null;\n }\n\n const timeoutMs = Number.parseInt(rawTimeout, 10);\n return Number.isInteger(timeoutMs) && timeoutMs > 0 ? timeoutMs : null;\n }\n\n private createErrorResponse(status: number, message: string): ForwardedResponse {\n return {\n status,\n body: JSON.stringify({ type: 'error', error: { type: API_ERROR_TYPE, message } }),\n headers: { 'content-type': ERROR_RESPONSE_CONTENT_TYPE },\n };\n }\n\n /**\n * Parses and validates an inbound Claude request.\n */\n private parseClaudeRequest(requestBody: string): z.infer<typeof CLAUDE_REQUEST_SCHEMA> {\n try {\n return CLAUDE_REQUEST_SCHEMA.parse(JSON.parse(requestBody));\n } catch (error) {\n if (error instanceof SyntaxError || error instanceof ZodError) {\n throw new GatewayValidationError('Invalid Claude request payload', REQUEST_VALIDATION_FAILED, 400, {\n cause: error,\n });\n }\n\n throw error;\n }\n }\n\n /**\n * Persists normalized inbound request messages for a proxied call.\n */\n private async recordRequest(\n scope: string,\n slot: ModelSlot,\n resolved: ResolvedSlotConfig,\n requestId: string,\n parsedRequest: z.infer<typeof CLAUDE_REQUEST_SCHEMA>,\n rawBody: string,\n ): Promise<void> {\n const entries: Omit<ConversationHistoryEntry, 'id' | 'createdAt'>[] = [];\n const systemEntries = this.normalizeSystemPayloads(parsedRequest.system);\n for (const payload of systemEntries) {\n entries.push({\n scope,\n requestId,\n direction: REQUEST_DIRECTION,\n role: SYSTEM_ROLE,\n messageType: SYSTEM_ROLE,\n model: resolved.model,\n slot,\n payloadJson: JSON.stringify(payload),\n });\n }\n\n const messages = Array.isArray(parsedRequest.messages) ? parsedRequest.messages : [];\n for (const message of messages) {\n const role = this.extractRole(message);\n entries.push({\n scope,\n requestId,\n direction: REQUEST_DIRECTION,\n role,\n messageType: MESSAGE_MESSAGE_TYPE,\n model: resolved.model,\n slot,\n payloadJson: JSON.stringify(message),\n });\n }\n\n if (entries.length === 0) {\n entries.push({\n scope,\n requestId,\n direction: REQUEST_DIRECTION,\n role: null,\n messageType: RAW_REQUEST_MESSAGE_TYPE,\n model: resolved.model,\n slot,\n payloadJson: rawBody,\n });\n }\n\n await this.historyService.appendEntries(entries);\n }\n\n /**\n * Persists normalized upstream response items or a stream fallback.\n */\n private async recordResponse(\n scope: string,\n slot: ModelSlot,\n resolved: ResolvedSlotConfig,\n requestId: string,\n upstreamText: string,\n claudeBody: string,\n ): Promise<void> {\n const parsedEntries = this.normalizeResponsePayloads(scope, requestId, slot, resolved.model, upstreamText);\n if (parsedEntries.length > 0) {\n await this.historyService.appendEntries(parsedEntries);\n return;\n }\n\n await this.historyService.appendEntries([\n {\n scope,\n requestId,\n direction: RESPONSE_DIRECTION,\n role: ASSISTANT_ROLE,\n messageType: RESPONSE_STREAM_MESSAGE_TYPE,\n model: resolved.model,\n slot,\n payloadJson: JSON.stringify({ upstreamText, claudeBody }),\n },\n ]);\n }\n\n /**\n * Persists a redacted error record for the request lifecycle.\n */\n private async recordError(\n scope: string,\n slot: ModelSlot,\n resolved: ResolvedSlotConfig | null,\n requestId: string,\n message: string,\n payload: string,\n ): Promise<void> {\n await this.historyService.appendEntries([\n {\n scope,\n requestId,\n direction: ERROR_DIRECTION,\n role: null,\n messageType: ERROR_MESSAGE_TYPE,\n model: resolved?.model ?? null,\n slot,\n payloadJson: JSON.stringify({ message, payloadPreview: this.summarizePayload(payload) }),\n },\n ]);\n }\n\n /**\n * Normalizes Claude system payloads into storable entries.\n */\n private normalizeSystemPayloads(system: unknown): unknown[] {\n if (!system) {\n return [];\n }\n\n if (typeof system === 'string') {\n return [{ type: 'text', text: system }];\n }\n\n if (Array.isArray(system)) {\n return system;\n }\n\n return [system];\n }\n\n /**\n * Removes proxy-private metadata before sending Claude payloads to strict Anthropic-compatible upstreams.\n */\n private sanitizeClaudePayloadForAnthropic<T>(payload: T): T {\n return this.stripPrivateChatGptMetadata(payload) as T;\n }\n\n private stripPrivateChatGptMetadata(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => this.stripPrivateChatGptMetadata(item));\n }\n\n if (!value || typeof value !== 'object') {\n return value;\n }\n\n return Object.fromEntries(\n Object.entries(value)\n .filter(([key]) => !key.startsWith('_chatgpt_'))\n .map(([key, nestedValue]) => [key, this.stripPrivateChatGptMetadata(nestedValue)]),\n );\n }\n\n /**\n * Extracts a message role string when present.\n */\n private extractRole(message: unknown): string | null {\n if (!message || typeof message !== 'object') {\n return null;\n }\n\n const candidate = (message as { role?: unknown }).role;\n return typeof candidate === 'string' ? candidate : null;\n }\n\n /**\n * Extracts response output items from upstream SSE payloads for storage.\n */\n private normalizeResponsePayloads(\n scope: string,\n requestId: string,\n slot: ModelSlot,\n model: string | null,\n upstreamText: string,\n ): Omit<ConversationHistoryEntry, 'id' | 'createdAt'>[] {\n const entries: Omit<ConversationHistoryEntry, 'id' | 'createdAt'>[] = [];\n for (const event of upstreamText.split('\\n\\n')) {\n const dataLine = event\n .split('\\n')\n .find((line) => line.startsWith('data:'))\n ?.slice(5)\n .trim();\n if (!dataLine || dataLine === '[DONE]') {\n continue;\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(dataLine);\n } catch {\n continue;\n }\n\n const response = this.extractCompletedResponse(payload);\n if (!response?.output || !Array.isArray(response.output)) {\n continue;\n }\n\n for (const output of response.output as Array<{ type?: string } & Record<string, unknown>>) {\n entries.push({\n scope,\n requestId,\n direction: RESPONSE_DIRECTION,\n role: ASSISTANT_ROLE,\n messageType: typeof output.type === 'string' ? output.type : RESPONSE_ITEM_MESSAGE_TYPE,\n model: typeof response.model === 'string' ? response.model : model,\n slot,\n payloadJson: JSON.stringify(output),\n });\n }\n }\n\n return entries;\n }\n\n /**\n * Extracts the completed response envelope from an upstream SSE event payload.\n */\n private extractCompletedResponse(payload: unknown): { model?: string; output?: unknown[] } | null {\n if (!payload || typeof payload !== 'object') {\n return null;\n }\n\n const candidate = payload as { type?: unknown; response?: unknown; model?: unknown; output?: unknown };\n if (candidate.type === 'response.completed' && candidate.response && typeof candidate.response === 'object') {\n return candidate.response as { model?: string; output?: unknown[] };\n }\n\n if (candidate.response && typeof candidate.response === 'object') {\n return candidate.response as { model?: string; output?: unknown[] };\n }\n\n return {\n model: typeof candidate.model === 'string' ? candidate.model : undefined,\n output: Array.isArray(candidate.output) ? candidate.output : undefined,\n };\n }\n\n /**\n * Redacts large request bodies before they are stored in error history.\n */\n private summarizePayload(payload: string): string {\n const compact = payload.replace(/\\s+/g, ' ').trim();\n return compact.length <= REQUEST_PAYLOAD_PREVIEW_LIMIT\n ? compact\n : `${compact.slice(0, REQUEST_PAYLOAD_PREVIEW_LIMIT)}...`;\n }\n}\n","export const ADMIN_PAGE_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Model Proxy Admin</title>\n <style>\n :root {\n color-scheme: light;\n --bg: #f3efe6;\n --panel: rgba(255, 252, 246, 0.92);\n --panel-border: #d7cdb7;\n --text: #1f1b16;\n --muted: #6b6255;\n --accent: #b24a2f;\n --accent-2: #1b6b73;\n --danger: #8f2d21;\n }\n * { box-sizing: border-box; }\n body {\n margin: 0;\n font-family: \"Iowan Old Style\", \"Palatino Linotype\", serif;\n color: var(--text);\n background:\n radial-gradient(circle at top left, rgba(178, 74, 47, 0.14), transparent 28%),\n radial-gradient(circle at top right, rgba(27, 107, 115, 0.12), transparent 24%),\n linear-gradient(180deg, #f8f4eb 0%, var(--bg) 100%);\n }\n main {\n max-width: 1280px;\n margin: 0 auto;\n padding: 32px 20px 48px;\n }\n h1, h2 {\n margin: 0 0 12px;\n font-weight: 700;\n }\n p { color: var(--muted); margin-top: 0; }\n .hero {\n display: grid;\n gap: 16px;\n margin-bottom: 24px;\n }\n .panel {\n background: var(--panel);\n border: 1px solid var(--panel-border);\n border-radius: 18px;\n padding: 18px;\n box-shadow: 0 14px 40px rgba(80, 58, 24, 0.08);\n }\n .row {\n display: grid;\n gap: 12px;\n }\n .row.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n .row.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n .toolbar {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n align-items: end;\n }\n label {\n display: grid;\n gap: 6px;\n font-size: 13px;\n color: var(--muted);\n }\n input, select, button, textarea {\n font: inherit;\n border-radius: 10px;\n border: 1px solid #c9bea7;\n padding: 10px 12px;\n background: #fffdf8;\n color: var(--text);\n }\n button {\n background: var(--text);\n color: #fff7ea;\n border-color: var(--text);\n cursor: pointer;\n }\n button.secondary {\n background: #fff7ea;\n color: var(--text);\n }\n button.danger {\n background: var(--danger);\n border-color: var(--danger);\n }\n table {\n width: 100%;\n border-collapse: collapse;\n }\n th, td {\n padding: 10px 8px;\n text-align: left;\n border-bottom: 1px solid rgba(107, 98, 85, 0.16);\n vertical-align: top;\n }\n th {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--muted);\n }\n code, pre {\n font-family: \"SFMono-Regular\", \"Menlo\", monospace;\n font-size: 12px;\n }\n pre {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 180px;\n overflow: auto;\n }\n .status {\n min-height: 20px;\n color: var(--accent-2);\n }\n .muted { color: var(--muted); }\n .slot-grid {\n display: grid;\n gap: 12px;\n }\n .slot-card {\n padding: 14px;\n border-radius: 14px;\n border: 1px solid rgba(107, 98, 85, 0.16);\n background: rgba(255, 255, 255, 0.7);\n }\n .slot-card h3 {\n margin: 0 0 10px;\n font-size: 18px;\n }\n .pill {\n display: inline-flex;\n padding: 4px 8px;\n border-radius: 999px;\n background: rgba(27, 107, 115, 0.1);\n color: var(--accent-2);\n font-size: 12px;\n }\n .paths {\n display: grid;\n gap: 8px;\n }\n @media (max-width: 900px) {\n .row.cols-2, .row.cols-3 { grid-template-columns: 1fr; }\n }\n </style>\n </head>\n <body>\n <main>\n <section class=\"hero\">\n <div>\n <h1>Model Proxy Admin</h1>\n <p>Scoped slot routing, provider-aware model selection, and conversation history.</p>\n </div>\n <div class=\"panel toolbar\">\n <label>\n Scope\n <select id=\"scope-input\"></select>\n </label>\n <button id=\"load-button\" class=\"secondary\">Load scope</button>\n <span id=\"status\" class=\"status\"></span>\n </div>\n </section>\n\n <section class=\"panel\">\n <h2>Runtime Config</h2>\n <div class=\"paths muted\">\n <div>Providers: <code id=\"provider-config-path\"></code></div>\n <div>Model catalog: <code id=\"model-list-path\"></code></div>\n <div>Scope config: <code id=\"scope-config-path\"></code></div>\n </div>\n <div id=\"slot-grid\" class=\"slot-grid\" style=\"margin-top:16px;\"></div>\n <div class=\"toolbar\" style=\"margin-top:16px;\">\n <button id=\"save-config\">Save config</button>\n </div>\n </section>\n\n <section class=\"panel\" style=\"margin-top:20px;\">\n <h2>Model Catalog</h2>\n <div id=\"catalog\" class=\"row\"></div>\n </section>\n\n <section class=\"panel\" style=\"margin-top:20px;\">\n <div class=\"toolbar\" style=\"justify-content:space-between;\">\n <div>\n <h2 style=\"margin-bottom:4px;\">Conversation History</h2>\n <p id=\"history-stats\"></p>\n </div>\n <div class=\"toolbar\">\n <label>\n Limit\n <select id=\"history-limit\">\n <option>25</option>\n <option selected>50</option>\n <option>100</option>\n </select>\n </label>\n <button id=\"refresh-history\" class=\"secondary\">Refresh history</button>\n <button id=\"clear-history\" class=\"danger\">Clear history</button>\n </div>\n </div>\n <div style=\"overflow:auto;\">\n <table>\n <thead>\n <tr>\n <th>Created</th>\n <th>Direction</th>\n <th>Role</th>\n <th>Slot</th>\n <th>Model</th>\n <th>Payload</th>\n </tr>\n </thead>\n <tbody id=\"history-body\"></tbody>\n </table>\n </div>\n <div class=\"toolbar\" style=\"margin-top:16px;\">\n <button id=\"more-history\" class=\"secondary\">Load more</button>\n </div>\n </section>\n </main>\n\n <script>\n const reasoningOptions = ['minimal', 'low', 'medium', 'high'];\n const slots = ['default', 'sonnet', 'opus', 'haiku', 'subagent'];\n let currentConfig = null;\n let nextCursor = null;\n\n const scopeInput = document.getElementById('scope-input');\n const statusEl = document.getElementById('status');\n const slotGridEl = document.getElementById('slot-grid');\n const catalogEl = document.getElementById('catalog');\n const providerConfigPathEl = document.getElementById('provider-config-path');\n const modelListPathEl = document.getElementById('model-list-path');\n const scopeConfigPathEl = document.getElementById('scope-config-path');\n const historyBodyEl = document.getElementById('history-body');\n const historyStatsEl = document.getElementById('history-stats');\n const historyLimitEl = document.getElementById('history-limit');\n\n function setStatus(message, isError = false) {\n statusEl.textContent = message;\n statusEl.style.color = isError ? 'var(--danger)' : 'var(--accent-2)';\n }\n\n function renderScopeOptions(scopes) {\n const currentScope = scopeInput.value || 'default';\n const scopeList = Array.from(new Set(['default'].concat(scopes || []))).sort();\n scopeInput.innerHTML = scopeList\n .map((scope) => '<option value=\"' + scope + '\">' + scope + '</option>')\n .join('');\n scopeInput.value = scopeList.includes(currentScope) ? currentScope : 'default';\n }\n\n function providerOptions(providers, selected) {\n return Object.entries(providers)\n .sort((left, right) => left[0].localeCompare(right[0]))\n .map(([id, config]) => {\n const isSelected = id === selected ? ' selected' : '';\n return '<option value=\"' + id + '\"' + isSelected + '>' + id + ' (' + config.type + ')</option>';\n })\n .join('');\n }\n\n function modelOptions(models, provider, selected) {\n return models\n .filter((model) => model.enabled && model.provider === provider)\n .map((model) => {\n const isSelected = model.model === selected ? ' selected' : '';\n return '<option value=\"' + model.model + '\"' + isSelected + '>' + model.label + ' (' + model.model + ')</option>';\n })\n .join('');\n }\n\n function reasoningSelect(value, slot) {\n return (\n '<select data-slot-reasoning=\"' +\n slot +\n '\">' +\n reasoningOptions\n .map((option) => {\n const selected = option === value ? ' selected' : '';\n return '<option value=\"' + option + '\"' + selected + '>' + option + '</option>';\n })\n .join('') +\n '</select>'\n );\n }\n\n function refreshSlotModelOptions(slot) {\n if (!currentConfig) {\n return;\n }\n\n const providerSelect = document.querySelector('[data-slot-provider=\"' + slot + '\"]');\n const modelSelect = document.querySelector('[data-slot-model=\"' + slot + '\"]');\n if (!providerSelect || !modelSelect) {\n return;\n }\n\n const resolved = currentConfig.slots[slot];\n const provider = providerSelect.value;\n modelSelect.innerHTML = modelOptions(currentConfig.models, provider, resolved.model);\n\n if (!modelSelect.value) {\n const fallbackModel = currentConfig.models.find((model) => model.enabled && model.provider === provider);\n if (fallbackModel) {\n modelSelect.value = fallbackModel.model;\n }\n }\n\n const endpointEl = document.querySelector('[data-slot-endpoint=\"' + slot + '\"]');\n if (endpointEl) {\n endpointEl.textContent = currentConfig.providers[provider]?.endpoint || 'No provider config';\n }\n }\n\n function renderConfig(config) {\n currentConfig = config;\n providerConfigPathEl.textContent = config.providerConfigPath;\n modelListPathEl.textContent = config.modelListPath;\n scopeConfigPathEl.textContent = config.scopeConfigPath;\n\n slotGridEl.innerHTML = slots.map((slot) => {\n const resolved = config.slots[slot];\n return (\n '<div class=\"slot-card\">' +\n '<div class=\"toolbar\" style=\"justify-content:space-between;\">' +\n '<h3>' + slot + '</h3>' +\n '<span class=\"pill\">' +\n (resolved.providerType ?? 'unconfigured') +\n (resolved.fallbacks.length > 0 ? ' · +' + resolved.fallbacks.length + ' fallback' + (resolved.fallbacks.length > 1 ? 's' : '') : '') +\n '</span>' +\n '</div>' +\n '<div class=\"row cols-3\">' +\n '<label>Provider<select data-slot-provider=\"' + slot + '\">' +\n providerOptions(config.providers, resolved.provider || '') +\n '</select></label>' +\n '<label>Model<select data-slot-model=\"' + slot + '\"></select></label>' +\n '<label>Thinking' + reasoningSelect(resolved.reasoningEffort, slot) + '</label>' +\n '</div>' +\n '<div class=\"muted\" style=\"margin-top:10px;\">Endpoint: <code data-slot-endpoint=\"' + slot + '\"></code></div>' +\n '</div>'\n );\n }).join('');\n\n for (const slot of slots) {\n refreshSlotModelOptions(slot);\n const providerSelect = document.querySelector('[data-slot-provider=\"' + slot + '\"]');\n if (providerSelect) {\n providerSelect.addEventListener('change', () => refreshSlotModelOptions(slot));\n }\n }\n\n catalogEl.innerHTML = config.models\n .map(\n (model) =>\n '<div class=\"panel\" style=\"padding:12px;\">' +\n '<strong>' + model.label + '</strong>' +\n '<div class=\"muted\"><code>' + model.provider + '</code> · <code>' + model.model + '</code> · default thinking: ' + model.reasoningEffort + '</div>' +\n '</div>',\n )\n .join('');\n }\n\n function payloadPreview(payloadJson) {\n try {\n return JSON.stringify(JSON.parse(payloadJson), null, 2);\n } catch {\n return payloadJson;\n }\n }\n\n async function loadConfig() {\n const scope = encodeURIComponent(scopeInput.value || 'default');\n const response = await fetch('/admin/config?scope=' + scope);\n if (!response.ok) {\n throw new Error(await response.text());\n }\n renderConfig(await response.json());\n }\n\n async function loadScopes() {\n const response = await fetch('/admin/scopes');\n if (!response.ok) {\n throw new Error(await response.text());\n }\n const payload = await response.json();\n renderScopeOptions(payload.scopes || []);\n }\n\n async function saveConfig() {\n const models = {};\n for (const slot of slots) {\n const currentSlot = currentConfig.scopeModels[slot];\n models[slot] = {\n main: {\n provider: document.querySelector('[data-slot-provider=\"' + slot + '\"]')?.value,\n model: document.querySelector('[data-slot-model=\"' + slot + '\"]')?.value,\n reasoningEffort: document.querySelector('[data-slot-reasoning=\"' + slot + '\"]')?.value,\n thinkingDisabled:\n currentSlot?.main?.thinkingDisabled ?? currentConfig.slots[slot]?.thinkingDisabled ?? false,\n },\n fallbacks: currentSlot?.fallbacks ?? [],\n };\n }\n\n const response = await fetch('/admin/config?scope=' + encodeURIComponent(scopeInput.value || 'default'), {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ models }),\n });\n if (!response.ok) {\n throw new Error(await response.text());\n }\n renderConfig(await response.json());\n }\n\n async function loadHistory(append = false) {\n const scope = encodeURIComponent(scopeInput.value || 'default');\n const cursorQuery = append && nextCursor ? '&cursor=' + encodeURIComponent(nextCursor) : '';\n const limit = encodeURIComponent(historyLimitEl.value);\n const response = await fetch('/admin/history?scope=' + scope + '&limit=' + limit + cursorQuery);\n if (!response.ok) {\n throw new Error(await response.text());\n }\n const payload = await response.json();\n nextCursor = payload.nextCursor;\n const rows = payload.items\n .map(\n (item) =>\n '<tr>' +\n '<td>' + item.createdAt + '</td>' +\n '<td>' + item.direction + '</td>' +\n '<td>' + (item.role ?? '') + '</td>' +\n '<td>' + item.slot + '</td>' +\n '<td>' + (item.model ?? '') + '</td>' +\n '<td><pre>' + payloadPreview(item.payloadJson) + '</pre></td>' +\n '</tr>',\n )\n .join('');\n historyBodyEl.innerHTML = append ? historyBodyEl.innerHTML + rows : rows;\n document.getElementById('more-history').disabled = !nextCursor;\n\n const statsResponse = await fetch('/admin/history/stats?scope=' + scope);\n const stats = await statsResponse.json();\n historyStatsEl.textContent = stats.totalMessages + ' stored messages. Retention limit ' + stats.retentionLimit + '.';\n }\n\n async function clearHistory() {\n const scope = encodeURIComponent(scopeInput.value || 'default');\n const response = await fetch('/admin/history?scope=' + scope, { method: 'DELETE' });\n if (!response.ok) {\n throw new Error(await response.text());\n }\n nextCursor = null;\n historyBodyEl.innerHTML = '';\n await loadHistory();\n }\n\n document.getElementById('load-button').addEventListener('click', async () => {\n try {\n setStatus('Loading...');\n nextCursor = null;\n await loadConfig();\n await loadHistory();\n setStatus('Scope loaded.');\n } catch (error) {\n setStatus(error.message, true);\n }\n });\n\n document.getElementById('save-config').addEventListener('click', async () => {\n try {\n setStatus('Saving config...');\n await saveConfig();\n setStatus('Config saved.');\n } catch (error) {\n setStatus(error.message, true);\n }\n });\n\n document.getElementById('refresh-history').addEventListener('click', async () => {\n try {\n setStatus('Refreshing history...');\n nextCursor = null;\n await loadHistory();\n setStatus('History refreshed.');\n } catch (error) {\n setStatus(error.message, true);\n }\n });\n\n document.getElementById('clear-history').addEventListener('click', async () => {\n try {\n setStatus('Clearing history...');\n await clearHistory();\n setStatus('History cleared.');\n } catch (error) {\n setStatus(error.message, true);\n }\n });\n\n document.getElementById('more-history').addEventListener('click', async () => {\n try {\n setStatus('Loading more history...');\n await loadHistory(true);\n setStatus('More history loaded.');\n } catch (error) {\n setStatus(error.message, true);\n }\n });\n\n document.addEventListener('DOMContentLoaded', async () => {\n try {\n await loadScopes();\n await loadConfig();\n await loadHistory();\n setStatus('Ready.');\n } catch (error) {\n setStatus(error.message, true);\n }\n });\n </script>\n </body>\n</html>\n`;\n","import { serve } from '@hono/node-server';\nimport { Hono } from 'hono';\nimport { z } from 'zod';\nimport { DEFAULT_HTTP_PORT, DEFAULT_SERVICE_NAME } from '../constants/defaults.js';\nimport { GatewayService } from '../services/GatewayService.js';\nimport { ADMIN_PAGE_HTML } from './adminPage.js';\n\nconst reasoningEffortSchema = z.enum(['minimal', 'low', 'medium', 'high']);\nconst modelSlotSchema = z.enum(['default', 'sonnet', 'opus', 'haiku', 'subagent']);\nconst selectionSchema = z.object({\n provider: z.string().min(1),\n model: z.string().min(1),\n reasoningEffort: reasoningEffortSchema,\n thinkingDisabled: z.boolean().optional(),\n});\nconst slotConfigSchema = z.object({\n main: selectionSchema,\n fallbacks: z.array(selectionSchema).default([]),\n});\nconst adminConfigUpdateSchema = z.object({\n models: z\n .object({\n default: slotConfigSchema.nullable().optional(),\n sonnet: slotConfigSchema.nullable().optional(),\n opus: slotConfigSchema.nullable().optional(),\n haiku: slotConfigSchema.nullable().optional(),\n subagent: slotConfigSchema.nullable().optional(),\n })\n .optional(),\n});\nconst profileSchema = z.object({\n id: z.string().min(1),\n label: z.string().min(1),\n provider: z.string().min(1),\n model: z.string().min(1),\n endpoint: z.url().nullable(),\n reasoningEffort: reasoningEffortSchema.default('medium'),\n enabled: z.boolean().default(true),\n providerType: z.enum(['chatgpt-codex', 'anthropic-compatible', 'gemini-direct']).nullable().optional(),\n});\n\nexport function createHttpServer(gatewayService = new GatewayService()) {\n const app = new Hono();\n const getScope = (scope?: string) => scope || 'default';\n\n app.get('/health', (c) => c.json({ status: 'healthy', service: DEFAULT_SERVICE_NAME }));\n\n app.get('/status', async (c) => {\n const status = await gatewayService.getStatus();\n return c.json(status);\n });\n\n app.get('/v1/models', async (c) => c.json(await gatewayService.getModels()));\n app.get('/scopes/:scope/status', async (c) => c.json(await gatewayService.getStatus(getScope(c.req.param('scope')))));\n app.get('/scopes/:scope/v1/models', async (c) =>\n c.json(await gatewayService.getModels(getScope(c.req.param('scope')))),\n );\n\n app.post('/v1/messages', async (c) => {\n const body = await c.req.text();\n const response = await gatewayService.forwardClaudeRequest(body, 'default', c.req.raw.headers);\n return new Response(response.body, { status: response.status, headers: response.headers });\n });\n app.post('/scopes/:scope/v1/messages', async (c) => {\n const body = await c.req.text();\n const response = await gatewayService.forwardClaudeRequest(body, getScope(c.req.param('scope')), c.req.raw.headers);\n return new Response(response.body, { status: response.status, headers: response.headers });\n });\n\n app.get(\n '/admin',\n () =>\n new Response(ADMIN_PAGE_HTML, {\n headers: {\n 'content-type': 'text/html; charset=utf-8',\n },\n }),\n );\n app.get('/admin/scopes', async (c) => c.json({ scopes: await gatewayService.listScopes() }));\n app.get('/admin/config', async (c) => {\n const scope = getScope(c.req.query('scope'));\n return c.json(await gatewayService.getAdminConfig(scope));\n });\n app.get('/admin/profiles', async (c) => {\n const scope = getScope(c.req.query('scope'));\n return c.json({ profiles: await gatewayService.listProfiles(scope) });\n });\n app.get('/admin/current-model', async (c) => {\n const scope = getScope(c.req.query('scope'));\n const slot = (c.req.query('slot') as z.infer<typeof modelSlotSchema> | undefined) || 'default';\n return c.json({ profile: await gatewayService.getCurrentModel(scope, slot) });\n });\n app.get('/admin/history', async (c) => {\n const scope = getScope(c.req.query('scope'));\n const limit = z.coerce\n .number()\n .int()\n .positive()\n .max(200)\n .default(50)\n .parse(c.req.query('limit') ?? 50);\n const cursor = c.req.query('cursor') || undefined;\n return c.json(await gatewayService.listHistory(scope, limit, cursor));\n });\n app.get('/admin/history/stats', async (c) => {\n const scope = getScope(c.req.query('scope'));\n return c.json(await gatewayService.getHistoryStats(scope));\n });\n\n app.put('/admin/profiles/:id', async (c) => {\n const payload = profileSchema.parse(await c.req.json());\n const scope = getScope(c.req.query('scope'));\n const result = await gatewayService.upsertProfile(\n { ...payload, id: c.req.param('id'), providerType: payload.providerType ?? null },\n scope,\n );\n return c.json(result);\n });\n\n app.put('/admin/active-profile', async (c) => {\n const scope = getScope(c.req.query('scope'));\n const payload = z\n .object({\n profileId: z.string().min(1),\n slot: modelSlotSchema.default('default'),\n })\n .parse(await c.req.json());\n const result = await gatewayService.setActiveProfile(payload.profileId, scope, payload.slot);\n return c.json(result);\n });\n\n app.put('/admin/current-model', async (c) => {\n const scope = getScope(c.req.query('scope'));\n const payload = z\n .object({\n model: z.string().min(1),\n slot: modelSlotSchema.default('default'),\n })\n .parse(await c.req.json());\n const result = await gatewayService.switchModel(payload.model, scope, payload.slot);\n return c.json(result);\n });\n app.put('/admin/config', async (c) => {\n const scope = getScope(c.req.query('scope'));\n const payload = adminConfigUpdateSchema.parse(await c.req.json());\n return c.json(await gatewayService.updateAdminConfig(payload, scope));\n });\n app.delete('/admin/history', async (c) => {\n const scope = getScope(c.req.query('scope'));\n return c.json(await gatewayService.clearHistory(scope));\n });\n\n return app;\n}\n\nexport async function startHttpServer(port = DEFAULT_HTTP_PORT) {\n const app = createHttpServer();\n return serve({ fetch: app.fetch, port, hostname: '127.0.0.1' });\n}\n","import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { z } from 'zod';\nimport { GatewayService } from '../services/GatewayService.js';\n\nconst DEFAULT_SCOPE = 'default';\nconst DEFAULT_SLOT = 'default';\nconst MODEL_PROXY_SCOPE_ENV = 'MODEL_PROXY_MCP_SCOPE';\nconst MODEL_PROXY_SLOT_ENV = 'MODEL_PROXY_MCP_SLOT';\nconst modelSlotSchema = z.enum(['default', 'sonnet', 'opus', 'haiku', 'subagent']);\n\nexport function createServer(\n gatewayService = new GatewayService(),\n environment: NodeJS.ProcessEnv = process.env,\n): Server {\n const resolveScope = (args?: Record<string, unknown>) => {\n const scope = args?.scope;\n return typeof scope === 'string' && scope.trim() ? scope : environment[MODEL_PROXY_SCOPE_ENV] || DEFAULT_SCOPE;\n };\n const resolveSlot = (args?: Record<string, unknown>) => {\n const slot = typeof args?.slot === 'string' ? args.slot : environment[MODEL_PROXY_SLOT_ENV] || DEFAULT_SLOT;\n return modelSlotSchema.parse(slot);\n };\n\n const server = new Server(\n {\n name: 'model-proxy-mcp',\n version: '0.1.0',\n },\n {\n capabilities: {\n tools: {},\n },\n },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'get_proxy_status',\n description: 'Get the HTTP proxy status, auth status, and active profile.',\n inputSchema: {\n type: 'object',\n properties: {\n scope: { type: 'string' },\n },\n additionalProperties: false,\n },\n },\n {\n name: 'list_profiles',\n description: 'List all configured model proxy profiles.',\n inputSchema: {\n type: 'object',\n properties: {\n scope: { type: 'string' },\n },\n additionalProperties: false,\n },\n },\n {\n name: 'get_active_profile',\n description: 'Get the active model proxy profile.',\n inputSchema: {\n type: 'object',\n properties: {\n scope: { type: 'string' },\n slot: { type: 'string', enum: modelSlotSchema.options },\n },\n additionalProperties: false,\n },\n },\n {\n name: 'get_current_model',\n description: 'Get the currently active model and profile settings.',\n inputSchema: {\n type: 'object',\n properties: {\n scope: { type: 'string' },\n slot: { type: 'string', enum: modelSlotSchema.options },\n },\n additionalProperties: false,\n },\n },\n {\n name: 'set_model_target',\n description: 'Set the scoped slot main target directly by provider, model, and reasoning effort.',\n inputSchema: {\n type: 'object',\n properties: {\n provider: { type: 'string' },\n model: { type: 'string' },\n reasoningEffort: { type: 'string', enum: ['minimal', 'low', 'medium', 'high'] },\n scope: { type: 'string' },\n slot: { type: 'string', enum: modelSlotSchema.options },\n thinkingDisabled: { type: 'boolean' },\n },\n required: ['provider', 'model', 'reasoningEffort'],\n additionalProperties: false,\n },\n },\n {\n name: 'upsert_profile',\n description: 'Create or update a Codex model profile.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n label: { type: 'string' },\n provider: { type: 'string' },\n model: { type: 'string' },\n endpoint: { type: 'string' },\n reasoningEffort: { type: 'string', enum: ['minimal', 'low', 'medium', 'high'] },\n enabled: { type: 'boolean' },\n scope: { type: 'string' },\n },\n required: ['id', 'label', 'model', 'endpoint', 'reasoningEffort', 'enabled'],\n additionalProperties: false,\n },\n },\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n try {\n switch (name) {\n case 'get_proxy_status':\n return textResult(JSON.stringify(await gatewayService.getStatus(resolveScope(args)), null, 2));\n case 'list_profiles':\n return textResult(JSON.stringify(await gatewayService.listProfiles(resolveScope(args)), null, 2));\n case 'get_active_profile':\n return textResult(\n JSON.stringify(await gatewayService.getActiveProfile(resolveScope(args), resolveSlot(args)), null, 2),\n );\n case 'get_current_model':\n return textResult(\n JSON.stringify(await gatewayService.getCurrentModel(resolveScope(args), resolveSlot(args)), null, 2),\n );\n case 'set_model_target': {\n const scope = resolveScope(args);\n const slot = resolveSlot(args);\n const existingConfig = await gatewayService.getAdminConfig(scope);\n return textResult(\n JSON.stringify(\n await gatewayService.updateAdminConfig(\n {\n models: {\n [slot]: {\n main: {\n provider: String(args?.provider),\n model: String(args?.model),\n reasoningEffort: z\n .enum(['minimal', 'low', 'medium', 'high'])\n .parse(String(args?.reasoningEffort)),\n thinkingDisabled: args?.thinkingDisabled === undefined ? false : Boolean(args.thinkingDisabled),\n },\n fallbacks: existingConfig.scopeModels[slot]?.fallbacks ?? [],\n },\n },\n },\n scope,\n ),\n null,\n 2,\n ),\n );\n }\n case 'upsert_profile':\n return textResult(\n JSON.stringify(\n await gatewayService.upsertProfile(\n {\n id: String(args?.id),\n label: String(args?.label),\n provider: String(args?.provider || 'chatgpt-codex'),\n providerType: null,\n model: String(args?.model),\n endpoint: String(args?.endpoint),\n reasoningEffort: String(args?.reasoningEffort) as 'minimal' | 'low' | 'medium' | 'high',\n enabled: Boolean(args?.enabled),\n },\n resolveScope(args),\n ),\n null,\n 2,\n ),\n );\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (error) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n });\n\n return server;\n}\n\nfunction textResult(text: string) {\n return {\n content: [\n {\n type: 'text' as const,\n text,\n },\n ],\n };\n}\n","import type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport type { TransportHandler } from '../types/index.js';\n\nexport class StdioTransportHandler implements TransportHandler {\n private transport: StdioServerTransport | null = null;\n\n constructor(private readonly server: Server) {}\n\n async start(): Promise<void> {\n this.transport = new StdioServerTransport();\n await this.server.connect(this.transport);\n }\n\n async stop(): Promise<void> {\n if (this.transport) {\n await this.transport.close();\n this.transport = null;\n }\n }\n}\n"],"mappings":"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"}
|