import { randomUUID } from 'node:crypto'; import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; import { getProviderAdapter } from './adapters'; import { providerCredentialEnv } from './contract-env'; import { UnsupportedProviderCapabilityError } from './errors'; import { normalizeGatewayBuildOptions, resolveGatewayConfiguration } from './gateway-tools'; import { isRecord } from './json'; import { OMP_SDK_BACKEND_VERSION, OMP_SDK_BUN_VERSION, OMP_SDK_MAX_REQUEST_BYTES, OMP_SDK_PROTOCOL_VERSION, parseOmpSdkSidecarRequest, } from './omp/sdk-protocol'; import type { OmpSdkExecutionContext, OmpSdkSidecarRequest } from './omp/sdk-protocol'; import { normalizeOmpSdkSettings, OMP_AUTH_BROKER_ENV_NAMES, parseExactOmpModelSelector, resolveOmpSdkSettings, } from './omp/sdk-settings'; import { ompSdkEnvironmentPolicy } from './omp/sdk-environment-policy'; import type { ConfiguredOmpSdkSettings } from './omp/sdk-settings'; import { getDefaultProviderId, getProviderRegistryEntry, resolveProviderCommand, supportsProviderCapability, supportsProviderOutputReformatting, } from './provider-registry'; import { runtimeProbeIsAvailable } from './probe-availability'; import type { BuildProviderCommandOptions, CliFeatureOverrides, CommandSpec, GatewayBuildOptions, LevelOverrides, ModelLevel, ModelSpec, ProviderAdapter, StructuredOutputRecoveryAdapter, ProviderCliFeatures, ProviderId, ResolvedGatewayBuildOptions, ReasoningEffort, OmpSdkContainmentRequirement, OmpSdkExecutionIdentity, OmpSdkSemanticIdentity, PreparedEnvironmentPolicy, PreparedPrivateArtifacts, PreparedProviderInvoke, WebSearchAttestation, } from './types'; type UnknownFunction = (...args: readonly unknown[]) => unknown; interface RuntimeProviderSettings { readonly defaultLevel?: ModelLevel; readonly levelOverrides: LevelOverrides; readonly gateway?: GatewayBuildOptions; readonly webSearch?: boolean; readonly trustIsolatedRecoveryProfile?: boolean; } interface RuntimeCommandContext { readonly cliFeatures: CliFeatureOverrides; readonly authEnv: Readonly>; } export interface SingleAgentProviderCommandInput { readonly provider?: string | null; readonly context: string; readonly options?: BuildProviderCommandOptions; } export interface PreparedSingleAgentProviderCommand { readonly adapter: ProviderAdapter; readonly commandSpec: CommandSpec; readonly context: string; readonly options: BuildProviderCommandOptions; readonly cliFeatures: CliFeatureOverrides; readonly configuration: { readonly webSearch: WebSearchAttestation; }; readonly invoke: PreparedProviderInvoke; readonly environmentPolicy?: PreparedEnvironmentPolicy; readonly credentialNames?: readonly string[]; readonly privateArtifacts?: PreparedPrivateArtifacts; readonly executionIdentity?: OmpSdkExecutionIdentity; readonly semanticIdentity?: OmpSdkSemanticIdentity; readonly containmentRequirement?: OmpSdkContainmentRequirement; } export interface RuntimeProviderProbe { readonly available: boolean; readonly helpText: string; readonly versionText: string; readonly capabilities: ProviderCliFeatures; readonly configuration: { readonly webSearch: WebSearchAttestation; }; } interface RuntimeProbeEvidence { readonly available?: boolean; readonly helpText: string; readonly versionText: string; } type MutableModelSpec = { level?: ModelLevel; model?: string | null; reasoningEffort?: ReasoningEffort; }; const MODEL_LEVELS: readonly ModelLevel[] = ['level1', 'level2', 'level3']; const REASONING_EFFORTS: readonly ReasoningEffort[] = ['low', 'medium', 'high', 'xhigh', 'max']; const LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV = 'ZEROSHOT_ISOLATED_PROVIDER_SETTINGS_JSON'; const providerDetectionModule: unknown = require('../../lib/provider-detection'); const ompSdkRuntimeModule: unknown = require('../../scripts/omp/runtime'); const commandExistsFn = moduleFunction(providerDetectionModule, 'commandExists'); const getHelpOutputFn = moduleFunction(providerDetectionModule, 'getHelpOutput'); const getVersionOutputFn = moduleFunction(providerDetectionModule, 'getVersionOutput'); const resolveOmpSdkRuntimeFn = moduleFunction(ompSdkRuntimeModule, 'resolveOmpSdkRuntime'); const resolveOmpSdkContainerRuntimeFn = moduleFunction( ompSdkRuntimeModule, 'resolveOmpSdkContainerRuntime' ); export const resolveOmpTransport = (runtimeSettings?: Record): 'sdk' | 'rpc' => { const settings = runtimeSettings ?? loadRuntimeSettings(); const providerSettings = settings.providerSettings; if (!isRecord(providerSettings)) return 'sdk'; const omp = providerSettings.omp; return isRecord(omp) && omp.transport === 'rpc' ? 'rpc' : 'sdk'; }; export function prepareSingleAgentProviderCommand( input: SingleAgentProviderCommandInput, runtimeSettings?: Record ): PreparedSingleAgentProviderCommand { rejectCallerSuppliedModelProvenance(input); const baseOptions = input.options ?? {}; const settings = runtimeSettings ?? loadRuntimeSettings(); const adapter = adapterForRuntimeInput(input.provider, settings); const ompTransport = adapter.id === 'omp' ? resolveOmpTransport(settings) : undefined; if (ompTransport === 'sdk') { const configuredOmpSettings = resolveOmpSdkSettings(settings); return prepareOmpProviderCommand(input, adapter, baseOptions, configuredOmpSettings); } const providerSettings = runtimeProviderSettings( settings, adapter.id, baseOptions.cwd ?? process.cwd() ); const requestedWebSearch = baseOptions.structuredOutputRecovery ? recoveryWebSearchOption(adapter) : (baseOptions.webSearch ?? providerSettings.webSearch); assertWebSearchDeclared(adapter.id, requestedWebSearch); const cliFeatures = resolveRuntimeCliFeatures( adapter.id, baseOptions.cliFeatures, requestedWebSearch === true, settings ); const authEnv = baseOptions.authEnv ?? resolveRuntimeAuthEnv(adapter.id, settings); const options = buildRuntimeOptions(baseOptions, adapter, providerSettings, { cliFeatures, authEnv, }); return { invoke: preparedInvokeForRegistry(adapter, options), adapter, context: input.context, options, cliFeatures, configuration: { webSearch: webSearchAttestation(options), }, commandSpec: buildRuntimeCommand(adapter, input.context, options), }; } interface OmpSdkRuntimeAssets { readonly bunExecutable: string; readonly bunVersion: string; readonly ompVersion: string; readonly sidecarPath: string; } function prepareOmpProviderCommand( input: SingleAgentProviderCommandInput, adapter: ProviderAdapter, baseOptions: BuildProviderCommandOptions, rawOmpSettings: unknown ): PreparedSingleAgentProviderCommand { const executionContext = ompExecutionContext(baseOptions.executionContext); const normalized = normalizeOmpSdkSettings(rawOmpSettings, { ...(executionContext === undefined ? {} : { executionContext: executionContext === 'benchmark' ? 'docker' : executionContext, }), requireModelConfiguration: true, }); if (executionContext === undefined) { throw new Error( 'options.executionContext is required for OMP SDK preparation and must be "host", "detached", "docker", or "benchmark".' ); } if (baseOptions.resumeSessionId !== undefined || baseOptions.continueSession === true) { throw new UnsupportedProviderCapabilityError( 'omp', 'sessionResume', 'OMP SDK structured runs are always fresh; resume and continue are not supported.' ); } if (baseOptions.structuredOutputRecovery === true) { throw new UnsupportedProviderCapabilityError( 'omp', 'structuredOutputRecovery', 'OMP SDK strict output is produced by the original coding turn and cannot run a recovery turn.' ); } if (baseOptions.mcpConfig !== undefined && baseOptions.mcpConfig.length > 0) { throw new UnsupportedProviderCapabilityError( 'omp', 'mcpServers', 'OMP SDK preparation does not accept caller MCP configuration.' ); } if (baseOptions.webSearch === true) { throw new UnsupportedProviderCapabilityError( 'omp', 'webSearch', 'OMP SDK preparation uses the configured closed coding-tool allowlist and does not enable web search.' ); } if (baseOptions.authEnv !== undefined && Object.keys(baseOptions.authEnv).length > 0) { throw new Error( 'options.authEnv is not accepted for OMP SDK preparation; declare credential environment variable names in providerSettings.omp.auth.' ); } const configured = normalized as Readonly; const level = baseOptions.modelSpec?.level ?? configured.defaultLevel; const levelOverride = configured.levelOverrides[level]; const requestedModel = baseOptions.modelSpec?.model; if (requestedModel === null) { throw new Error('options.modelSpec.model must be an exact OMP provider/model selector.'); } if ( MODEL_LEVELS.indexOf(level) < MODEL_LEVELS.indexOf(configured.minLevel) || MODEL_LEVELS.indexOf(level) > MODEL_LEVELS.indexOf(configured.maxLevel) ) { throw new Error( `options.modelSpec.level must be between providerSettings.omp.minLevel (${configured.minLevel}) and maxLevel (${configured.maxLevel}).` ); } if (requestedModel !== undefined && requestedModel !== levelOverride.model) { throw new Error( `options.modelSpec.model must exactly match providerSettings.omp.levelOverrides.${level}.model.` ); } const modelSelector = requestedModel ?? levelOverride.model; const parsedSelector = parseExactOmpModelSelector(modelSelector); const requestedReasoningEffort = baseOptions.modelSpec?.reasoningEffort; if ( requestedReasoningEffort !== undefined && requestedReasoningEffort !== levelOverride.reasoningEffort ) { throw new Error( `options.modelSpec.reasoningEffort must exactly match providerSettings.omp.levelOverrides.${level}.reasoningEffort.` ); } const reasoningEffort = requestedReasoningEffort ?? levelOverride.reasoningEffort; const output = ompSdkOutputContract(baseOptions); const cwd = path.resolve(baseOptions.cwd ?? process.cwd()); const cliFeatures = adapter.detectCliFeatures('', ''); const options: BuildProviderCommandOptions = { cwd, executionContext, modelSpec: { level, model: modelSelector, reasoningEffort, }, outputFormat: output.mode, ...(output.mode === 'json' ? { jsonSchema: output.schema } : {}), strictSchema: true, cliFeatures, }; const requestInput: OmpSdkSidecarRequest = output.mode === 'json' ? { protocolVersion: OMP_SDK_PROTOCOL_VERSION, runId: randomUUID(), cwd, executionContext, prompt: input.context, modelSelector, reasoningEffort, modelsConfig: configured.modelsConfig, auth: configured.auth, tools: configured.tools, context: '', outputMode: 'json', outputSchema: output.schema, } : { protocolVersion: OMP_SDK_PROTOCOL_VERSION, runId: randomUUID(), cwd, executionContext, prompt: input.context, modelSelector, reasoningEffort, modelsConfig: configured.modelsConfig, auth: configured.auth, tools: configured.tools, context: '', outputMode: 'text', }; const request = parseOmpSdkSidecarRequest(requestInput); const requestText = JSON.stringify(request); if (Buffer.byteLength(requestText, 'utf8') > OMP_SDK_MAX_REQUEST_BYTES) { throw new Error(`OMP SDK request exceeds ${OMP_SDK_MAX_REQUEST_BYTES} bytes.`); } const usesContainerRuntime = executionContext === 'docker' || executionContext === 'benchmark'; const runtime = usesContainerRuntime ? ompSdkContainerRuntimeAssets() : ompSdkRuntimeAssets(); let privateRoot: string | undefined; try { privateRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'zeroshot-omp-sdk-request-')); fs.chmodSync(privateRoot, 0o700); const requestPath = path.join(privateRoot, 'request.json'); fs.writeFileSync(requestPath, requestText, { flag: 'wx', mode: 0o600 }); fs.chmodSync(requestPath, 0o600); const credentialNames = ompSdkCredentialNames(configured, parsedSelector.provider); const invoke = { lane: 'spawn', parser: 'omp-sdk-ndjson', ptyEligible: false, strictTerminal: true, } as const; return { context: input.context, adapter, options, cliFeatures, configuration: { webSearch: { requested: false, effective: false }, }, invoke, environmentPolicy: ompSdkEnvironmentPolicy(), credentialNames, privateArtifacts: { root: privateRoot, requestPath, owned: true, }, executionIdentity: { backend: 'omp-sdk', backendVersion: OMP_SDK_BACKEND_VERSION, runtime: { name: 'bun', version: OMP_SDK_BUN_VERSION, }, transport: 'sdk', }, semanticIdentity: { requestedModelSelector: modelSelector, reasoningEffort, provider: parsedSelector.provider, }, containmentRequirement: { mode: usesContainerRuntime ? 'container' : 'host-process-tree', required: true, }, commandSpec: { binary: runtime.bunExecutable, args: [runtime.sidecarPath, requestPath], env: {}, cwd, cleanup: [privateRoot], cleanupMetadata: [ { kind: 'temp-directory', provider: 'omp', path: privateRoot, reason: 'sdk-private-root', }, ], warnings: [], redactions: credentialNames.map((key) => ({ kind: 'env' as const, key })), invocation: { lane: 'spawn', pty: false, protocol: 'omp-sdk-v1', }, }, }; } catch (error) { if (privateRoot !== undefined) { fs.rmSync(privateRoot, { recursive: true, force: true }); } throw error; } } function ompExecutionContext( value: BuildProviderCommandOptions['executionContext'] ): OmpSdkExecutionContext | undefined { if (value === undefined) return undefined; if (value === 'host' || value === 'detached' || value === 'docker' || value === 'benchmark') { return value; } throw new Error('options.executionContext must be "host", "detached", "docker", or "benchmark".'); } function ompSdkOutputContract( options: BuildProviderCommandOptions ): | { readonly mode: 'json'; readonly schema: boolean | Readonly> } | { readonly mode: 'text' } { const hasSchema = options.jsonSchema !== undefined && options.jsonSchema !== null; if (hasSchema) { if (options.outputFormat !== undefined && options.outputFormat !== 'json') { throw new Error('OMP SDK caller schemas require options.outputFormat "json".'); } if (options.strictSchema === false) { throw new Error('OMP SDK caller schemas require strict schema enforcement.'); } if (typeof options.jsonSchema !== 'boolean' && !isRecord(options.jsonSchema)) { throw new Error('options.jsonSchema must be a boolean or JSON Schema object.'); } return { mode: 'json', schema: options.jsonSchema }; } if (options.outputFormat !== undefined && options.outputFormat !== 'text') { throw new Error( 'OMP SDK output without a caller schema must use options.outputFormat "text" and the host-owned strict text envelope.' ); } if (options.strictSchema === false) { throw new Error('OMP SDK text output always uses the host-owned strict text envelope.'); } return { mode: 'text' }; } function ompSdkCredentialNames( settings: Readonly, provider: string ): readonly string[] { if (settings.auth.mode === 'environment') { const credential = settings.auth.credentials[provider]; if (credential === undefined) { throw new Error(`No OMP environment credential reference is declared for ${provider}.`); } return Object.freeze([credential.env]); } if (settings.auth.mode === 'broker') { return Object.freeze( [OMP_AUTH_BROKER_ENV_NAMES.token, OMP_AUTH_BROKER_ENV_NAMES.url].sort((left, right) => left.localeCompare(right, 'en') ) ); } return Object.freeze([]); } function requiredStringValue(value: unknown, field: string): string { if (typeof value !== 'string' || value.length === 0) { throw new Error(`${field} must be a non-empty string.`); } return value; } function ompSdkRuntimeAssets(): OmpSdkRuntimeAssets { return validatedOmpSdkRuntime(resolveOmpSdkRuntimeFn()); } function ompSdkContainerRuntimeAssets(): OmpSdkRuntimeAssets { return validatedOmpSdkRuntime(resolveOmpSdkContainerRuntimeFn()); } function validatedOmpSdkRuntime(value: unknown): OmpSdkRuntimeAssets { if (!isRecord(value)) throw new Error('Pinned OMP SDK runtime resolver returned invalid evidence.'); const runtime = { bunExecutable: requiredStringValue(value.bunExecutable, 'ompSdkRuntime.bunExecutable'), bunVersion: requiredStringValue(value.bunVersion, 'ompSdkRuntime.bunVersion'), ompVersion: requiredStringValue(value.ompVersion, 'ompSdkRuntime.ompVersion'), sidecarPath: requiredStringValue(value.sidecarPath, 'ompSdkRuntime.sidecarPath'), }; if ( runtime.bunVersion !== OMP_SDK_BUN_VERSION || runtime.ompVersion !== OMP_SDK_BACKEND_VERSION ) { throw new Error('Pinned OMP SDK runtime identity does not match the sidecar protocol.'); } return runtime; } function preparedInvokeForRegistry( adapter: ProviderAdapter, options: BuildProviderCommandOptions ): PreparedProviderInvoke { const invoke = getProviderRegistryEntry(adapter.id).invoke; if (invoke.lane === 'acp-stdio') { return { lane: 'acp-stdio', parser: 'acp', ptyEligible: false, strictTerminal: false, }; } if (invoke.lane === 'rpc-stdio') { return { lane: 'rpc-stdio', parser: 'provider', ptyEligible: false, strictTerminal: false, }; } return { lane: 'spawn', parser: 'provider', ptyEligible: !(adapter.id === 'claude' && Boolean(options.jsonSchema)), strictTerminal: false, }; } function buildRuntimeCommand( adapter: ProviderAdapter, context: string, options: BuildProviderCommandOptions ): CommandSpec { if (options.structuredOutputRecovery !== true) { return adapter.buildCommand(context, options); } if (!supportsProviderOutputReformatting(adapter.id)) { throw new UnsupportedProviderCapabilityError( adapter.id, 'structuredOutputRecovery', `Provider ${adapter.id} does not advertise structured-output recovery.` ); } const recoveryAdapter = adapter as ProviderAdapter & Partial; if (typeof recoveryAdapter.buildStructuredOutputRecoveryCommand !== 'function') { throw new UnsupportedProviderCapabilityError( adapter.id, 'structuredOutputRecovery', `Provider ${adapter.id} advertises structured output without a recovery adapter. Upgrade Zeroshot before retrying.` ); } return recoveryAdapter.buildStructuredOutputRecoveryCommand(context, options); } export function detectRuntimeProviderCliFeatures( provider: string, runtimeSettings?: Record ): ProviderCliFeatures { return probeRuntimeProviderCli(provider, undefined, runtimeSettings).capabilities; } function resolveRuntimeCliFeatures( provider: ProviderId, overrides: CliFeatureOverrides | undefined, webSearchRequested: boolean, runtimeSettings: Record ): CliFeatureOverrides { if (provider === 'gateway') { const detected = detectRuntimeProviderCliFeatures(provider, runtimeSettings); return { ...detected, ...overrides, supportsBundledRunner: true, supportsWebSearch: false, }; } if (provider === 'pi') { const detected = detectRuntimeProviderCliFeatures(provider, runtimeSettings); return overrides === undefined ? detected : mergePiFailClosedCliFeatures(detected, overrides); } if (getProviderRegistryEntry(provider).invoke.lane === 'acp-stdio') { const detected = detectRuntimeProviderCliFeatures(provider, runtimeSettings); if (overrides === undefined) return detected; return mergeAcpFailClosedCliFeatures(detected, overrides); } if (overrides === undefined) return detectRuntimeProviderCliFeatures(provider, runtimeSettings); if (!webSearchRequested) return overrides; const detected = detectRuntimeProviderCliFeatures(provider, runtimeSettings); return { ...overrides, supportsResume: 'supportsResume' in detected && detected.supportsResume === true && overrides.supportsResume !== false, supportsWebSearch: detected.supportsWebSearch === true && overrides.supportsWebSearch !== false, }; } function mergePiFailClosedCliFeatures( detected: ProviderCliFeatures, overrides: CliFeatureOverrides ): CliFeatureOverrides { return Object.fromEntries( Object.entries(detected).map(([field, value]) => [ field, typeof value === 'boolean' ? value && Reflect.get(overrides, field) !== false : value, ]) ); } function mergeAcpFailClosedCliFeatures( detected: ProviderCliFeatures, overrides: CliFeatureOverrides ): CliFeatureOverrides { if (!('supportsAcpStdio' in detected)) return overrides; return { ...detected, ...overrides, supportsAcpStdio: detected.supportsAcpStdio && overrides.supportsAcpStdio !== false, supportsPromptImages: detected.supportsPromptImages && overrides.supportsPromptImages !== false, supportsLoadSession: detected.supportsLoadSession && overrides.supportsLoadSession !== false, supportsSessionCancel: detected.supportsSessionCancel && overrides.supportsSessionCancel !== false, supportsSessionSetModel: detected.supportsSessionSetModel && overrides.supportsSessionSetModel !== false, supportsSessionSetMode: detected.supportsSessionSetMode && overrides.supportsSessionSetMode !== false, supportsRemoteTransport: false, supportsCustomTransport: false, supportsPermissionRequests: false, supportsFsTools: false, supportsTerminalTools: false, }; } export function probeRuntimeProviderCli( provider: string, evidence?: RuntimeProbeEvidence, runtimeSettings?: Record, context: { readonly executionContext?: OmpSdkExecutionContext } = {} ): RuntimeProviderProbe { const adapter = getProviderAdapter(provider); if (adapter.id === 'gateway') { return probeGatewayProvider(adapter, runtimeSettings); } const registryEntry = getProviderRegistryEntry(adapter.id); const settings = runtimeSettings ?? loadRuntimeSettings(); if (adapter.id === 'omp' && resolveOmpTransport(settings) === 'sdk') { const capabilities = adapter.detectCliFeatures('', ''); try { const executionContext = ompExecutionContext(context.executionContext); const runtime = executionContext === 'docker' || executionContext === 'benchmark' ? ompSdkContainerRuntimeAssets() : ompSdkRuntimeAssets(); return { available: true, helpText: 'Pinned bundled OMP SDK sidecar', versionText: `omp-sdk ${runtime.ompVersion}; bun ${runtime.bunVersion}`, capabilities, configuration: { webSearch: { requested: false, effective: false }, }, }; } catch { return { available: false, helpText: '', versionText: '', capabilities, configuration: { webSearch: { requested: false, effective: false }, }, }; } } const requested = registryEntry.settingsFields.includes('webSearch') ? runtimeProviderSettings(settings, adapter.id, process.cwd()).webSearch === true : false; const helpCommand = resolveProviderCommand(adapter.id); const commandAvailable = evidence === undefined ? booleanResult(commandExistsFn(helpCommand.command)) : evidence.available !== false; if (!commandAvailable) { const capabilities = attestedCliFeatures(adapter, '', ''); return { available: false, helpText: '', versionText: '', capabilities, configuration: { webSearch: webSearchAttestation({ webSearch: requested, cliFeatures: capabilities }), }, }; } const helpText = evidence?.helpText ?? (adapter.id === 'pi' ? '' : stringResult(getHelpOutputFn(helpCommand.command, helpCommand.args)).trim()); const versionText = evidence?.versionText ?? stringResult( getVersionOutputFn( helpCommand.command, registryEntry.capabilities.webSearch === true ? [] : helpCommand.args ) ).trim(); const capabilities = attestedCliFeatures(adapter, helpText, versionText); return { available: runtimeProbeIsAvailable( registryEntry.availabilityProbe, evidence?.available, helpText, versionText, capabilities ), helpText, versionText, capabilities, configuration: { webSearch: webSearchAttestation({ webSearch: requested, cliFeatures: capabilities }), }, }; } function buildRuntimeOptions( baseOptions: BuildProviderCommandOptions, adapter: ProviderAdapter, providerSettings: RuntimeProviderSettings, runtime: RuntimeCommandContext ): BuildProviderCommandOptions { const modelSpec = resolveRuntimeModelSpec(adapter, baseOptions.modelSpec, providerSettings); const gateway = resolveRuntimeGatewayOptions( adapter.id, baseOptions, providerSettings, modelSpec ); const webSearch = baseOptions.structuredOutputRecovery ? recoveryWebSearchOption(adapter) : (baseOptions.webSearch ?? providerSettings.webSearch); assertWebSearchDeclared(adapter.id, webSearch); const baseResolved = { ...baseOptions, modelSpec, ...(gateway === undefined ? {} : { gateway }), ...(webSearch === undefined ? {} : { webSearch }), cliFeatures: runtime.cliFeatures, }; const resolved = { ...baseResolved }; delete resolved.trustIsolatedCodexProfile; if (baseOptions.structuredOutputRecovery && adapter.id === 'codex') { resolved.trustIsolatedCodexProfile = providerSettings.trustIsolatedRecoveryProfile === true; } if (baseOptions.structuredOutputRecovery) { delete resolved.resumeSessionId; delete resolved.continueSession; delete resolved.mcpConfig; resolved.autoApprove = false; if (recoveryWebSearchOption(adapter) === undefined) delete resolved.webSearch; else resolved.webSearch = false; } if (baseOptions.jsonSchema && !supportsProviderCapability(adapter.id, 'jsonSchema')) { if (!shouldIncludeAuthEnv(baseOptions, runtime.authEnv)) { return { ...resolved, strictSchema: false }; } return { ...resolved, authEnv: runtime.authEnv, strictSchema: false }; } if (!shouldIncludeAuthEnv(baseOptions, runtime.authEnv)) return resolved; return { ...resolved, authEnv: runtime.authEnv }; } function recoveryWebSearchOption(adapter: ProviderAdapter): false | undefined { return getProviderRegistryEntry(adapter.id).capabilities.webSearch === false ? undefined : false; } function resolveRuntimeGatewayOptions( provider: ProviderId, baseOptions: BuildProviderCommandOptions, providerSettings: RuntimeProviderSettings, modelSpec: ModelSpec ): ResolvedGatewayBuildOptions | undefined { if (provider !== 'gateway') return undefined; const cwd = baseOptions.cwd ?? process.cwd(); const settingsGateway = providerSettings.gateway ?? {}; const requestGateway = baseOptions.gateway ?? {}; const apiKey = resolveGatewayApiKey(requestGateway, settingsGateway); const mergedHeaders = requestGateway.headers === undefined ? settingsGateway.headers : { ...(settingsGateway.headers ?? {}), ...requestGateway.headers }; const mergedGateway: GatewayBuildOptions = { ...((requestGateway.protocol ?? settingsGateway.protocol) ? { protocol: requestGateway.protocol ?? settingsGateway.protocol } : {}), ...((requestGateway.baseUrl ?? settingsGateway.baseUrl) ? { baseUrl: requestGateway.baseUrl ?? settingsGateway.baseUrl } : {}), ...(apiKey === undefined ? {} : { apiKey }), ...(mergedHeaders === undefined ? {} : { headers: mergedHeaders }), model: requestGateway.model ?? modelSpec.model ?? settingsGateway.model ?? null, ...((requestGateway.maxTokens ?? settingsGateway.maxTokens) ? { maxTokens: requestGateway.maxTokens ?? settingsGateway.maxTokens } : {}), ...((requestGateway.toolPolicy ?? settingsGateway.toolPolicy) ? { toolPolicy: requestGateway.toolPolicy ?? settingsGateway.toolPolicy } : {}), }; return resolveGatewayConfiguration(mergedGateway, 'options.gateway', cwd); } function resolveGatewayApiKey( request: GatewayBuildOptions, settings: GatewayBuildOptions ): string | undefined { if (request.apiKeyEnv !== undefined) { throw new Error('options.gateway.apiKeyEnv requires trusted provider settings'); } const requestOwnsTransport = request.protocol !== undefined || request.baseUrl !== undefined || request.headers !== undefined; if ((settings.apiKeyEnv !== undefined || settings.apiKey !== undefined) && requestOwnsTransport) { throw new Error('options.gateway transport cannot override credential settings'); } const direct = request.apiKey ?? settings.apiKey; const environmentName = settings.apiKeyEnv; if (direct !== undefined && environmentName !== undefined) { throw new Error('gateway apiKey and apiKeyEnv are mutually exclusive'); } if (direct !== undefined) return direct; if (environmentName === undefined) return undefined; const value = process.env[environmentName]; if (typeof value !== 'string' || !value.trim()) { throw new Error(`gateway apiKeyEnv requires environment variable ${environmentName}`); } return value; } function shouldIncludeAuthEnv( baseOptions: BuildProviderCommandOptions, authEnv: Readonly> ): boolean { return baseOptions.authEnv !== undefined || Object.keys(authEnv).length > 0; } function resolveRuntimeModelSpec( adapter: ProviderAdapter, explicit: ModelSpec | undefined, providerSettings: RuntimeProviderSettings ): ModelSpec { if (explicit?.model !== undefined) { adapter.validateModelId(explicit.model); return explicit; } const level = explicit?.level ?? providerSettings.defaultLevel ?? adapter.defaultLevel; const resolved = adapter.resolveModelSpec(level, providerSettings.levelOverrides); const modelSpec = modelSpecFromResolved(resolved); if (explicit?.reasoningEffort === undefined) return modelSpec; return { ...modelSpec, reasoningEffort: explicit.reasoningEffort }; } function modelSpecFromResolved(resolved: { readonly level: ModelLevel; readonly model: string | null; readonly reasoningEffort: ReasoningEffort | undefined; }): ModelSpec { const result: MutableModelSpec = { level: resolved.level, model: resolved.model, }; if (resolved.reasoningEffort !== undefined) result.reasoningEffort = resolved.reasoningEffort; return result; } function resolveRuntimeAuthEnv( provider: ProviderId, settings: Record ): Readonly> { if (provider === 'codex') return providerCredentialEnv(provider); if (provider !== 'claude') return {}; const claudeAuthModule: unknown = require('../../lib/settings/claude-auth'); const resolveClaudeAuth = moduleFunction(claudeAuthModule, 'resolveClaudeAuth'); return stringRecordFromUnknown(resolveClaudeAuth(settings), 'resolveClaudeAuth'); } function adapterForRuntimeInput( provider: string | null | undefined, settings: Record ): ProviderAdapter { const configured = provider ?? optionalString(settings.defaultProvider, 'settings.defaultProvider'); return getProviderAdapter(configured ?? getDefaultProviderId()); } function runtimeProviderSettings( settings: Record, provider: ProviderId, cwd: string ): RuntimeProviderSettings { const allSettings = optionalRecord(settings.providerSettings, 'settings.providerSettings'); const providerValue = allSettings?.[provider]; if (providerValue === undefined) return { levelOverrides: {} }; const providerSettings = requiredRecord(providerValue, `settings.providerSettings.${provider}`); const defaultLevel = optionalModelLevel( providerSettings.defaultLevel, `settings.providerSettings.${provider}.defaultLevel` ); const levelOverrides = levelOverridesFromUnknown( providerSettings.levelOverrides, `settings.providerSettings.${provider}.levelOverrides` ); const webSearch = optionalBoolean( providerSettings.webSearch, `settings.providerSettings.${provider}.webSearch` ); const trustIsolatedRecoveryProfile = optionalBoolean( providerSettings.trustIsolatedRecoveryProfile, `settings.providerSettings.${provider}.trustIsolatedRecoveryProfile` ); const gateway = provider === 'gateway' ? normalizeGatewayBuildOptions(providerSettings, 'settings.providerSettings.gateway', cwd) : undefined; const base = { levelOverrides, ...(gateway === undefined ? {} : { gateway }), ...(webSearch === undefined ? {} : { webSearch }), ...(trustIsolatedRecoveryProfile === undefined ? {} : { trustIsolatedRecoveryProfile }), }; return defaultLevel === undefined ? base : { ...base, defaultLevel }; } function probeGatewayProvider( adapter: ProviderAdapter, runtimeSettings?: Record ): RuntimeProviderProbe { const capabilities = attestedCliFeatures(adapter, '', ''); try { const settings = runtimeSettings ?? loadRuntimeSettings(); const providerSettings = runtimeProviderSettings(settings, 'gateway', process.cwd()); resolveRuntimeGatewayOptions('gateway', {}, providerSettings, providerSettings.gateway ?? {}); return { available: true, helpText: 'Bundled gateway runner', versionText: process.version, capabilities, configuration: { webSearch: { requested: false, effective: false }, }, }; } catch { return { available: false, helpText: 'Bundled gateway runner', versionText: process.version, capabilities, configuration: { webSearch: { requested: false, effective: false }, }, }; } } function attestedCliFeatures( adapter: ProviderAdapter, helpText: string, versionText: string ): ProviderCliFeatures { const detected = adapter.detectCliFeatures(helpText, versionText); return { ...detected, supportsWebSearch: getProviderRegistryEntry(adapter.id).capabilities.webSearch === true && detected.supportsWebSearch === true, }; } function webSearchAttestation(options: { readonly webSearch?: boolean; readonly cliFeatures?: CliFeatureOverrides; }): WebSearchAttestation { const requested = options.webSearch === true; return { requested, effective: requested && options.cliFeatures?.supportsWebSearch === true, }; } function assertWebSearchDeclared(provider: ProviderId, requested: boolean | undefined): void { if ( requested === undefined || getProviderRegistryEntry(provider).capabilities.webSearch === true ) { return; } throw new UnsupportedProviderCapabilityError( provider, 'webSearch', `Provider ${provider} does not expose provider-controlled native web search; remove options.webSearch.` ); } function loadRuntimeSettings(): Record { if (Object.prototype.hasOwnProperty.call(process.env, LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV)) { throw new Error( `${LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV} is not a trusted settings channel; use the settings file.` ); } const settingsModule: unknown = require('../../lib/settings'); const loadSettings = moduleFunction(settingsModule, 'loadSettings'); return requiredRecord(loadSettings(), 'loadSettings'); } function rejectCallerSuppliedModelProvenance(input: SingleAgentProviderCommandInput): void { if (Object.prototype.hasOwnProperty.call(input, 'modelSpecSource')) { throw new Error( 'modelSpecSource is not accepted at the child provider boundary; use modelLevel and effective provider settings.' ); } } function moduleFunction(moduleValue: unknown, field: string): UnknownFunction { const record = requiredRecord(moduleValue, 'module'); const value = record[field]; if (isUnknownFunction(value)) return value; throw new Error(`Expected ${field} to be a function.`); } function isUnknownFunction(value: unknown): value is UnknownFunction { return typeof value === 'function'; } function levelOverridesFromUnknown(value: unknown, field: string): LevelOverrides { if (value === undefined) return {}; const record = requiredRecord(value, field); const result: Partial> = {}; for (const level of MODEL_LEVELS) { if (record[level] !== undefined) result[level] = modelSpecFromUnknown(record[level], field); } return result; } function modelSpecFromUnknown(value: unknown, field: string): ModelSpec { const record = requiredRecord(value, field); const result: MutableModelSpec = {}; addModelLevel(result, record.level, `${field}.level`); addModel(result, record.model, `${field}.model`); addReasoningEffort(result, record.reasoningEffort, `${field}.reasoningEffort`); return result; } function addModelLevel(result: MutableModelSpec, value: unknown, field: string): void { const level = optionalModelLevel(value, field); if (level !== undefined) result.level = level; } function addModel(result: MutableModelSpec, value: unknown, field: string): void { if (value === undefined) return; if (value === null || typeof value === 'string') { result.model = value; return; } throw new Error(`${field} must be a string or null.`); } function addReasoningEffort(result: MutableModelSpec, value: unknown, field: string): void { const effort = optionalReasoningEffort(value, field); if (effort !== undefined) result.reasoningEffort = effort; } function optionalBoolean(value: unknown, field: string): boolean | undefined { if (value === undefined) return undefined; if (typeof value === 'boolean') return value; throw new Error(`${field} must be a boolean.`); } function optionalModelLevel(value: unknown, field: string): ModelLevel | undefined { if (value === undefined) return undefined; if (value === 'level1' || value === 'level2' || value === 'level3') return value; throw new Error(`${field} must be one of: ${MODEL_LEVELS.join(', ')}.`); } function optionalReasoningEffort(value: unknown, field: string): ReasoningEffort | undefined { if (value === undefined) return undefined; if ( value === 'low' || value === 'medium' || value === 'high' || value === 'xhigh' || value === 'max' ) { return value; } throw new Error(`${field} must be one of: ${REASONING_EFFORTS.join(', ')}.`); } function optionalString(value: unknown, field: string): string | undefined { if (value === undefined || value === null) return undefined; if (typeof value === 'string') return value; throw new Error(`${field} must be a string.`); } function optionalRecord( value: unknown, field: string ): Readonly> | undefined { if (value === undefined || value === null) return undefined; return requiredRecord(value, field); } function requiredRecord(value: unknown, field: string): Record { if (isRecord(value)) return value; throw new Error(`${field} must be an object.`); } function stringRecordFromUnknown(value: unknown, field: string): Readonly> { if (value === undefined || value === null) return {}; const record = requiredRecord(value, field); const result: Record = {}; for (const [key, item] of Object.entries(record)) { if (typeof item !== 'string') throw new Error(`${field}.${key} must be a string.`); result[key] = item; } return result; } function stringResult(value: unknown): string { if (typeof value === 'string') return value; throw new Error('Provider help output must be a string.'); } function booleanResult(value: unknown): boolean { if (typeof value === 'boolean') return value; throw new Error('Provider availability probe must return a boolean.'); }