import type { AgentConfigRegistry } from '../agents/registry.js'; import { loadStoredAnthropicAuth, loadStoredAnthropicAuthToken, loadStoredOpenAIApiKey, loadStoredOpenAIAuth, loadStoredZaiAuth, } from '../auth/index.js'; import type { Config, ModelConfig, ModelProvider } from '../config/index.js'; import type { ModelTier } from '../models/router.js'; import type { ChatResponseFormat } from '../models/types.js'; interface DelegateRunner { delegate(request: { tier: ModelTier; systemPrompt: string; message: string; maxTokens?: number; responseFormat?: ChatResponseFormat; }): Promise<{ content: string; usage: { inputTokens: number; outputTokens: number }; tier: ModelTier; }>; } interface CredentialState { openaiOAuth: boolean; openaiApiKeyStored: boolean; anthropicApiKeyStored: boolean; anthropicAuthTokenStored: boolean; zaiStored: boolean; } export interface CouncilPreflightOptions { config: Config; registry: AgentConfigRegistry; delegateRunner: DelegateRunner; activeTier?: ModelTier; includeLiveProbe?: boolean; credentialState?: CredentialState; } interface TierConfigResolution { modelConfig: ModelConfig; fellBackToDefault: boolean; } interface AuthResolution { mode: string; source: string; note?: string; } const DEFAULT_ENDPOINTS: Partial> = { openai: 'https://api.openai.com/v1', openrouter: 'https://openrouter.ai/api/v1', vercel: 'https://ai-gateway.vercel.sh/v1', zhipuai: 'https://api.z.ai/api/paas/v4', xai: 'https://api.x.ai/v1', minimax: 'https://api.minimax.io/v1', moonshot: 'https://api.moonshot.cn/v1', ollama: 'http://localhost:11434', llamacpp: 'http://localhost:8080', }; function getCredentialStateFromSystem(): CredentialState { return { openaiOAuth: Boolean(loadStoredOpenAIAuth()), openaiApiKeyStored: Boolean(loadStoredOpenAIApiKey()), anthropicApiKeyStored: Boolean(loadStoredAnthropicAuth()), anthropicAuthTokenStored: Boolean(loadStoredAnthropicAuthToken()), zaiStored: Boolean(loadStoredZaiAuth()), }; } function getEffectiveAuthMode(cfg: ModelConfig): 'auto' | 'api_key' | 'oauth' { if (cfg.auth_mode) { return cfg.auth_mode; } if (cfg.use_oauth) { return 'oauth'; } return 'auto'; } function resolveTierConfig(config: Config, tier: ModelTier): TierConfigResolution { if (tier === 'default') { return { modelConfig: config.models.default, fellBackToDefault: false }; } const direct = config.models[tier]; if (direct) { return { modelConfig: direct, fellBackToDefault: false }; } return { modelConfig: config.models.default, fellBackToDefault: true }; } function firstTruthySource(sources: Array<[boolean, string]>): string { for (const [present, label] of sources) { if (present) { return label; } } return 'missing'; } function resolveAuth(cfg: ModelConfig, credentialState: CredentialState): AuthResolution { if (cfg.provider === 'zhipuai') { const source = firstTruthySource([ [Boolean(cfg.api_key?.trim()), 'config.api_key'], [Boolean(cfg.auth_token?.trim()), 'config.auth_token'], [Boolean(process.env.ZAI_API_KEY?.trim()), 'env:ZAI_API_KEY'], [Boolean(process.env.ZHIPUAI_API_KEY?.trim()), 'env:ZHIPUAI_API_KEY'], [Boolean(process.env.ZHIPUAI_AUTH_TOKEN?.trim()), 'env:ZHIPUAI_AUTH_TOKEN'], [credentialState.zaiStored, 'auth.json:zai'], ]); const note = cfg.use_oauth || cfg.auth_mode === 'oauth' ? 'use_oauth/auth_mode=oauth is ignored for zhipuai' : undefined; return { mode: 'bearer_credential', source, note, }; } if (cfg.provider === 'openai') { const authMode = getEffectiveAuthMode(cfg); const apiSource = firstTruthySource([ [Boolean(cfg.api_keys && cfg.api_keys.length > 0), 'config.api_keys'], [Boolean(cfg.api_key?.trim()), 'config.api_key'], [Boolean(process.env.OPENAI_API_KEY?.trim()), 'env:OPENAI_API_KEY'], [credentialState.openaiApiKeyStored, 'auth.json:openai.api_key'], ]); const oauthSource = credentialState.openaiOAuth ? 'auth.json:openai.oauth' : 'missing'; if (authMode === 'oauth') { return { mode: 'oauth', source: oauthSource }; } if (authMode === 'api_key') { return { mode: 'api_key', source: apiSource }; } if (apiSource !== 'missing') { return { mode: 'auto->api_key', source: apiSource }; } return { mode: 'auto->oauth', source: oauthSource }; } if (cfg.provider === 'anthropic') { const authMode = getEffectiveAuthMode(cfg); const apiSource = firstTruthySource([ [Boolean(cfg.api_keys && cfg.api_keys.length > 0), 'config.api_keys'], [Boolean(cfg.api_key?.trim()), 'config.api_key'], [Boolean(process.env.ANTHROPIC_API_KEY?.trim()), 'env:ANTHROPIC_API_KEY'], [credentialState.anthropicApiKeyStored, 'auth.json:anthropic.api_key'], ]); const oauthSource = firstTruthySource([ [Boolean(cfg.auth_token?.trim()), 'config.auth_token'], [Boolean(process.env.ANTHROPIC_AUTH_TOKEN?.trim()), 'env:ANTHROPIC_AUTH_TOKEN'], [credentialState.anthropicAuthTokenStored, 'auth.json:anthropic.auth_token'], ]); if (authMode === 'oauth') { return { mode: 'oauth', source: oauthSource }; } if (authMode === 'api_key') { return { mode: 'api_key', source: apiSource }; } if (apiSource !== 'missing') { return { mode: 'auto->api_key', source: apiSource }; } return { mode: 'auto->oauth', source: oauthSource }; } if (cfg.provider === 'gemini') { const source = firstTruthySource([ [Boolean(cfg.api_key?.trim()), 'config.api_key'], [Boolean(process.env.GEMINI_API_KEY?.trim()), 'env:GEMINI_API_KEY'], [Boolean(process.env.GOOGLE_API_KEY?.trim()), 'env:GOOGLE_API_KEY'], ]); return { mode: 'api_key', source }; } if (cfg.provider === 'bedrock') { const source = firstTruthySource([ [Boolean(cfg.api_key?.trim() && cfg.auth_token?.trim()), 'config.api_key+auth_token'], [Boolean(process.env.AWS_ACCESS_KEY_ID?.trim() && process.env.AWS_SECRET_ACCESS_KEY?.trim()), 'env:AWS_ACCESS_KEY_ID+AWS_SECRET_ACCESS_KEY'], ]); return { mode: 'aws_credentials', source }; } if (cfg.provider === 'ollama' || cfg.provider === 'llamacpp' || cfg.provider === 'synthetic') { return { mode: 'local', source: 'none' }; } const source = firstTruthySource([ [Boolean(cfg.api_keys && cfg.api_keys.length > 0), 'config.api_keys'], [Boolean(cfg.api_key?.trim()), 'config.api_key'], ]); return { mode: 'api_key', source }; } function resolveEndpoint(cfg: ModelConfig): string { if (cfg.endpoint?.trim()) { return cfg.endpoint.trim(); } return DEFAULT_ENDPOINTS[cfg.provider] ?? '(provider default)'; } function normalizeProbeError(error: unknown): string { if (error instanceof Error) { return error.message; } return String(error); } function isPreflightRequest(task: string): boolean { return task.trim().toLowerCase() === 'preflight'; } export function shouldRunCouncilPreflight(task: string): boolean { return isPreflightRequest(task); } export async function buildCouncilPreflightReport(options: CouncilPreflightOptions): Promise { const { config, registry, delegateRunner } = options; const councils = config.councils; const credentialState = options.credentialState ?? getCredentialStateFromSystem(); const roles = [ { role: 'D.arbiter', agent: councils.groups.D.arbiter_agent, tierOverride: councils.groups.D.model_tier }, { role: 'D.freethinker', agent: councils.groups.D.freethinker_agent, tierOverride: councils.groups.D.model_tier }, ...(councils.groups.D.grounder_agent ? [{ role: 'D.grounder', agent: councils.groups.D.grounder_agent, tierOverride: councils.groups.D.model_tier }] : []), ...(councils.groups.D.writer_agent ? [{ role: 'D.writer', agent: councils.groups.D.writer_agent, tierOverride: councils.groups.D.model_tier }] : []), { role: 'P.arbiter', agent: councils.groups.P.arbiter_agent, tierOverride: councils.groups.P.model_tier }, { role: 'P.freethinker', agent: councils.groups.P.freethinker_agent, tierOverride: councils.groups.P.model_tier }, ...(councils.groups.P.grounder_agent ? [{ role: 'P.grounder', agent: councils.groups.P.grounder_agent, tierOverride: councils.groups.P.model_tier }] : []), ...(councils.groups.P.writer_agent ? [{ role: 'P.writer', agent: councils.groups.P.writer_agent, tierOverride: councils.groups.P.model_tier }] : []), { role: 'Meta.arbiter', agent: councils.meta_arbiter_agent, tierOverride: councils.meta_model_tier }, ...(councils.meta_writer_agent ? [{ role: 'Meta.writer', agent: councils.meta_writer_agent, tierOverride: councils.meta_model_tier }] : []), ]; const roleLines: string[] = []; const tiersToProbe = new Set(); for (const role of roles) { const agentConfig = registry.get(role.agent); const agentTier = agentConfig?.modelTier ?? 'default'; const effectiveTier = role.tierOverride ?? agentTier; const { modelConfig, fellBackToDefault } = resolveTierConfig(config, effectiveTier); const modelLabel = `${modelConfig.provider}/${modelConfig.model}`; const missingSuffix = agentConfig ? '' : ' [agent_missing]'; const fallbackSuffix = fellBackToDefault ? ' [tier_unconfigured->default]' : ''; roleLines.push( `- ${role.role}: agent=${role.agent}${missingSuffix} ` + `agent_tier=${agentTier} override_tier=${role.tierOverride ?? 'none'} ` + `effective_tier=${effectiveTier} model=${modelLabel}${fallbackSuffix}`, ); tiersToProbe.add(effectiveTier); } const tierLines: string[] = []; for (const tier of [...tiersToProbe].sort()) { const { modelConfig, fellBackToDefault } = resolveTierConfig(config, tier); const auth = resolveAuth(modelConfig, credentialState); const endpoint = resolveEndpoint(modelConfig); tierLines.push( `- ${tier}: provider=${modelConfig.provider} model=${modelConfig.model} ` + `endpoint=${endpoint} auth_mode=${auth.mode} auth_source=${auth.source}` + `${auth.note ? ` note=${auth.note}` : ''}` + `${fellBackToDefault ? ' fallback=default' : ''}`, ); } const probeLines: string[] = []; if (options.includeLiveProbe ?? true) { const probeResults = await Promise.all( [...tiersToProbe].sort().map(async (tier) => { const startedAt = Date.now(); try { await delegateRunner.delegate({ tier, systemPrompt: 'Return exactly {"ok":true}.', message: 'Return exactly {"ok":true}.', maxTokens: 64, }); return { tier, ok: true, latencyMs: Math.max(0, Date.now() - startedAt), error: '', }; } catch (error) { return { tier, ok: false, latencyMs: Math.max(0, Date.now() - startedAt), error: normalizeProbeError(error), }; } }), ); for (const result of probeResults) { if (result.ok) { probeLines.push(`- ${result.tier}: ok (${result.latencyMs}ms)`); } else { probeLines.push(`- ${result.tier}: failed (${result.latencyMs}ms) ${result.error}`); } } } else { probeLines.push('- skipped'); } const activeTier = options.activeTier ?? 'default'; const activeModel = resolveTierConfig(config, activeTier).modelConfig; return [ '[Council preflight]', `Councils enabled: ${councils.enabled ? 'yes' : 'no'}`, `Active interactive tier: ${activeTier} (${activeModel.provider}/${activeModel.model})`, `Scaffold path: ${councils.scaffold_path?.trim() ? councils.scaffold_path : '(none)'}`, '', 'Role routing:', ...roleLines, '', 'Tier provider/auth:', ...tierLines, '', 'Live tier probes:', ...probeLines, '', 'Path comparison:', '- Interactive TUI messages use the active tier above.', '- Council calls use per-role effective tiers (group override, then agent tier).', ].join('\n'); }