@albinocrabs/o-switcher 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config/schema.ts","../src/config/defaults.ts","../src/config/loader.ts","../src/config/discovery.ts","../src/registry/health.ts","../src/registry/registry.ts","../src/registry/types.ts","../src/mode/detection.ts","../src/audit/logger.ts","../src/errors/taxonomy.ts","../src/errors/corpus.ts","../src/errors/classifier.ts","../src/errors/direct-adapter.ts","../src/errors/heuristic-adapter.ts","../src/retry/backoff.ts","../src/retry/retry-policy.ts","../src/routing/types.ts","../src/routing/events.ts","../src/routing/dual-breaker.ts","../src/routing/circuit-breaker.ts","../src/routing/concurrency-tracker.ts","../src/routing/policy-engine.ts","../src/routing/cooldown.ts","../src/routing/admission.ts","../src/routing/log-subscriber.ts","../src/routing/failover.ts","../src/execution/stream-buffer.ts","../src/execution/stream-stitcher.ts","../src/execution/audit-collector.ts","../src/execution/orchestrator.ts","../src/execution/adapters/plugin-adapter.ts","../src/execution/adapters/server-adapter.ts","../src/execution/adapters/sdk-adapter.ts","../src/execution/adapters/adapter-factory.ts","../src/operator/reload.ts","../src/operator/commands.ts","../src/operator/server-auth.ts","../src/operator/plugin-tools.ts","../src/profiles/store.ts","../src/profiles/watcher.ts","../src/profiles/tools.ts"],"sourcesContent":["/**\n * O-Switcher public API.\n *\n * Routing and execution resilience layer for the OpenCode ecosystem.\n * Re-exports public interfaces from all core modules.\n */\n\nexport * from './config/index.js';\nexport * from './registry/index.js';\nexport * from './mode/index.js';\nexport * from './audit/index.js';\nexport * from './errors/index.js';\nexport * from './retry/index.js';\nexport * from './routing/index.js';\nexport * from './execution/index.js';\nexport * from './operator/index.js';\nexport * from './profiles/index.js';\n","/**\n * Zod 4 schemas for O-Switcher configuration.\n *\n * Defines validation schemas for the switcher configuration subtree\n * within OpenCode's effective merged config (D-04, D-05, D-06).\n * All optional fields have sensible defaults so minimal config works.\n */\n\nimport { z } from 'zod';\nimport {\n DEFAULT_BACKOFF_BASE_MS,\n DEFAULT_BACKOFF_MAX_MS,\n DEFAULT_BACKOFF_MULTIPLIER,\n DEFAULT_BACKOFF_JITTER,\n DEFAULT_RETRY_BUDGET,\n DEFAULT_FAILOVER_BUDGET,\n DEFAULT_ROUTING_WEIGHT_HEALTH,\n DEFAULT_ROUTING_WEIGHT_LATENCY,\n DEFAULT_ROUTING_WEIGHT_FAILURE,\n DEFAULT_ROUTING_WEIGHT_PRIORITY,\n DEFAULT_QUEUE_LIMIT,\n DEFAULT_GLOBAL_CONCURRENCY_LIMIT,\n DEFAULT_BACKPRESSURE_THRESHOLD,\n DEFAULT_CB_FAILURE_THRESHOLD,\n DEFAULT_CB_FAILURE_RATE_THRESHOLD,\n DEFAULT_CB_SLIDING_WINDOW_SIZE,\n DEFAULT_CB_HALF_OPEN_AFTER_MS,\n DEFAULT_CB_HALF_OPEN_MAX_PROBES,\n DEFAULT_CB_SUCCESS_THRESHOLD,\n DEFAULT_MAX_EXPECTED_LATENCY_MS,\n} from './defaults.js';\n\n/**\n * Schema for exponential backoff configuration.\n * All fields have defaults per D-10.\n */\nexport const BackoffConfigSchema = z.object({\n base_ms: z.number().positive().default(DEFAULT_BACKOFF_BASE_MS),\n multiplier: z.number().positive().default(DEFAULT_BACKOFF_MULTIPLIER),\n max_ms: z.number().positive().default(DEFAULT_BACKOFF_MAX_MS),\n jitter: z.enum(['full', 'equal', 'none']).default(DEFAULT_BACKOFF_JITTER),\n});\n\n/**\n * Schema for routing weight configuration.\n * Per D-17: multi-factor scoring weights.\n */\nexport const RoutingWeightsSchema = z.object({\n health: z.number().default(DEFAULT_ROUTING_WEIGHT_HEALTH),\n latency: z.number().default(DEFAULT_ROUTING_WEIGHT_LATENCY),\n failure: z.number().default(DEFAULT_ROUTING_WEIGHT_FAILURE),\n priority: z.number().default(DEFAULT_ROUTING_WEIGHT_PRIORITY),\n});\n\n/**\n * Schema for circuit breaker configuration.\n * Per D-22: dual trigger (consecutive + rate-based).\n * failure_rate_threshold uses gt(0).lt(1) to exclude boundary values\n * (Pitfall 1 from research: 0% or 100% thresholds are nonsensical).\n */\nexport const CircuitBreakerConfigSchema = z.object({\n failure_threshold: z\n .number()\n .int()\n .positive()\n .default(DEFAULT_CB_FAILURE_THRESHOLD),\n failure_rate_threshold: z\n .number()\n .gt(0)\n .lt(1)\n .default(DEFAULT_CB_FAILURE_RATE_THRESHOLD),\n sliding_window_size: z\n .number()\n .int()\n .positive()\n .default(DEFAULT_CB_SLIDING_WINDOW_SIZE),\n half_open_after_ms: z\n .number()\n .positive()\n .default(DEFAULT_CB_HALF_OPEN_AFTER_MS),\n half_open_max_probes: z\n .number()\n .int()\n .positive()\n .default(DEFAULT_CB_HALF_OPEN_MAX_PROBES),\n success_threshold: z\n .number()\n .int()\n .positive()\n .default(DEFAULT_CB_SUCCESS_THRESHOLD),\n});\n\n/**\n * Schema for a single target definition.\n * target_id and provider_id are required; all other fields have defaults.\n * No credential fields -- provider_id is a pointer to OpenCode's auth store (D-13).\n */\nexport const TargetConfigSchema = z.object({\n target_id: z.string().min(1),\n provider_id: z.string().min(1),\n profile: z.string().optional(),\n endpoint_id: z.string().optional(),\n capabilities: z.array(z.string()).default([]),\n enabled: z.boolean().default(true),\n operator_priority: z.number().int().default(0),\n policy_tags: z.array(z.string()).default([]),\n retry_budget: z.number().int().positive().optional(),\n failover_budget: z.number().int().positive().optional(),\n backoff: BackoffConfigSchema.optional(),\n concurrency_limit: z.number().int().positive().optional(),\n circuit_breaker: CircuitBreakerConfigSchema.optional(),\n});\n\n/**\n * Top-level schema for the O-Switcher configuration subtree.\n * Targets are optional — when absent, auto-discovery populates them from OpenCode providers.\n * When provided, at least one target is required (min 1).\n * Shorthand fields `retry` and `timeout` map to retry_budget and max_expected_latency_ms.\n */\nexport const SwitcherConfigSchema = z.object({\n targets: z.array(TargetConfigSchema).min(1).optional(),\n retry: z.number().int().positive().optional(),\n timeout: z.number().positive().optional(),\n retry_budget: z.number().int().positive().default(DEFAULT_RETRY_BUDGET),\n failover_budget: z.number().int().positive().default(DEFAULT_FAILOVER_BUDGET),\n backoff: BackoffConfigSchema.default({\n base_ms: DEFAULT_BACKOFF_BASE_MS,\n multiplier: DEFAULT_BACKOFF_MULTIPLIER,\n max_ms: DEFAULT_BACKOFF_MAX_MS,\n jitter: DEFAULT_BACKOFF_JITTER,\n }),\n deployment_mode_hint: z\n .enum(['plugin-only', 'server-companion', 'sdk-control', 'auto'])\n .default('auto'),\n routing_weights: RoutingWeightsSchema.default({\n health: DEFAULT_ROUTING_WEIGHT_HEALTH,\n latency: DEFAULT_ROUTING_WEIGHT_LATENCY,\n failure: DEFAULT_ROUTING_WEIGHT_FAILURE,\n priority: DEFAULT_ROUTING_WEIGHT_PRIORITY,\n }),\n queue_limit: z.number().int().positive().default(DEFAULT_QUEUE_LIMIT),\n concurrency_limit: z\n .number()\n .int()\n .positive()\n .default(DEFAULT_GLOBAL_CONCURRENCY_LIMIT),\n backpressure_threshold: z\n .number()\n .int()\n .nonnegative()\n .default(DEFAULT_BACKPRESSURE_THRESHOLD),\n circuit_breaker: CircuitBreakerConfigSchema.default({\n failure_threshold: DEFAULT_CB_FAILURE_THRESHOLD,\n failure_rate_threshold: DEFAULT_CB_FAILURE_RATE_THRESHOLD,\n sliding_window_size: DEFAULT_CB_SLIDING_WINDOW_SIZE,\n half_open_after_ms: DEFAULT_CB_HALF_OPEN_AFTER_MS,\n half_open_max_probes: DEFAULT_CB_HALF_OPEN_MAX_PROBES,\n success_threshold: DEFAULT_CB_SUCCESS_THRESHOLD,\n }),\n max_expected_latency_ms: z\n .number()\n .positive()\n .default(DEFAULT_MAX_EXPECTED_LATENCY_MS),\n});\n\n/** Inferred type for a validated backoff configuration. */\nexport type BackoffConfig = z.infer<typeof BackoffConfigSchema>;\n\n/** Inferred type for a validated target configuration. */\nexport type TargetConfig = z.infer<typeof TargetConfigSchema>;\n\n/** Inferred type for a validated switcher configuration. */\nexport type SwitcherConfig = z.infer<typeof SwitcherConfigSchema>;\n\n/** Inferred type for validated routing weights. */\nexport type RoutingWeightsConfig = z.infer<typeof RoutingWeightsSchema>;\n\n/** Inferred type for validated circuit breaker config. */\nexport type CircuitBreakerConfigParsed = z.infer<\n typeof CircuitBreakerConfigSchema\n>;\n","/**\n * Default configuration values for O-Switcher.\n *\n * These constants define sensible defaults for all optional configuration\n * fields, ensuring minimal config works out of the box (D-10).\n */\n\n/** Default maximum retry attempts per request. */\nexport const DEFAULT_RETRY_BUDGET = 3;\n\n/** Default maximum failover attempts per request. */\nexport const DEFAULT_FAILOVER_BUDGET = 2;\n\n/** Default base delay in milliseconds for exponential backoff. */\nexport const DEFAULT_BACKOFF_BASE_MS = 1000;\n\n/** Default multiplier for exponential backoff. */\nexport const DEFAULT_BACKOFF_MULTIPLIER = 2;\n\n/** Default maximum delay in milliseconds for exponential backoff. */\nexport const DEFAULT_BACKOFF_MAX_MS = 30000;\n\n/** Default jitter strategy for exponential backoff. */\nexport const DEFAULT_BACKOFF_JITTER = 'full' as const;\n\n/** Default routing weight for health score factor. */\nexport const DEFAULT_ROUTING_WEIGHT_HEALTH = 1.0;\n\n/** Default routing weight for latency factor. */\nexport const DEFAULT_ROUTING_WEIGHT_LATENCY = 0.5;\n\n/** Default routing weight for failure score factor. */\nexport const DEFAULT_ROUTING_WEIGHT_FAILURE = 0.8;\n\n/** Default routing weight for operator priority factor. */\nexport const DEFAULT_ROUTING_WEIGHT_PRIORITY = 0.3;\n\n/** Default maximum expected latency in ms for normalization. */\nexport const DEFAULT_MAX_EXPECTED_LATENCY_MS = 30000;\n\n/** Default queue limit for admission control. */\nexport const DEFAULT_QUEUE_LIMIT = 100;\n\n/** Default global concurrency limit. */\nexport const DEFAULT_GLOBAL_CONCURRENCY_LIMIT = 10;\n\n/** Default backpressure threshold. */\nexport const DEFAULT_BACKPRESSURE_THRESHOLD = 50;\n\n/** Default circuit breaker consecutive failure threshold. */\nexport const DEFAULT_CB_FAILURE_THRESHOLD = 5;\n\n/** Default circuit breaker failure rate threshold (0-1). */\nexport const DEFAULT_CB_FAILURE_RATE_THRESHOLD = 0.5;\n\n/** Default circuit breaker sliding window size. */\nexport const DEFAULT_CB_SLIDING_WINDOW_SIZE = 10;\n\n/** Default circuit breaker half-open delay in ms. */\nexport const DEFAULT_CB_HALF_OPEN_AFTER_MS = 30000;\n\n/** Default circuit breaker max probes in half-open state. */\nexport const DEFAULT_CB_HALF_OPEN_MAX_PROBES = 1;\n\n/** Default circuit breaker success threshold to close from half-open. */\nexport const DEFAULT_CB_SUCCESS_THRESHOLD = 2;\n\n/** Default retry shorthand value (maps to retry_budget). */\nexport const DEFAULT_RETRY = 3;\n\n/** Default timeout shorthand value in ms (maps to max_expected_latency_ms). */\nexport const DEFAULT_TIMEOUT_MS = 30000;\n","/**\n * Configuration validation with field-path diagnostics.\n *\n * Validates raw configuration input against the SwitcherConfigSchema\n * and returns a frozen, immutable config object on success.\n * On failure, throws ConfigValidationError with structured diagnostics\n * containing field paths, messages, and received values (D-05).\n */\n\nimport { SwitcherConfigSchema } from './schema.js';\nimport type { SwitcherConfig } from './schema.js';\nimport { DEFAULT_RETRY_BUDGET, DEFAULT_MAX_EXPECTED_LATENCY_MS } from './defaults.js';\n\n/** A single diagnostic entry describing a validation failure. */\nexport interface ConfigDiagnostic {\n readonly path: string;\n readonly message: string;\n readonly received: unknown;\n}\n\n/**\n * Error thrown when configuration validation fails.\n * Contains structured diagnostics with field paths and error messages.\n */\nexport class ConfigValidationError extends Error {\n readonly diagnostics: ReadonlyArray<ConfigDiagnostic>;\n\n constructor(diagnostics: ReadonlyArray<ConfigDiagnostic>) {\n const summary = diagnostics\n .map((d) => ` ${d.path}: ${d.message}`)\n .join('\\n');\n super(`Invalid O-Switcher configuration:\\n${summary}`);\n this.name = 'ConfigValidationError';\n this.diagnostics = diagnostics;\n }\n}\n\n/**\n * Validates raw input against the SwitcherConfigSchema.\n *\n * On success, returns a frozen (immutable) SwitcherConfig.\n * On failure, throws ConfigValidationError with structured diagnostics.\n */\nexport const validateConfig = (raw: unknown): SwitcherConfig => {\n const result = SwitcherConfigSchema.safeParse(raw);\n\n if (result.success) {\n const data = { ...result.data };\n\n // Shorthand mapping: retry -> retry_budget (only if retry_budget was not explicitly set)\n if (data.retry !== undefined && data.retry_budget === DEFAULT_RETRY_BUDGET) {\n data.retry_budget = data.retry;\n }\n\n // Shorthand mapping: timeout -> max_expected_latency_ms (only if not explicitly set)\n if (data.timeout !== undefined && data.max_expected_latency_ms === DEFAULT_MAX_EXPECTED_LATENCY_MS) {\n data.max_expected_latency_ms = data.timeout;\n }\n\n // Detect duplicate (provider_id, profile) combinations (D-54)\n // Skip when targets is undefined (auto-discovery will handle it)\n if (data.targets !== undefined) {\n const seen = new Set<string>();\n const duplicateDiagnostics: Array<ConfigDiagnostic> = [];\n for (const target of data.targets) {\n const key = `${target.provider_id}::${target.profile ?? '__default__'}`;\n if (seen.has(key)) {\n duplicateDiagnostics.push({\n path: 'targets',\n message: `Duplicate provider_id + profile combination: ${key}`,\n received: key,\n });\n }\n seen.add(key);\n }\n if (duplicateDiagnostics.length > 0) {\n throw new ConfigValidationError(duplicateDiagnostics);\n }\n }\n\n return Object.freeze(data) as SwitcherConfig;\n }\n\n const diagnostics: ReadonlyArray<ConfigDiagnostic> = result.error.issues.map(\n (issue) => ({\n path: issue.path.join('.'),\n message: issue.message,\n received: 'expected' in issue ? issue.expected : undefined,\n }),\n );\n\n throw new ConfigValidationError(diagnostics);\n};\n","/**\n * Auto-discovery of targets from OpenCode provider configuration.\n *\n * Pure functions: given a provider config map or a ProfileStore, produce arrays\n * of TargetConfig objects with sensible defaults (D-55, D-56, D-71).\n */\n\nimport { TargetConfigSchema } from './schema.js';\nimport type { TargetConfig } from './schema.js';\nimport type { ProfileStore } from '../profiles/types.js';\n\n/**\n * Minimal interface for an OpenCode provider config entry.\n * Only the fields needed for target discovery are required.\n */\nexport interface ProviderConfigLike {\n readonly id?: string;\n readonly name?: string;\n readonly options?: Record<string, unknown>;\n}\n\n/**\n * Discovers targets from OpenCode provider configuration.\n *\n * For each provider entry in the map, creates a TargetConfig with:\n * - target_id = the config key (e.g., \"anthropic\", \"openai\")\n * - provider_id = provider.id if present, otherwise the config key\n * - capabilities = [\"chat\"]\n * - enabled = true\n * - operator_priority = 0\n * - policy_tags = []\n *\n * Skips falsy entries. Returns validated TargetConfig objects.\n */\nexport const discoverTargets = (\n providerConfig: Record<string, ProviderConfigLike>,\n): TargetConfig[] => {\n const targets: TargetConfig[] = [];\n\n for (const [key, value] of Object.entries(providerConfig)) {\n if (!value) continue;\n\n const raw = {\n target_id: key,\n provider_id: value.id ?? key,\n capabilities: ['chat'],\n enabled: true,\n operator_priority: 0,\n policy_tags: [],\n };\n\n const parsed = TargetConfigSchema.parse(raw);\n targets.push(parsed);\n }\n\n return targets;\n};\n\n/**\n * Discovers targets from the O-Switcher profile store (D-71).\n *\n * For each profile entry in the store, creates a TargetConfig with:\n * - target_id = profile.id (e.g., \"openai-1\")\n * - provider_id = profile.provider (e.g., \"openai\")\n * - profile = profile.id (links to profile for credential resolution)\n * - capabilities = [\"chat\"]\n * - enabled = true\n * - operator_priority = 0\n * - policy_tags = []\n *\n * Returns validated TargetConfig objects via TargetConfigSchema.parse().\n */\nexport const discoverTargetsFromProfiles = (\n store: ProfileStore,\n): TargetConfig[] => {\n const targets: TargetConfig[] = [];\n\n for (const entry of Object.values(store)) {\n if (!entry) continue;\n\n const raw = {\n target_id: entry.id,\n provider_id: entry.provider,\n profile: entry.id,\n capabilities: ['chat'],\n enabled: true,\n operator_priority: 0,\n policy_tags: [],\n };\n\n const parsed = TargetConfigSchema.parse(raw);\n targets.push(parsed);\n }\n\n return targets;\n};\n","/**\n * Health score computation using Exponential Moving Average (EMA).\n *\n * Pure functions for updating health scores and latency EMAs.\n * Health score ranges from 0.0 (completely unhealthy) to 1.0 (perfect health).\n */\n\n/** Initial health score for newly registered targets. */\nexport const INITIAL_HEALTH_SCORE = 1.0;\n\n/** Default EMA smoothing factor (alpha). Higher = more reactive to recent observations. */\nexport const DEFAULT_ALPHA = 0.1;\n\n/**\n * Updates health score using EMA formula.\n *\n * Formula: alpha * observation + (1 - alpha) * currentScore\n *\n * @param currentScore - Current health score (0.0 to 1.0)\n * @param observation - 1 for success, 0 for failure\n * @param alpha - EMA smoothing factor (default 0.1)\n * @returns Updated health score\n */\nexport const updateHealthScore = (\n currentScore: number,\n observation: 0 | 1,\n alpha: number = DEFAULT_ALPHA,\n): number => alpha * observation + (1 - alpha) * currentScore;\n\n/**\n * Updates latency EMA using the same EMA formula.\n *\n * @param currentEma - Current latency EMA in milliseconds\n * @param observedMs - Observed latency in milliseconds\n * @param alpha - EMA smoothing factor (default 0.1)\n * @returns Updated latency EMA\n */\nexport const updateLatencyEma = (\n currentEma: number,\n observedMs: number,\n alpha: number = DEFAULT_ALPHA,\n): number => alpha * observedMs + (1 - alpha) * currentEma;\n","/**\n * In-memory target registry.\n *\n * Initialized from validated SwitcherConfig. Single authoritative source\n * of target state during runtime (D-09). All state mutations go through\n * the registry.\n *\n * No credential material stored -- provider_id is a pointer only (D-13).\n */\n\nimport type { SwitcherConfig } from '../config/schema.js';\nimport type { TargetEntry, TargetState, RegistrySnapshot } from './types.js';\nimport {\n INITIAL_HEALTH_SCORE,\n updateHealthScore,\n updateLatencyEma,\n} from './health.js';\n\n/**\n * Target registry managing per-target state.\n *\n * Provides methods for state mutation, health scoring, cooldown management,\n * and read-only snapshot generation.\n */\nexport class TargetRegistry {\n private readonly targets: Map<string, TargetEntry>;\n\n constructor(config: SwitcherConfig) {\n this.targets = new Map(\n (config.targets ?? []).map((t) => [\n t.target_id,\n {\n target_id: t.target_id,\n provider_id: t.provider_id,\n profile: t.profile,\n endpoint_id: t.endpoint_id,\n capabilities: [...t.capabilities],\n enabled: t.enabled,\n state: 'Active' as const,\n health_score: INITIAL_HEALTH_SCORE,\n cooldown_until: null,\n latency_ema_ms: 0,\n failure_score: 0,\n operator_priority: t.operator_priority,\n policy_tags: [...t.policy_tags],\n },\n ]),\n );\n }\n\n /** Returns the target entry for the given id, or undefined if not found. */\n getTarget(id: string): TargetEntry | undefined {\n return this.targets.get(id);\n }\n\n /** Returns a readonly array of all target entries. */\n getAllTargets(): ReadonlyArray<Readonly<TargetEntry>> {\n return [...this.targets.values()];\n }\n\n /**\n * Updates the state of a target.\n * @returns true if the target was found and updated, false otherwise.\n */\n updateState(id: string, newState: TargetState): boolean {\n const target = this.targets.get(id);\n if (!target) {\n return false;\n }\n this.targets.set(id, { ...target, state: newState });\n return true;\n }\n\n /**\n * Records a success (1) or failure (0) observation for a target.\n * Updates health_score via EMA.\n */\n recordObservation(id: string, observation: 0 | 1): void {\n const target = this.targets.get(id);\n if (!target) {\n return;\n }\n const newHealthScore = updateHealthScore(\n target.health_score,\n observation,\n );\n this.targets.set(id, { ...target, health_score: newHealthScore });\n }\n\n /** Sets the cooldown_until timestamp for a target. */\n setCooldown(id: string, untilMs: number): void {\n const target = this.targets.get(id);\n if (!target) {\n return;\n }\n this.targets.set(id, { ...target, cooldown_until: untilMs });\n }\n\n /** Updates the latency EMA for a target. */\n updateLatency(id: string, ms: number): void {\n const target = this.targets.get(id);\n if (!target) {\n return;\n }\n const newLatency = updateLatencyEma(target.latency_ema_ms, ms);\n this.targets.set(id, { ...target, latency_ema_ms: newLatency });\n }\n\n /**\n * Adds a new target entry to the registry.\n * @returns true if added, false if target_id already exists.\n */\n addTarget(entry: TargetEntry): boolean {\n if (this.targets.has(entry.target_id)) {\n return false;\n }\n this.targets.set(entry.target_id, entry);\n return true;\n }\n\n /**\n * Removes a target entry from the registry.\n * @returns true if found and removed, false if not found.\n */\n removeTarget(id: string): boolean {\n return this.targets.delete(id);\n }\n\n /** Returns a deep-frozen snapshot of all targets. */\n getSnapshot(): RegistrySnapshot {\n const snapshot: RegistrySnapshot = {\n targets: [...this.targets.values()].map((t) => ({ ...t })),\n };\n return Object.freeze(snapshot);\n }\n}\n\n/** Factory function to create a registry from validated config. */\nexport const createRegistry = (config: SwitcherConfig): TargetRegistry =>\n new TargetRegistry(config);\n","/**\n * Target registry types.\n *\n * Defines the TargetEntry interface with all FOUN-02 fields,\n * the TargetState enum, and RegistrySnapshot for read-only access.\n *\n * SECURITY: No credential fields (api_key, token, secret, password).\n * provider_id is a pointer to OpenCode's auth store (D-13, SECU-01, SECU-02).\n */\n\n/**\n * All valid states for a target in the registry.\n *\n * - Active: healthy and available for routing\n * - CoolingDown: temporarily unavailable after transient failure\n * - ReauthRequired: authentication failure, awaiting credential refresh\n * - PolicyBlocked: blocked by policy (403), no retry\n * - CircuitOpen: circuit breaker tripped, no requests allowed\n * - CircuitHalfOpen: circuit breaker probing with limited requests\n * - Draining: operator-initiated drain, no new requests\n * - Disabled: operator-disabled or config-disabled\n */\nexport const TARGET_STATES = [\n 'Active',\n 'CoolingDown',\n 'ReauthRequired',\n 'PolicyBlocked',\n 'CircuitOpen',\n 'CircuitHalfOpen',\n 'Draining',\n 'Disabled',\n] as const;\n\n/** Target state type. */\nexport type TargetState = (typeof TARGET_STATES)[number];\n\n/**\n * A single target entry in the registry.\n *\n * Contains all fields per FOUN-02: target_id, provider_id, endpoint_id,\n * capabilities, enabled, state, health_score, cooldown_until, latency_ema_ms,\n * failure_score, operator_priority, policy_tags.\n *\n * NO credential fields -- provider_id maps to OpenCode's credential store.\n */\nexport interface TargetEntry {\n readonly target_id: string;\n readonly provider_id: string;\n readonly profile: string | undefined;\n readonly endpoint_id: string | undefined;\n readonly capabilities: readonly string[];\n readonly enabled: boolean;\n readonly state: TargetState;\n readonly health_score: number;\n readonly cooldown_until: number | null;\n readonly latency_ema_ms: number;\n readonly failure_score: number;\n readonly operator_priority: number;\n readonly policy_tags: readonly string[];\n}\n\n/** Read-only snapshot of the entire registry. */\nexport interface RegistrySnapshot {\n readonly targets: ReadonlyArray<Readonly<TargetEntry>>;\n}\n","/**\n * Deployment mode detection.\n *\n * Determines the active deployment mode from a config hint.\n * When hint is 'auto', defaults to 'plugin-only' (auto-detection\n * logic will be refined in Phase 3 when mode adapters are built).\n *\n * Maps each mode to its signal fidelity and capability set (FOUN-03, FOUN-04).\n */\n\nimport type { DeploymentMode, SignalFidelity, ModeCapabilities } from './types.js';\n\n/**\n * Detects the deployment mode from a configuration hint.\n *\n * If hint is not 'auto', returns the hint directly.\n * If 'auto', defaults to 'plugin-only' (conservative default).\n */\nexport const detectDeploymentMode = (\n hint: 'plugin-only' | 'server-companion' | 'sdk-control' | 'auto',\n): DeploymentMode => {\n if (hint !== 'auto') {\n return hint;\n }\n // Auto-detection defaults to plugin-only (most restrictive / conservative).\n // Refined in Phase 3 when mode adapters provide runtime probing.\n return 'plugin-only';\n};\n\n/**\n * Returns the signal fidelity for a given deployment mode.\n *\n * - plugin-only: 'heuristic' (no raw HTTP status codes)\n * - server-companion / sdk-control: 'direct' (full HTTP access)\n */\nexport const getSignalFidelity = (mode: DeploymentMode): SignalFidelity => {\n if (mode === 'plugin-only') {\n return 'heuristic';\n }\n return 'direct';\n};\n\n/**\n * Returns the full capability map for a deployment mode.\n *\n * plugin-only has no HTTP status, no Retry-After, no operator API.\n * server-companion and sdk-control have all capabilities.\n */\nexport const getModeCapabilities = (mode: DeploymentMode): ModeCapabilities => {\n if (mode === 'plugin-only') {\n return {\n mode,\n signalFidelity: 'heuristic',\n hasHttpStatus: false,\n hasRetryAfterHeader: false,\n hasOperatorApi: false,\n };\n }\n return {\n mode,\n signalFidelity: 'direct',\n hasHttpStatus: true,\n hasRetryAfterHeader: true,\n hasOperatorApi: true,\n };\n};\n","/**\n * Pino-based structured audit logger with credential redaction.\n *\n * Provides logger creation with automatic redaction of secret-pattern\n * fields (SECU-04), child logger creation for per-request correlation IDs,\n * and UUID v4 correlation ID generation.\n */\n\nimport pino from 'pino';\nimport crypto from 'node:crypto';\n\n/**\n * Pino redaction paths for secret-pattern fields.\n *\n * Includes both top-level paths (for direct log object fields)\n * and wildcard paths (for nested objects) to ensure comprehensive\n * credential redaction regardless of nesting depth.\n */\nexport const REDACT_PATHS: readonly string[] = [\n 'api_key',\n 'token',\n 'secret',\n 'password',\n 'authorization',\n 'credential',\n 'credentials',\n '*.api_key',\n '*.token',\n '*.secret',\n '*.password',\n '*.authorization',\n '*.credential',\n '*.credentials',\n];\n\n/** Options for creating an audit logger. */\nexport interface AuditLoggerOptions {\n readonly level?: string;\n readonly destination?: pino.DestinationStream;\n}\n\n/**\n * Creates a pino logger with secret redaction configured.\n *\n * All fields matching REDACT_PATHS patterns are replaced with '[Redacted]'\n * in log output, preventing credential leakage (SECU-04).\n */\nexport const createAuditLogger = (\n options?: AuditLoggerOptions,\n): pino.Logger => {\n const opts: pino.LoggerOptions = {\n level: options?.level ?? 'info',\n redact: {\n paths: [...REDACT_PATHS],\n censor: '[Redacted]',\n },\n };\n\n if (options?.destination) {\n return pino(opts, options.destination);\n }\n\n return pino(opts);\n};\n\n/**\n * Creates a child logger with a request_id binding for correlation.\n *\n * All log entries from the child logger include the request_id field,\n * enabling end-to-end request tracing in the audit trail.\n */\nexport const createRequestLogger = (\n baseLogger: pino.Logger,\n requestId: string,\n): pino.Logger => baseLogger.child({ request_id: requestId });\n\n/**\n * Generates a UUID v4 correlation ID using Node.js crypto.\n *\n * @returns A UUID v4 string suitable for request correlation.\n */\nexport const generateCorrelationId = (): string => crypto.randomUUID();\n","/**\n * Error taxonomy: 10 error classes as a Zod discriminated union.\n *\n * Defines NormalizedSignal (classifier input), ClassificationResult (classifier output),\n * and helper functions for retry decisions and target state transitions.\n *\n * Per D-01, D-02, D-03, ERRC-01.\n */\n\nimport { z } from 'zod';\nimport type { TargetState } from '../registry/types.js';\n\n/**\n * RateLimited: transient rate limit from provider.\n * Retryable with optional Retry-After hint.\n */\nexport const RateLimitedSchema = z.object({\n class: z.literal('RateLimited'),\n retryable: z.literal(true),\n retry_after_ms: z.number().optional(),\n provider_reason: z.string().optional(),\n});\n\n/**\n * QuotaExhausted: billing or quota limit reached.\n * NOT retryable -- target should be disabled.\n */\nexport const QuotaExhaustedSchema = z.object({\n class: z.literal('QuotaExhausted'),\n retryable: z.literal(false),\n provider_reason: z.string().optional(),\n});\n\n/**\n * AuthFailure: invalid or expired credentials.\n * NOT retryable -- at most one recovery attempt (ERRC-06).\n */\nexport const AuthFailureSchema = z.object({\n class: z.literal('AuthFailure'),\n retryable: z.literal(false),\n recovery_attempted: z.boolean().default(false),\n});\n\n/**\n * PermissionFailure: valid credentials but insufficient permissions.\n * NOT retryable (ERRC-07).\n */\nexport const PermissionFailureSchema = z.object({\n class: z.literal('PermissionFailure'),\n retryable: z.literal(false),\n});\n\n/**\n * PolicyFailure: request violates provider policy (bad format, content policy).\n * NOT retryable.\n */\nexport const PolicyFailureSchema = z.object({\n class: z.literal('PolicyFailure'),\n retryable: z.literal(false),\n});\n\n/**\n * RegionRestriction: provider not available in requested region.\n * NOT retryable -- target should be disabled.\n */\nexport const RegionRestrictionSchema = z.object({\n class: z.literal('RegionRestriction'),\n retryable: z.literal(false),\n});\n\n/**\n * ModelUnavailable: requested model not found or not ready.\n * NOT retryable on same target, but eligible for failover to different target.\n */\nexport const ModelUnavailableSchema = z.object({\n class: z.literal('ModelUnavailable'),\n retryable: z.literal(false),\n failover_eligible: z.literal(true),\n});\n\n/**\n * TransientServerFailure: provider internal error (5xx).\n * Retryable with backoff.\n */\nexport const TransientServerFailureSchema = z.object({\n class: z.literal('TransientServerFailure'),\n retryable: z.literal(true),\n http_status: z.number().optional(),\n});\n\n/**\n * TransportFailure: network-level error (timeout, connection refused).\n * Retryable with backoff (ERRC-08).\n */\nexport const TransportFailureSchema = z.object({\n class: z.literal('TransportFailure'),\n retryable: z.literal(true),\n});\n\n/**\n * InterruptedExecution: stream or execution interrupted mid-response.\n * Retryable; may include partial output size for stitching.\n */\nexport const InterruptedExecutionSchema = z.object({\n class: z.literal('InterruptedExecution'),\n retryable: z.literal(true),\n partial_output_bytes: z.number().optional(),\n});\n\n/**\n * Discriminated union of all 10 error classes.\n * The 'class' field is the discriminator.\n */\nexport const ErrorClassSchema = z.discriminatedUnion('class', [\n RateLimitedSchema,\n QuotaExhaustedSchema,\n AuthFailureSchema,\n PermissionFailureSchema,\n PolicyFailureSchema,\n RegionRestrictionSchema,\n ModelUnavailableSchema,\n TransientServerFailureSchema,\n TransportFailureSchema,\n InterruptedExecutionSchema,\n]);\n\n/** Inferred type for any error class variant. */\nexport type ErrorClass = z.infer<typeof ErrorClassSchema>;\n\n/**\n * Normalized signal: the common input format for the classifier.\n *\n * Direct adapters populate http_status and response_body.\n * Heuristic adapters populate error_message and error_type.\n * detection_mode is always set by the adapter (D-02).\n */\nexport interface NormalizedSignal {\n readonly http_status?: number;\n readonly error_type?: string;\n readonly error_message?: string;\n readonly response_body?: unknown;\n readonly detection_mode: 'direct' | 'heuristic';\n readonly provider_id?: string;\n readonly retry_after_ms?: number;\n}\n\n/**\n * Classification result: the classifier output.\n *\n * Contains the error class, detection mode, confidence level,\n * and the raw signal that produced it.\n */\nexport interface ClassificationResult {\n readonly error_class: ErrorClass;\n readonly detection_mode: 'direct' | 'heuristic';\n readonly confidence: 'high' | 'medium' | 'low';\n readonly raw_signal: NormalizedSignal;\n}\n\n/**\n * Checks whether an error class is retryable.\n *\n * @param errorClass - The classified error.\n * @returns true if the error is retryable.\n */\nexport const isRetryable = (errorClass: ErrorClass): boolean =>\n errorClass.retryable;\n\n/**\n * Maps an error class to the target state transition it triggers.\n *\n * Returns null when the error should not cause a target state change\n * (e.g., transient failures that are handled by retry).\n *\n * @param errorClass - The classified error.\n * @returns The new target state, or null if no transition.\n */\nexport const getTargetStateTransition = (\n errorClass: ErrorClass,\n): TargetState | null => {\n switch (errorClass.class) {\n case 'RateLimited':\n return 'CoolingDown';\n case 'QuotaExhausted':\n return 'Disabled';\n case 'AuthFailure':\n return 'ReauthRequired';\n case 'PermissionFailure':\n return 'PolicyBlocked';\n case 'PolicyFailure':\n return 'PolicyBlocked';\n case 'RegionRestriction':\n return 'Disabled';\n case 'ModelUnavailable':\n return null;\n case 'TransientServerFailure':\n return null;\n case 'TransportFailure':\n return null;\n case 'InterruptedExecution':\n return null;\n }\n};\n","/**\n * Provider-specific error pattern corpus.\n *\n * Contains known error response patterns for Anthropic, OpenAI, Google,\n * and AWS Bedrock (direct classification) and heuristic message patterns\n * for plugin-only mode classification.\n *\n * Per ERRC-02, ERRC-05, Pitfalls 1-3.\n */\n\n/** A provider-specific error response pattern for direct classification. */\nexport interface ProviderErrorPattern {\n readonly provider: string;\n readonly http_status: number;\n readonly error_type_field: string;\n readonly error_type_value: string;\n readonly error_class: string;\n readonly notes?: string;\n}\n\n/**\n * Known provider error patterns for direct HTTP status classification.\n *\n * Order matters for matching: more specific patterns (with error_type_value)\n * should be checked before generic status-code fallbacks.\n */\nexport const PROVIDER_PATTERNS: ReadonlyArray<ProviderErrorPattern> = [\n // Anthropic\n { provider: 'anthropic', http_status: 400, error_type_field: 'error.type', error_type_value: 'invalid_request_error', error_class: 'PolicyFailure' },\n { provider: 'anthropic', http_status: 401, error_type_field: 'error.type', error_type_value: 'authentication_error', error_class: 'AuthFailure' },\n { provider: 'anthropic', http_status: 402, error_type_field: 'error.type', error_type_value: 'billing_error', error_class: 'QuotaExhausted' },\n { provider: 'anthropic', http_status: 403, error_type_field: 'error.type', error_type_value: 'permission_error', error_class: 'PermissionFailure' },\n { provider: 'anthropic', http_status: 404, error_type_field: 'error.type', error_type_value: 'not_found_error', error_class: 'ModelUnavailable' },\n { provider: 'anthropic', http_status: 429, error_type_field: 'error.type', error_type_value: 'rate_limit_error', error_class: 'RateLimited' },\n { provider: 'anthropic', http_status: 500, error_type_field: 'error.type', error_type_value: 'api_error', error_class: 'TransientServerFailure' },\n { provider: 'anthropic', http_status: 504, error_type_field: 'error.type', error_type_value: 'timeout_error', error_class: 'TransportFailure' },\n { provider: 'anthropic', http_status: 529, error_type_field: 'error.type', error_type_value: 'overloaded_error', error_class: 'RateLimited', notes: 'Server capacity exhaustion; backoff on same provider, do NOT failover' },\n\n // OpenAI\n { provider: 'openai', http_status: 400, error_type_field: 'error.code', error_type_value: '', error_class: 'PolicyFailure' },\n { provider: 'openai', http_status: 401, error_type_field: 'error.code', error_type_value: 'invalid_api_key', error_class: 'AuthFailure' },\n { provider: 'openai', http_status: 403, error_type_field: 'error.code', error_type_value: 'unsupported_country_region_territory', error_class: 'RegionRestriction', notes: 'GeoIP block — collected 2026-04-11 from real API' },\n { provider: 'openai', http_status: 403, error_type_field: 'error.code', error_type_value: '', error_class: 'PermissionFailure' },\n { provider: 'openai', http_status: 429, error_type_field: 'error.code', error_type_value: 'rate_limit_exceeded', error_class: 'RateLimited' },\n { provider: 'openai', http_status: 429, error_type_field: 'error.code', error_type_value: 'insufficient_quota', error_class: 'QuotaExhausted', notes: 'Billing exhausted -- NOT retryable' },\n { provider: 'openai', http_status: 500, error_type_field: 'error.code', error_type_value: '', error_class: 'TransientServerFailure' },\n { provider: 'openai', http_status: 503, error_type_field: 'error.code', error_type_value: '', error_class: 'TransientServerFailure' },\n\n // Google Vertex AI / Gemini\n { provider: 'google', http_status: 400, error_type_field: 'error.status', error_type_value: 'INVALID_ARGUMENT', error_class: 'PolicyFailure' },\n { provider: 'google', http_status: 403, error_type_field: 'error.status', error_type_value: 'PERMISSION_DENIED', error_class: 'PermissionFailure' },\n { provider: 'google', http_status: 429, error_type_field: 'error.status', error_type_value: 'RESOURCE_EXHAUSTED', error_class: 'RateLimited' },\n { provider: 'google', http_status: 500, error_type_field: 'error.status', error_type_value: 'INTERNAL', error_class: 'TransientServerFailure' },\n { provider: 'google', http_status: 503, error_type_field: 'error.status', error_type_value: 'UNAVAILABLE', error_class: 'TransientServerFailure' },\n\n // AWS Bedrock\n { provider: 'bedrock', http_status: 429, error_type_field: '__type', error_type_value: 'ThrottlingException', error_class: 'RateLimited' },\n { provider: 'bedrock', http_status: 408, error_type_field: '__type', error_type_value: 'ModelTimeoutException', error_class: 'TransportFailure' },\n { provider: 'bedrock', http_status: 424, error_type_field: '__type', error_type_value: 'ModelNotReadyException', error_class: 'ModelUnavailable' },\n { provider: 'bedrock', http_status: 403, error_type_field: '__type', error_type_value: 'AccessDeniedException', error_class: 'PermissionFailure' },\n { provider: 'bedrock', http_status: 400, error_type_field: '__type', error_type_value: 'ValidationException', error_class: 'PolicyFailure' },\n { provider: 'bedrock', http_status: 500, error_type_field: '__type', error_type_value: 'InternalServerException', error_class: 'TransientServerFailure' },\n];\n\n/** A heuristic pattern for plugin-only mode message classification. */\nexport interface HeuristicPattern {\n readonly pattern: RegExp;\n readonly error_class: string;\n readonly confidence: 'high' | 'medium' | 'low';\n readonly provider?: string;\n readonly notes?: string;\n}\n\n/**\n * Heuristic patterns for plugin-only mode classification.\n *\n * Order matters: more specific patterns should come first.\n * TEMPORAL_QUOTA_PATTERN is checked separately before these patterns\n * to correctly handle Pitfall 2.\n */\nexport const HEURISTIC_PATTERNS: ReadonlyArray<HeuristicPattern> = [\n // Transport errors (high confidence -- these are unambiguous)\n { pattern: /ECONNREFUSED|ECONNRESET|ETIMEDOUT/, error_class: 'TransportFailure', confidence: 'high' },\n\n // Quota patterns (before rate limit to avoid misclassification -- Pitfall 2/3)\n { pattern: /quota\\s*(?:exceeded|exhausted)/i, error_class: 'QuotaExhausted', confidence: 'medium' },\n { pattern: /insufficient\\s*quota/i, error_class: 'QuotaExhausted', confidence: 'medium', provider: 'openai' },\n { pattern: /billing/i, error_class: 'QuotaExhausted', confidence: 'low', provider: 'openai' },\n\n // Rate limit patterns\n { pattern: /rate\\s*limit/i, error_class: 'RateLimited', confidence: 'medium' },\n { pattern: /too many requests/i, error_class: 'RateLimited', confidence: 'medium' },\n { pattern: /retry\\s*after/i, error_class: 'RateLimited', confidence: 'medium' },\n { pattern: /overloaded/i, error_class: 'RateLimited', confidence: 'medium', provider: 'anthropic' },\n { pattern: /resource\\s*exhausted/i, error_class: 'RateLimited', confidence: 'medium', provider: 'google' },\n\n // Auth patterns\n { pattern: /authentication/i, error_class: 'AuthFailure', confidence: 'medium' },\n { pattern: /invalid\\s*api\\s*key/i, error_class: 'AuthFailure', confidence: 'medium' },\n { pattern: /unauthorized/i, error_class: 'AuthFailure', confidence: 'medium' },\n\n // Permission patterns\n { pattern: /permission\\s*denied/i, error_class: 'PermissionFailure', confidence: 'medium' },\n { pattern: /forbidden/i, error_class: 'PermissionFailure', confidence: 'low' },\n\n // Model availability patterns\n { pattern: /model\\s*not\\s*(?:available|ready|found)/i, error_class: 'ModelUnavailable', confidence: 'medium' },\n { pattern: /not\\s*found/i, error_class: 'ModelUnavailable', confidence: 'low' },\n\n // Transport patterns (lower confidence than ECONNREFUSED)\n { pattern: /timeout/i, error_class: 'TransportFailure', confidence: 'low' },\n\n // Region restriction (requires both keywords)\n { pattern: /unsupported.country.*region.*territory/i, error_class: 'RegionRestriction', confidence: 'high', notes: 'OpenAI GeoIP block — collected 2026-04-11' },\n { pattern: /country.*region.*not supported/i, error_class: 'RegionRestriction', confidence: 'high' },\n { pattern: /region.*restrict|restrict.*region/i, error_class: 'RegionRestriction', confidence: 'low' },\n];\n\n/**\n * Temporal quota pattern to distinguish quota exhaustion from transient rate limits.\n *\n * Matches messages like \"Too many tokens per day\" from Bedrock, which arrive as\n * ThrottlingException but represent non-retryable quota exhaustion (Pitfall 2).\n */\nexport const TEMPORAL_QUOTA_PATTERN = /too many tokens per (?:day|month|hour|week)/i;\n","/**\n * Mode-agnostic error classifier core.\n *\n * Accepts a NormalizedSignal and routes to direct (HTTP) or heuristic\n * (message pattern) classification based on signal content.\n *\n * Per D-01, ERRC-01.\n */\n\nimport type { NormalizedSignal, ClassificationResult, ErrorClass } from './taxonomy.js';\nimport { PROVIDER_PATTERNS, HEURISTIC_PATTERNS, TEMPORAL_QUOTA_PATTERN } from './corpus.js';\n\n/**\n * Builds an ErrorClass object from a class name string.\n *\n * Maps class name to the correct discriminated union variant\n * with appropriate metadata fields.\n */\nconst buildErrorClass = (\n className: string,\n extras?: {\n readonly retry_after_ms?: number;\n readonly provider_reason?: string;\n readonly http_status?: number;\n },\n): ErrorClass => {\n switch (className) {\n case 'RateLimited':\n return {\n class: 'RateLimited',\n retryable: true,\n retry_after_ms: extras?.retry_after_ms,\n provider_reason: extras?.provider_reason,\n };\n case 'QuotaExhausted':\n return {\n class: 'QuotaExhausted',\n retryable: false,\n provider_reason: extras?.provider_reason,\n };\n case 'AuthFailure':\n return { class: 'AuthFailure', retryable: false, recovery_attempted: false };\n case 'PermissionFailure':\n return { class: 'PermissionFailure', retryable: false };\n case 'PolicyFailure':\n return { class: 'PolicyFailure', retryable: false };\n case 'RegionRestriction':\n return { class: 'RegionRestriction', retryable: false };\n case 'ModelUnavailable':\n return { class: 'ModelUnavailable', retryable: false, failover_eligible: true };\n case 'TransientServerFailure':\n return {\n class: 'TransientServerFailure',\n retryable: true,\n http_status: extras?.http_status,\n };\n case 'TransportFailure':\n return { class: 'TransportFailure', retryable: true };\n case 'InterruptedExecution':\n return { class: 'InterruptedExecution', retryable: true };\n default:\n return { class: 'TransientServerFailure', retryable: true, http_status: extras?.http_status };\n }\n};\n\n/**\n * Extracts an error type string from a response body, trying\n * multiple provider-specific field paths.\n */\nconst extractErrorTypeFromBody = (body: unknown): string | undefined => {\n if (typeof body !== 'object' || body === null) return undefined;\n const b = body as Record<string, unknown>;\n\n const errorObj = b.error as Record<string, unknown> | undefined;\n if (typeof errorObj === 'object' && errorObj !== null) {\n if (typeof errorObj.type === 'string') return errorObj.type;\n if (typeof errorObj.code === 'string') return errorObj.code;\n if (typeof errorObj.status === 'string') return errorObj.status;\n }\n\n if (typeof b.__type === 'string') return b.__type;\n return undefined;\n};\n\n/**\n * Classifies a signal with HTTP status code (direct mode).\n *\n * Classification priority:\n * 1. Temporal quota pattern on error message (Pitfall 2)\n * 2. Provider-specific error type matching from corpus\n * 3. OpenAI insufficient_quota special case (Pitfall 3)\n * 4. Anthropic 529 overloaded_error special case (Pitfall 3)\n * 5. Generic HTTP status fallback\n */\nconst classifyDirect = (signal: NormalizedSignal): ClassificationResult => {\n const status = signal.http_status!;\n const errorType = signal.error_type ?? extractErrorTypeFromBody(signal.response_body);\n const errorMessage = signal.error_message ?? '';\n\n // Pitfall 2: temporal quota qualifiers override status code classification\n if (status === 429 && TEMPORAL_QUOTA_PATTERN.test(errorMessage)) {\n return {\n error_class: buildErrorClass('QuotaExhausted'),\n detection_mode: 'direct',\n confidence: 'high',\n raw_signal: signal,\n };\n }\n\n // Pitfall 3: OpenAI insufficient_quota on 429 is QuotaExhausted, NOT RateLimited\n if (status === 429 && errorType === 'insufficient_quota') {\n return {\n error_class: buildErrorClass('QuotaExhausted'),\n detection_mode: 'direct',\n confidence: 'high',\n raw_signal: signal,\n };\n }\n\n // Pitfall 3: Anthropic 529 overloaded_error is capacity, not account rate limit\n if (status === 529 && errorType === 'overloaded_error') {\n return {\n error_class: buildErrorClass('RateLimited', {\n retry_after_ms: signal.retry_after_ms,\n provider_reason: 'server_capacity_exhaustion',\n }),\n detection_mode: 'direct',\n confidence: 'high',\n raw_signal: signal,\n };\n }\n\n // Match against provider corpus by error type\n if (errorType) {\n const match = PROVIDER_PATTERNS.find(\n (p) => p.http_status === status && p.error_type_value === errorType,\n );\n if (match) {\n return {\n error_class: buildErrorClass(match.error_class, {\n retry_after_ms: signal.retry_after_ms,\n http_status: status,\n }),\n detection_mode: 'direct',\n confidence: 'high',\n raw_signal: signal,\n };\n }\n }\n\n // Also check for Bedrock temporal quota on ThrottlingException\n if (errorType === 'ThrottlingException' && TEMPORAL_QUOTA_PATTERN.test(errorMessage)) {\n return {\n error_class: buildErrorClass('QuotaExhausted'),\n detection_mode: 'direct',\n confidence: 'high',\n raw_signal: signal,\n };\n }\n\n // Generic HTTP status fallback\n const fallbackClass = getClassFromStatus(status);\n return {\n error_class: buildErrorClass(fallbackClass, {\n retry_after_ms: signal.retry_after_ms,\n http_status: status,\n }),\n detection_mode: 'direct',\n confidence: 'high',\n raw_signal: signal,\n };\n};\n\n/**\n * Maps an HTTP status code to a default error class.\n */\nconst getClassFromStatus = (status: number): string => {\n if (status === 400) return 'PolicyFailure';\n if (status === 401) return 'AuthFailure';\n if (status === 402) return 'QuotaExhausted';\n if (status === 403) return 'PermissionFailure';\n if (status === 404) return 'ModelUnavailable';\n if (status === 408) return 'TransportFailure';\n if (status === 429) return 'RateLimited';\n if (status >= 500) return 'TransientServerFailure';\n return 'TransientServerFailure';\n};\n\n/**\n * Classifies a signal without HTTP status code (heuristic mode).\n *\n * Classification priority:\n * 1. Temporal quota pattern (Pitfall 2 heuristic path)\n * 2. Heuristic patterns from corpus (first match wins)\n * 3. Conservative fallback to TransientServerFailure with low confidence\n */\nconst classifyHeuristic = (signal: NormalizedSignal): ClassificationResult => {\n const message = signal.error_message ?? '';\n\n // Pitfall 2: temporal quota qualifiers checked first\n if (TEMPORAL_QUOTA_PATTERN.test(message)) {\n return {\n error_class: buildErrorClass('QuotaExhausted'),\n detection_mode: 'heuristic',\n confidence: 'medium',\n raw_signal: signal,\n };\n }\n\n // Match against heuristic pattern corpus -- first match wins\n for (const hp of HEURISTIC_PATTERNS) {\n if (hp.pattern.test(message)) {\n return {\n error_class: buildErrorClass(hp.error_class),\n detection_mode: 'heuristic',\n confidence: hp.confidence,\n raw_signal: signal,\n };\n }\n }\n\n // Conservative fallback: TransientServerFailure with low confidence\n // Prefer false negatives over false positives per CONTEXT.md\n return {\n error_class: buildErrorClass('TransientServerFailure'),\n detection_mode: 'heuristic',\n confidence: 'low',\n raw_signal: signal,\n };\n};\n\n/**\n * Classifies a NormalizedSignal into an ErrorClass.\n *\n * Routes to direct (HTTP) or heuristic (message pattern) classification\n * based on whether http_status is present in the signal.\n *\n * @param signal - The normalized error signal to classify.\n * @returns ClassificationResult with error class, mode, confidence, and raw signal.\n */\nexport const classify = (signal: NormalizedSignal): ClassificationResult => {\n if (signal.http_status !== undefined) {\n return classifyDirect(signal);\n }\n return classifyHeuristic(signal);\n};\n","/**\n * Direct signal adapter: HTTP status + body to NormalizedSignal.\n *\n * Used in server-companion and SDK-control modes where raw HTTP\n * status codes, response bodies, and headers are available.\n *\n * Per D-01, ERRC-02.\n */\n\nimport type { NormalizedSignal } from './taxonomy.js';\n\n/**\n * Extracts error type from a provider response body.\n *\n * Tries multiple provider-specific field paths:\n * - body.error.type (Anthropic)\n * - body.error.code (OpenAI)\n * - body.error.status (Google)\n * - body.__type (Bedrock)\n */\nconst extractErrorType = (body: unknown): string | undefined => {\n if (typeof body !== 'object' || body === null) {\n return undefined;\n }\n const b = body as Record<string, unknown>;\n\n // Anthropic: { error: { type: \"rate_limit_error\" } }\n const errorObj = b.error as Record<string, unknown> | undefined;\n if (typeof errorObj === 'object' && errorObj !== null) {\n if (typeof errorObj.type === 'string') return errorObj.type;\n if (typeof errorObj.code === 'string') return errorObj.code;\n if (typeof errorObj.status === 'string') return errorObj.status;\n }\n\n // Bedrock: { __type: \"ThrottlingException\" }\n if (typeof b.__type === 'string') return b.__type;\n\n return undefined;\n};\n\n/**\n * Extracts error message from a provider response body.\n *\n * Tries: body.error.message, body.message.\n */\nconst extractErrorMessage = (body: unknown): string | undefined => {\n if (typeof body !== 'object' || body === null) {\n return undefined;\n }\n const b = body as Record<string, unknown>;\n\n const errorObj = b.error as Record<string, unknown> | undefined;\n if (typeof errorObj === 'object' && errorObj !== null) {\n if (typeof errorObj.message === 'string') return errorObj.message;\n }\n\n if (typeof b.message === 'string') return b.message;\n\n return undefined;\n};\n\n/**\n * Extracts Retry-After value from response headers as milliseconds.\n *\n * Supports integer seconds format. HTTP-date format is not supported\n * (providers typically send integer seconds).\n *\n * @param headers - Response headers (case-insensitive lookup for retry-after).\n * @returns Retry-After in milliseconds, or undefined if not present/parseable.\n */\nexport const extractRetryAfterMs = (\n headers?: Record<string, string>,\n): number | undefined => {\n if (!headers) return undefined;\n\n const value = headers['retry-after'] ?? headers['Retry-After'];\n if (!value) return undefined;\n\n const seconds = Number(value);\n if (Number.isNaN(seconds) || seconds < 0) return undefined;\n\n return seconds * 1000;\n};\n\n/**\n * Creates a NormalizedSignal from an HTTP response.\n *\n * Always sets detection_mode='direct' since we have raw HTTP access.\n *\n * @param status - HTTP status code.\n * @param body - Parsed response body.\n * @param headers - Response headers (optional; used for Retry-After).\n * @returns NormalizedSignal ready for classifier.\n */\nexport const directSignalFromResponse = (\n status: number,\n body: unknown,\n headers?: Record<string, string>,\n): NormalizedSignal => ({\n http_status: status,\n error_type: extractErrorType(body),\n error_message: extractErrorMessage(body),\n response_body: body,\n detection_mode: 'direct',\n retry_after_ms: extractRetryAfterMs(headers),\n});\n","/**\n * Heuristic signal adapter: message pattern to NormalizedSignal.\n *\n * Used in plugin-only mode where HTTP status codes are not available.\n * Classification relies on message string matching against known patterns.\n *\n * Per D-01, ERRC-03.\n */\n\nimport type { NormalizedSignal } from './taxonomy.js';\n\n/**\n * Creates a NormalizedSignal from a session event message.\n *\n * Always sets detection_mode='heuristic' since no HTTP access is available.\n * No http_status field is set (not available in plugin-only mode).\n *\n * @param eventType - The event type (e.g., 'error', 'retry', 'status').\n * @param message - The error or status message string.\n * @param providerId - Optional provider identifier.\n * @returns NormalizedSignal ready for classifier.\n */\nexport const heuristicSignalFromEvent = (\n eventType: string,\n message: string,\n providerId?: string,\n): NormalizedSignal => ({\n error_type: eventType,\n error_message: message,\n detection_mode: 'heuristic',\n provider_id: providerId,\n});\n","/**\n * Exponential backoff with jitter and Retry-After floor.\n *\n * Pure function that computes the delay before the next retry attempt.\n * Supports full jitter, equal jitter, and no jitter modes.\n *\n * Per D-10, D-11, Pitfall 4.\n */\n\n/** Configuration for backoff computation. */\nexport interface BackoffParams {\n readonly base_ms: number;\n readonly multiplier: number;\n readonly max_ms: number;\n readonly jitter: 'full' | 'equal' | 'none';\n}\n\n/** Default backoff parameters per D-10. */\nexport const DEFAULT_BACKOFF_PARAMS: BackoffParams = {\n base_ms: 1000,\n multiplier: 2,\n max_ms: 30000,\n jitter: 'full',\n};\n\n/**\n * Computes the backoff delay in milliseconds for a given retry attempt.\n *\n * Formula: rawDelay = min(base_ms * multiplier^attempt, max_ms)\n *\n * Jitter modes:\n * - 'full': Math.random() * rawDelay (uniform [0, rawDelay])\n * - 'equal': rawDelay/2 + Math.random() * rawDelay/2 (uniform [rawDelay/2, rawDelay])\n * - 'none': rawDelay (deterministic)\n *\n * The Retry-After value (if provided) is used as a floor: the result\n * is at least retryAfterMs, preventing retry storms (Pitfall 4 fix).\n *\n * @param attempt - Zero-based retry attempt number.\n * @param params - Backoff configuration parameters.\n * @param retryAfterMs - Optional Retry-After value in ms to use as floor.\n * @returns Delay in milliseconds before next retry.\n */\nexport const computeBackoffMs = (\n attempt: number,\n params: BackoffParams,\n retryAfterMs?: number,\n): number => {\n const rawDelay = Math.min(\n params.base_ms * Math.pow(params.multiplier, attempt),\n params.max_ms,\n );\n\n const jitteredDelay =\n params.jitter === 'full'\n ? Math.random() * rawDelay\n : params.jitter === 'equal'\n ? rawDelay / 2 + Math.random() * (rawDelay / 2)\n : rawDelay;\n\n // Retry-After floor: always wait at least as long as the server asks (Pitfall 4)\n return Math.max(jitteredDelay, retryAfterMs ?? 0);\n};\n","/**\n * Bounded retry policy with budget tracking.\n *\n * Decides whether to retry, abort, or declare exhaustion based on\n * the error classification and remaining budget.\n *\n * Per D-10, D-12, ERRC-06, ERRC-07, ERRC-08.\n */\n\nimport type { ClassificationResult } from '../errors/taxonomy.js';\nimport { isRetryable, getTargetStateTransition } from '../errors/taxonomy.js';\nimport type { TargetState } from '../registry/types.js';\nimport { computeBackoffMs, DEFAULT_BACKOFF_PARAMS } from './backoff.js';\nimport type { BackoffParams } from './backoff.js';\n\n/**\n * A retry decision: retry with delay, abort immediately, or budget exhausted.\n */\nexport type RetryDecision =\n | { readonly action: 'retry'; readonly delay_ms: number; readonly attempt: number }\n | { readonly action: 'abort'; readonly reason: string; readonly target_state: TargetState | null }\n | { readonly action: 'exhausted'; readonly attempts_used: number };\n\n/**\n * A retry policy with budget and backoff configuration.\n */\nexport interface RetryPolicy {\n readonly budget: number;\n readonly backoffParams: BackoffParams;\n readonly decide: (\n classification: ClassificationResult,\n attemptsSoFar: number,\n ) => RetryDecision;\n}\n\n/**\n * Creates a bounded retry policy.\n *\n * Decision logic:\n * 1. Non-retryable errors (AuthFailure, PermissionFailure, QuotaExhausted,\n * PolicyFailure, RegionRestriction, ModelUnavailable) -> abort immediately\n * with target state transition (D-12)\n * 2. Budget exhausted -> return 'exhausted' with attempt count\n * 3. Retryable errors -> compute backoff with Retry-After floor and return 'retry'\n *\n * AuthFailure special handling (ERRC-06): if recovery_attempted is true,\n * abort with ReauthRequired state. The caller is responsible for setting\n * recovery_attempted on the first recovery attempt.\n *\n * @param budget - Maximum number of retry attempts.\n * @param backoffParams - Backoff configuration (defaults to full jitter).\n * @returns A RetryPolicy instance.\n */\nexport const createRetryPolicy = (\n budget: number,\n backoffParams: BackoffParams = DEFAULT_BACKOFF_PARAMS,\n): RetryPolicy => ({\n budget,\n backoffParams,\n decide: (\n classification: ClassificationResult,\n attemptsSoFar: number,\n ): RetryDecision => {\n const errorClass = classification.error_class;\n\n // Non-retryable errors abort immediately (D-12)\n if (!isRetryable(errorClass)) {\n return {\n action: 'abort',\n reason: `Non-retryable: ${errorClass.class}`,\n target_state: getTargetStateTransition(errorClass),\n };\n }\n\n // Budget check: prevent uncontrolled retry loops\n if (attemptsSoFar >= budget) {\n return {\n action: 'exhausted',\n attempts_used: attemptsSoFar,\n };\n }\n\n // Extract Retry-After from RateLimited error class\n const retryAfterMs =\n errorClass.class === 'RateLimited' ? errorClass.retry_after_ms : undefined;\n\n // Compute backoff with Retry-After as floor (Pitfall 4 fix)\n const delayMs = computeBackoffMs(attemptsSoFar, backoffParams, retryAfterMs);\n\n return {\n action: 'retry',\n delay_ms: delayMs,\n attempt: attemptsSoFar + 1,\n };\n },\n});\n","/**\n * Routing domain types for Phase 2.\n *\n * Defines ExclusionReason, AdmissionResult, SelectionRecord, RoutingWeights,\n * CircuitBreakerConfig, CircuitBreaker, and ConcurrencyTrackerApi types.\n *\n * Per D-17, D-20, D-22, D-24, D-26.\n */\n\nimport type { TargetState } from '../registry/types.js';\n\n/** 7 exclusion reasons per ROUT-03, D-17. */\nexport const EXCLUSION_REASONS = [\n 'disabled',\n 'policy_blocked',\n 'reauth_required',\n 'cooldown_active',\n 'circuit_open',\n 'capability_mismatch',\n 'draining',\n] as const;\n\n/** Why a target was excluded from routing. */\nexport type ExclusionReason = (typeof EXCLUSION_REASONS)[number];\n\n/** 4 admission outcomes per ADMC-02, D-20. */\nexport const ADMISSION_RESULTS = [\n 'admitted',\n 'queued',\n 'degraded',\n 'rejected',\n] as const;\n\n/** Admission control decision outcome. */\nexport type AdmissionResult = (typeof ADMISSION_RESULTS)[number];\n\n/** Admission decision with reason string. */\nexport interface AdmissionDecision {\n readonly result: AdmissionResult;\n readonly reason: string;\n}\n\n/** Scoring weights for target selection per D-17. */\nexport interface RoutingWeights {\n readonly health: number;\n readonly latency: number;\n readonly failure: number;\n readonly priority: number;\n}\n\n/** Circuit breaker configuration per D-22. */\nexport interface CircuitBreakerConfig {\n readonly failure_threshold: number;\n readonly failure_rate_threshold: number;\n readonly sliding_window_size: number;\n readonly half_open_after_ms: number;\n readonly half_open_max_probes: number;\n readonly success_threshold: number;\n}\n\n/** Full audit record for a target selection per D-26. */\nexport interface SelectionRecord {\n readonly request_id: string;\n readonly timestamp_ms: number;\n readonly candidates: ReadonlyArray<{\n readonly target_id: string;\n readonly score: number;\n readonly health_score: number;\n readonly latency_ema_ms: number;\n }>;\n readonly excluded: ReadonlyArray<{\n readonly target_id: string;\n readonly reason: ExclusionReason;\n }>;\n readonly selected: {\n readonly target_id: string;\n readonly score: number;\n readonly rank: number;\n } | null;\n}\n\n/**\n * Circuit breaker interface per D-18.\n * recordSuccess/recordFailure are async because they use cockatiel's\n * execute() internally to properly manage state transitions.\n */\nexport interface CircuitBreaker {\n state(): TargetState;\n recordSuccess(): Promise<void>;\n recordFailure(): Promise<void>;\n allowRequest(): boolean;\n reset(): void;\n}\n\n/** Concurrency tracker interface per D-24. */\nexport interface ConcurrencyTrackerApi {\n acquire(target_id: string): boolean;\n release(target_id: string): void;\n headroom(target_id: string): number;\n active(target_id: string): number;\n}\n","/**\n * Typed event bus for routing events per D-25.\n *\n * Uses eventemitter3 with a typed event map for type-safe emit/on.\n * 6 event types: circuit_state_change, target_excluded, health_updated,\n * admission_decision, cooldown_set, cooldown_expired.\n */\n\nimport { EventEmitter } from 'eventemitter3';\nimport type { TargetState } from '../registry/types.js';\nimport type { ExclusionReason, AdmissionResult } from './types.js';\n\n/** Typed event map for all routing events. */\nexport interface RoutingEventMap {\n circuit_state_change: (payload: {\n target_id: string;\n from: TargetState;\n to: TargetState;\n reason: string;\n }) => void;\n target_excluded: (payload: {\n target_id: string;\n reason: ExclusionReason;\n }) => void;\n health_updated: (payload: {\n target_id: string;\n old_score: number;\n new_score: number;\n }) => void;\n admission_decision: (payload: {\n request_id: string;\n result: AdmissionResult;\n reason: string;\n }) => void;\n cooldown_set: (payload: {\n target_id: string;\n until_ms: number;\n error_class: string;\n }) => void;\n cooldown_expired: (payload: { target_id: string }) => void;\n}\n\n/** Creates a typed event bus for routing events. */\nexport const createRoutingEventBus = (): EventEmitter<RoutingEventMap> =>\n new EventEmitter<RoutingEventMap>();\n","/**\n * DualBreaker: composite IBreaker for cockatiel circuit breaker.\n *\n * Composes ConsecutiveBreaker (N consecutive failures) with\n * CountBreaker (failure rate in sliding window). The circuit opens\n * if EITHER trigger fires (OR logic per D-22 dual trigger).\n *\n * Uses CountBreaker (not SamplingBreaker) because D-22's sliding_window\n * refers to request count, not time duration (Pitfall 2 from research).\n */\n\nimport {\n ConsecutiveBreaker,\n CountBreaker,\n type IBreaker,\n CircuitState,\n} from 'cockatiel';\n\n/** Composite breaker that trips on consecutive failures OR failure rate. */\nexport class DualBreaker implements IBreaker {\n private readonly consecutive: ConsecutiveBreaker;\n private readonly count: CountBreaker;\n\n constructor(\n consecutiveThreshold: number,\n countOpts: {\n threshold: number;\n size: number;\n minimumNumberOfCalls?: number;\n },\n ) {\n this.consecutive = new ConsecutiveBreaker(consecutiveThreshold);\n this.count = new CountBreaker(countOpts);\n }\n\n /** Serializable state for both internal breakers. */\n get state(): unknown {\n return {\n consecutive: this.consecutive.state,\n count: this.count.state,\n };\n }\n\n /** Restore state for both internal breakers. */\n set state(value: unknown) {\n const v = value as { consecutive: number; count: unknown };\n this.consecutive.state = v.consecutive;\n this.count.state = v.count;\n }\n\n /**\n * Record success on both breakers.\n * ConsecutiveBreaker.success() takes no args (resets counter).\n * CountBreaker.success() takes CircuitState.\n */\n success(state: CircuitState): void {\n this.consecutive.success();\n this.count.success(state);\n }\n\n /**\n * Record failure on both breakers.\n * Returns true if EITHER breaker trips (OR logic).\n * ConsecutiveBreaker.failure() takes no args.\n * CountBreaker.failure() takes CircuitState.\n */\n failure(state: CircuitState): boolean {\n const consecutiveTripped = this.consecutive.failure();\n const countTripped = this.count.failure(state);\n return consecutiveTripped || countTripped;\n }\n}\n","/**\n * CircuitBreaker wrapper around cockatiel's CircuitBreakerPolicy.\n *\n * Wraps cockatiel internals behind the CircuitBreaker interface from types.ts.\n * Maps cockatiel CircuitState to TargetState. Emits circuit_state_change events\n * via the routing event bus.\n *\n * Per D-18: cockatiel in wrapper pattern. We do NOT use execute() for routing;\n * instead we use recordSuccess/recordFailure to update the breaker state after\n * external request completion. Internally, we call policy.execute() with\n * success/failure functions to let cockatiel manage state transitions correctly.\n *\n * Note: cockatiel closes from HalfOpen after 1 success (native behavior).\n * This is accepted per research recommendation. D-22's success_threshold:2\n * is documented but not enforced at this layer.\n */\n\nimport {\n CircuitState,\n handleAll,\n circuitBreaker,\n type CircuitBreakerPolicy,\n BrokenCircuitError,\n IsolatedCircuitError,\n} from 'cockatiel';\nimport type { TargetState } from '../registry/types.js';\nimport type {\n CircuitBreaker,\n CircuitBreakerConfig,\n} from './types.js';\nimport type { RoutingEventMap } from './events.js';\nimport { EventEmitter } from 'eventemitter3';\nimport { DualBreaker } from './dual-breaker.js';\n\n/** Maps cockatiel CircuitState enum values to TargetState strings. */\nconst COCKATIEL_TO_TARGET: ReadonlyMap<CircuitState, TargetState> = new Map([\n [CircuitState.Closed, 'Active'],\n [CircuitState.Open, 'CircuitOpen'],\n [CircuitState.HalfOpen, 'CircuitHalfOpen'],\n [CircuitState.Isolated, 'Disabled'],\n]);\n\n/** Convert cockatiel CircuitState to TargetState. */\nconst toTargetState = (state: CircuitState): TargetState =>\n COCKATIEL_TO_TARGET.get(state) ?? 'Disabled';\n\n/**\n * Create a circuit breaker for a specific target.\n *\n * @param targetId - Target identifier for event attribution.\n * @param config - Circuit breaker configuration.\n * @param eventBus - Optional event bus for state change notifications.\n * @returns CircuitBreaker interface implementation.\n */\nexport const createCircuitBreaker = (\n targetId: string,\n config: CircuitBreakerConfig,\n eventBus?: EventEmitter<RoutingEventMap>,\n): CircuitBreaker => {\n const createPolicy = (): {\n policy: CircuitBreakerPolicy;\n breaker: DualBreaker;\n } => {\n const breaker = new DualBreaker(config.failure_threshold, {\n threshold: config.failure_rate_threshold,\n size: config.sliding_window_size,\n });\n\n const policy = circuitBreaker(handleAll, {\n halfOpenAfter: config.half_open_after_ms,\n breaker,\n });\n\n return { policy, breaker };\n };\n\n let current = createPolicy();\n let previousState = CircuitState.Closed;\n let openedAtMs = 0;\n\n /** Subscribe to state changes and emit events. */\n const subscribeEvents = (policy: CircuitBreakerPolicy): void => {\n policy.onStateChange((newState) => {\n if (newState === CircuitState.Open) {\n openedAtMs = Date.now();\n }\n\n const from = toTargetState(previousState);\n const to = toTargetState(newState);\n previousState = newState;\n\n if (from !== to && eventBus) {\n eventBus.emit('circuit_state_change', {\n target_id: targetId,\n from,\n to,\n reason: `state_transition`,\n });\n }\n });\n };\n\n subscribeEvents(current.policy);\n\n /**\n * Effective state accounts for cockatiel's lazy HalfOpen transition.\n * Cockatiel only transitions from Open to HalfOpen on execute() call,\n * but our state() should reflect the logical state based on elapsed time.\n */\n const effectiveState = (): CircuitState => {\n const raw = current.policy.state;\n if (\n raw === CircuitState.Open &&\n openedAtMs > 0 &&\n Date.now() - openedAtMs >= config.half_open_after_ms\n ) {\n return CircuitState.HalfOpen;\n }\n return raw;\n };\n\n return {\n state(): TargetState {\n return toTargetState(effectiveState());\n },\n\n async recordSuccess(): Promise<void> {\n try {\n await current.policy.execute(async () => undefined);\n } catch (err) {\n // BrokenCircuitError means circuit is open -- success can't be recorded\n if (\n err instanceof BrokenCircuitError ||\n err instanceof IsolatedCircuitError\n ) {\n return;\n }\n throw err;\n }\n },\n\n async recordFailure(): Promise<void> {\n try {\n await current.policy.execute(async () => {\n throw new Error('recorded-failure');\n });\n } catch {\n // Expected: either our thrown error or BrokenCircuitError\n // Both are fine -- the failure has been recorded (or circuit was already open)\n }\n },\n\n allowRequest(): boolean {\n return effectiveState() !== CircuitState.Open;\n },\n\n reset(): void {\n // Recreate the policy to reset all internal state\n current = createPolicy();\n previousState = CircuitState.Closed;\n openedAtMs = 0;\n subscribeEvents(current.policy);\n },\n };\n};\n","/**\n * Per-target concurrency tracking per D-24.\n *\n * Tracks in-flight request counts per target with acquire/release semantics.\n * Each target has an independent slot counter with a configurable limit.\n */\n\nimport type { ConcurrencyTrackerApi } from './types.js';\n\n/**\n * Create a concurrency tracker with a default per-target limit.\n *\n * @param defaultLimit - Default concurrency limit for targets.\n * @returns ConcurrencyTrackerApi with additional setLimit method for per-target overrides.\n */\nexport const createConcurrencyTracker = (\n defaultLimit: number,\n): ConcurrencyTrackerApi & {\n setLimit(target_id: string, limit: number): void;\n} => {\n const state = new Map<string, { active: number; limit: number }>();\n\n const getOrCreate = (target_id: string): { active: number; limit: number } => {\n const existing = state.get(target_id);\n if (existing) return existing;\n const entry = { active: 0, limit: defaultLimit };\n state.set(target_id, entry);\n return entry;\n };\n\n return {\n acquire(target_id: string): boolean {\n const entry = getOrCreate(target_id);\n if (entry.active >= entry.limit) return false;\n entry.active += 1;\n return true;\n },\n\n release(target_id: string): void {\n const entry = state.get(target_id);\n if (!entry || entry.active <= 0) return;\n entry.active -= 1;\n },\n\n headroom(target_id: string): number {\n const entry = getOrCreate(target_id);\n return Math.max(0, entry.limit - entry.active);\n },\n\n active(target_id: string): number {\n const entry = state.get(target_id);\n return entry ? entry.active : 0;\n },\n\n setLimit(target_id: string, limit: number): void {\n const entry = getOrCreate(target_id);\n entry.limit = limit;\n },\n };\n};\n","/**\n * Policy engine: filter-then-score target selection per D-17.\n *\n * Pure functions that select the best target from a registry snapshot.\n * No I/O, no external state dependencies -- deterministic for identical inputs.\n *\n * Score formula (D-17):\n * score = w_health * health_score\n * - w_latency * normalizeLatency(latency_ema_ms, maxLatencyMs)\n * - w_failure * failure_score\n * + w_priority * operator_priority\n *\n * Tie-breaking: target_id lexicographic ascending for full determinism (Pitfall 5).\n *\n * Exclusion order:\n * 1. !enabled -> 'disabled'\n * 2. PolicyBlocked -> 'policy_blocked'\n * 3. ReauthRequired -> 'reauth_required'\n * 4. Draining -> 'draining'\n * 5. Disabled state -> 'disabled'\n * 6. Circuit breaker denies -> 'circuit_open'\n * 7. Cooldown active -> 'cooldown_active'\n * 8. Capability mismatch -> 'capability_mismatch'\n *\n * Targets in `excludeTargets` are silently filtered (failover loop, D-19).\n */\n\nimport type pino from 'pino';\nimport type { TargetEntry, RegistrySnapshot } from '../registry/types.js';\nimport type {\n ExclusionReason,\n RoutingWeights,\n SelectionRecord,\n CircuitBreaker,\n} from './types.js';\n\n/**\n * Normalizes latency to [0, 1] range using max expected latency.\n * Clamps to 1.0 when latency exceeds maxExpectedMs.\n *\n * @param latencyEmaMs - Exponential moving average latency in ms.\n * @param maxExpectedMs - Maximum expected latency for normalization.\n * @returns Normalized latency in [0, 1].\n */\nexport const normalizeLatency = (\n latencyEmaMs: number,\n maxExpectedMs: number,\n): number => Math.min(latencyEmaMs / maxExpectedMs, 1.0);\n\n/**\n * Computes the routing score for a target using D-17 weighted formula.\n *\n * Higher score = better target.\n *\n * @param target - The target entry to score.\n * @param weights - Scoring weights configuration.\n * @param maxLatencyMs - Maximum expected latency for normalization.\n * @returns Numeric score for ranking.\n */\nexport const computeScore = (\n target: TargetEntry,\n weights: RoutingWeights,\n maxLatencyMs: number,\n): number =>\n weights.health * target.health_score -\n weights.latency * normalizeLatency(target.latency_ema_ms, maxLatencyMs) -\n weights.failure * target.failure_score +\n weights.priority * target.operator_priority;\n\n/**\n * Checks a single target against all exclusion criteria.\n *\n * Returns the first matching ExclusionReason, or null if eligible.\n * Check order matters -- earlier checks take priority.\n *\n * @param target - Target to evaluate.\n * @param circuitBreakers - Circuit breaker map by target_id.\n * @param requiredCapabilities - Capabilities the request needs.\n * @param excludeTargets - Set of target_ids to silently skip (failover).\n * @param nowMs - Current timestamp for cooldown evaluation.\n * @returns ExclusionReason or null if eligible.\n */\nexport const getExclusionReason = (\n target: TargetEntry,\n circuitBreakers: ReadonlyMap<string, CircuitBreaker>,\n requiredCapabilities: readonly string[],\n excludeTargets: ReadonlySet<string>,\n nowMs: number,\n): ExclusionReason | null => {\n // 1. Config-disabled\n if (!target.enabled) {\n return 'disabled';\n }\n\n // 2. PolicyBlocked state\n if (target.state === 'PolicyBlocked') {\n return 'policy_blocked';\n }\n\n // 3. ReauthRequired state\n if (target.state === 'ReauthRequired') {\n return 'reauth_required';\n }\n\n // 4. Draining state\n if (target.state === 'Draining') {\n return 'draining';\n }\n\n // 5. Disabled state (distinct from enabled=false config flag)\n if (target.state === 'Disabled') {\n return 'disabled';\n }\n\n // 6. Circuit breaker denies\n const breaker = circuitBreakers.get(target.target_id);\n if (breaker !== undefined && !breaker.allowRequest()) {\n return 'circuit_open';\n }\n\n // 7. Cooldown active (cooldown_until > now means still cooling down)\n if (target.cooldown_until !== null && target.cooldown_until > nowMs) {\n return 'cooldown_active';\n }\n\n // 8. Capability mismatch\n if (\n requiredCapabilities.length > 0 &&\n !requiredCapabilities.every((cap) => target.capabilities.includes(cap))\n ) {\n return 'capability_mismatch';\n }\n\n return null;\n};\n\n/**\n * Selects the best target from a registry snapshot using filter-then-score.\n *\n * 1. Filter: exclude ineligible targets, recording reasons.\n * 2. Silently filter targets in excludeTargets (failover re-selection prevention).\n * 3. Score: compute weighted score for each eligible target.\n * 4. Sort: by score DESC, then target_id ASC for determinism.\n * 5. Return full SelectionRecord per D-26.\n *\n * @param snapshot - Registry snapshot with all targets.\n * @param circuitBreakers - Circuit breaker map by target_id.\n * @param requiredCapabilities - Capabilities the request requires.\n * @param weights - Scoring weights for ranking.\n * @param maxLatencyMs - Max expected latency for normalization.\n * @param nowMs - Current timestamp for cooldown checks.\n * @param request_id - Request identifier for audit trail.\n * @param excludeTargets - Optional set of target_ids to silently skip.\n * @param logger - Optional pino logger for selection audit logging.\n * @returns SelectionRecord with full audit information.\n */\nexport const selectTarget = (\n snapshot: RegistrySnapshot,\n circuitBreakers: ReadonlyMap<string, CircuitBreaker>,\n requiredCapabilities: readonly string[],\n weights: RoutingWeights,\n maxLatencyMs: number,\n nowMs: number,\n request_id: string,\n excludeTargets?: ReadonlySet<string>,\n logger?: pino.Logger,\n): SelectionRecord => {\n const excluded: Array<{ readonly target_id: string; readonly reason: ExclusionReason }> = [];\n const eligible: TargetEntry[] = [];\n\n for (const target of snapshot.targets) {\n // Silent exclusion for failover loop (D-19) -- not recorded\n if (excludeTargets !== undefined && excludeTargets.has(target.target_id)) {\n continue;\n }\n\n const reason = getExclusionReason(\n target,\n circuitBreakers,\n requiredCapabilities,\n excludeTargets ?? new Set(),\n nowMs,\n );\n\n if (reason !== null) {\n excluded.push({ target_id: target.target_id, reason });\n } else {\n eligible.push(target);\n }\n }\n\n // Score each eligible target\n const scored = eligible.map((target) => ({\n target,\n score: computeScore(target, weights, maxLatencyMs),\n }));\n\n // Sort: score DESC, then target_id ASC for determinism (Pitfall 5)\n scored.sort((a, b) => {\n const scoreDiff = b.score - a.score;\n if (scoreDiff !== 0) {\n return scoreDiff;\n }\n return a.target.target_id.localeCompare(b.target.target_id);\n });\n\n // Build candidates array\n const candidates = scored.map((s) => ({\n target_id: s.target.target_id,\n score: s.score,\n health_score: s.target.health_score,\n latency_ema_ms: s.target.latency_ema_ms,\n }));\n\n // Build selected (first candidate or null)\n const firstCandidate = candidates.length > 0 ? candidates[0] : undefined;\n const selected =\n firstCandidate !== undefined\n ? {\n target_id: firstCandidate.target_id,\n score: firstCandidate.score,\n rank: 0,\n }\n : null;\n\n const record: SelectionRecord = {\n request_id,\n timestamp_ms: nowMs,\n candidates,\n excluded,\n selected,\n };\n\n if (logger !== undefined) {\n const excludedSummary: Record<string, number> = {};\n for (const e of excluded) {\n excludedSummary[e.reason] = (excludedSummary[e.reason] ?? 0) + 1;\n }\n\n const logFields = {\n event: 'target_selected' as const,\n component: 'policy-engine' as const,\n request_id,\n selected: selected?.target_id ?? null,\n score: selected?.score ?? null,\n candidates_count: candidates.length,\n excluded_count: excluded.length,\n excluded_summary: excludedSummary,\n };\n\n if (selected !== null) {\n logger.info(logFields, 'Target selected');\n } else {\n logger.warn(logFields, 'No eligible target');\n }\n }\n\n return record;\n};\n","/**\n * Adaptive cooldown manager per D-23.\n *\n * computeCooldownMs: Pure function that calculates cooldown duration\n * based on error class, consecutive failures, and backoff configuration.\n * - RateLimited with retry_after_ms: uses retry_after as base\n * - RateLimited without retry_after_ms: exponential backoff\n * - TransientServerFailure: half the backoff duration\n * - Other error classes: fixed 5000ms base\n * - All results include jitter (10-25%) to prevent thundering herd (Pitfall 7)\n * - All results clamped to maxMs\n *\n * CooldownManager: Coordinates cooldown state with TargetRegistry\n * and event bus. Uses passive checking (no setTimeout, Pitfall 6).\n */\n\nimport { computeBackoffMs } from '../retry/backoff.js';\nimport type { BackoffParams } from '../retry/backoff.js';\nimport type { ErrorClass } from '../errors/taxonomy.js';\nimport type { TargetRegistry } from '../registry/registry.js';\nimport type { EventEmitter } from 'eventemitter3';\nimport type { RoutingEventMap } from './events.js';\n\n/** Fixed base cooldown for non-rate-limited, non-transient errors. */\nconst DEFAULT_COOLDOWN_BASE_MS = 5000;\n\n/**\n * Computes the cooldown duration in milliseconds for a target.\n *\n * The duration adapts to the error class:\n * - RateLimited + retry_after_ms: uses server-provided value as base\n * - RateLimited (no retry_after): exponential backoff from consecutiveFailures\n * - TransientServerFailure: half the exponential backoff\n * - All others: fixed 5000ms base\n *\n * Jitter of 10-25% is added to prevent thundering herd.\n * Result is clamped to maxMs.\n *\n * @param errorClass - The classified error that triggered cooldown.\n * @param consecutiveFailures - Number of consecutive failures for this target.\n * @param backoffParams - Backoff configuration parameters.\n * @param maxMs - Maximum cooldown duration in ms.\n * @returns Cooldown duration in ms with jitter applied.\n */\nexport const computeCooldownMs = (\n errorClass: ErrorClass,\n consecutiveFailures: number,\n backoffParams: BackoffParams,\n maxMs: number,\n): number => {\n const noJitterParams: BackoffParams = {\n ...backoffParams,\n jitter: 'none',\n };\n\n let base: number;\n\n if (\n errorClass.class === 'RateLimited' &&\n 'retry_after_ms' in errorClass &&\n errorClass.retry_after_ms !== undefined\n ) {\n base = Math.min(errorClass.retry_after_ms, maxMs);\n } else if (errorClass.class === 'RateLimited') {\n base = computeBackoffMs(consecutiveFailures, noJitterParams);\n } else if (errorClass.class === 'TransientServerFailure') {\n base = computeBackoffMs(consecutiveFailures, noJitterParams) / 2;\n } else {\n base = DEFAULT_COOLDOWN_BASE_MS;\n }\n\n base = Math.min(base, maxMs);\n\n // Jitter: random between 10% and 25% of base (D-23)\n const jitterFraction = 0.1 + Math.random() * 0.15; // [0.10, 0.25)\n const jitter = jitterFraction * base;\n\n return Math.min(base + jitter, maxMs);\n};\n\n/** CooldownManager interface for coordinating cooldown state. */\nexport interface CooldownManager {\n /** Sets a target into cooldown for the given duration. */\n setCooldown(target_id: string, durationMs: number, errorClass: string): void;\n /** Checks all targets for expired cooldowns and transitions them to Active. */\n checkExpired(nowMs: number): readonly string[];\n /** Checks whether a specific target is currently in cooldown. */\n isInCooldown(target_id: string, nowMs: number): boolean;\n}\n\n/**\n * Creates a CooldownManager that coordinates with TargetRegistry and event bus.\n *\n * Uses passive checking (no setTimeout) per Pitfall 6.\n * checkExpired should be called periodically or before routing decisions.\n *\n * @param registry - Target registry for state mutations.\n * @param eventBus - Optional event bus for cooldown events.\n * @returns CooldownManager instance.\n */\nexport const createCooldownManager = (\n registry: TargetRegistry,\n eventBus?: EventEmitter<RoutingEventMap>,\n): CooldownManager => ({\n setCooldown(target_id: string, durationMs: number, errorClass: string): void {\n const untilMs = Date.now() + durationMs;\n registry.setCooldown(target_id, untilMs);\n registry.updateState(target_id, 'CoolingDown');\n eventBus?.emit('cooldown_set', {\n target_id,\n until_ms: untilMs,\n error_class: errorClass,\n });\n },\n\n checkExpired(nowMs: number): readonly string[] {\n const expired: string[] = [];\n for (const target of registry.getAllTargets()) {\n if (\n target.state === 'CoolingDown' &&\n target.cooldown_until !== null &&\n target.cooldown_until <= nowMs\n ) {\n registry.setCooldown(target.target_id, 0);\n registry.updateState(target.target_id, 'Active');\n eventBus?.emit('cooldown_expired', { target_id: target.target_id });\n expired.push(target.target_id);\n }\n }\n return expired;\n },\n\n isInCooldown(target_id: string, nowMs: number): boolean {\n const target = registry.getTarget(target_id);\n if (!target) {\n return false;\n }\n return target.cooldown_until !== null && target.cooldown_until > nowMs;\n },\n});\n","/**\n * Layered admission controller per D-20.\n *\n * Three-layer design:\n * 1. checkHardRejects: Pure function checking 4 preconditions (reject fast path)\n * 2. Backpressure detection: queue.pending > threshold -> degraded\n * 3. Concurrency gating via p-queue: bounded concurrency and queue capacity\n *\n * Uses queue.size for backpressure (queue depth = items waiting, not running).\n * Note: p-queue semantics differ from plan assumption -- pending = running, size = waiting.\n */\n\nimport PQueue from 'p-queue';\nimport type { EventEmitter } from 'eventemitter3';\nimport type { RoutingEventMap } from './events.js';\nimport type { AdmissionDecision } from './types.js';\n\n/**\n * Context for hard reject checks.\n * All fields are readonly -- pure input for the pure checkHardRejects function.\n */\nexport interface AdmissionContext {\n readonly hasEligibleTargets: boolean;\n readonly operatorPaused: boolean;\n readonly retryBudgetRemaining: number;\n readonly failoverBudgetRemaining: number;\n}\n\n/**\n * Configuration for the admission controller.\n */\nexport interface AdmissionConfig {\n readonly concurrencyLimit: number;\n readonly queueLimit: number;\n readonly backpressureThreshold: number;\n}\n\n/**\n * Admission controller interface.\n *\n * admit() checks admission without executing.\n * execute() checks admission and runs the function through p-queue if admitted.\n */\nexport interface AdmissionController {\n admit(request_id: string, ctx: AdmissionContext): Promise<AdmissionDecision>;\n execute<T>(\n fn: () => Promise<T>,\n request_id: string,\n ctx: AdmissionContext,\n ): Promise<{ decision: AdmissionDecision; result?: T }>;\n readonly pending: number;\n readonly size: number;\n}\n\n/**\n * Layer 1: Pure hard reject checks.\n *\n * Returns an AdmissionDecision with result 'rejected' if any precondition\n * fails, or null if all checks pass (no hard reject).\n *\n * Check order:\n * 1. No eligible targets\n * 2. Operator pause active\n * 3. Retry budget exhausted\n * 4. Failover budget exhausted\n *\n * @param ctx - Admission context with current system state.\n * @returns Rejection decision or null if no hard reject applies.\n */\nexport const checkHardRejects = (\n ctx: AdmissionContext,\n): AdmissionDecision | null => {\n if (!ctx.hasEligibleTargets) {\n return { result: 'rejected', reason: 'no eligible targets available' };\n }\n if (ctx.operatorPaused) {\n return { result: 'rejected', reason: 'operator pause active' };\n }\n if (ctx.retryBudgetRemaining <= 0) {\n return { result: 'rejected', reason: 'retry budget exhausted' };\n }\n if (ctx.failoverBudgetRemaining <= 0) {\n return { result: 'rejected', reason: 'failover budget exhausted' };\n }\n return null;\n};\n\n/**\n * Creates a layered admission controller with p-queue integration.\n *\n * Layer 1: checkHardRejects (pure, fast path)\n * Layer 2: Backpressure detection (queue.pending vs threshold)\n * Layer 3: Queue capacity check and p-queue concurrency gating\n *\n * @param config - Admission controller configuration.\n * @param eventBus - Optional event bus for admission_decision events.\n * @returns AdmissionController instance.\n */\nexport const createAdmissionController = (\n config: AdmissionConfig,\n eventBus?: EventEmitter<RoutingEventMap>,\n): AdmissionController => {\n const queue = new PQueue({\n concurrency: config.concurrencyLimit,\n });\n\n const emitDecision = (\n request_id: string,\n decision: AdmissionDecision,\n ): void => {\n eventBus?.emit('admission_decision', {\n request_id,\n result: decision.result,\n reason: decision.reason,\n });\n };\n\n const controller: AdmissionController = {\n async admit(\n request_id: string,\n ctx: AdmissionContext,\n ): Promise<AdmissionDecision> {\n // Layer 1: Hard rejects\n const hardReject = checkHardRejects(ctx);\n if (hardReject) {\n emitDecision(request_id, hardReject);\n return hardReject;\n }\n\n // Layer 2: Backpressure detection\n // p-queue semantics: size = items waiting in queue, pending = currently running\n // Use size (queue depth) for backpressure detection\n if (queue.size > config.backpressureThreshold) {\n const decision: AdmissionDecision = {\n result: 'degraded',\n reason: `backpressure: ${queue.size} queued > ${config.backpressureThreshold} threshold`,\n };\n emitDecision(request_id, decision);\n return decision;\n }\n\n // Layer 3: Queue capacity check (total = waiting + running)\n const total = queue.size + queue.pending;\n if (total >= config.queueLimit + config.concurrencyLimit) {\n const decision: AdmissionDecision = {\n result: 'rejected',\n reason: `queue full: ${total} >= ${config.queueLimit + config.concurrencyLimit}`,\n };\n emitDecision(request_id, decision);\n return decision;\n }\n\n const decision: AdmissionDecision = {\n result: 'admitted',\n reason: 'capacity available',\n };\n emitDecision(request_id, decision);\n return decision;\n },\n\n async execute<T>(\n fn: () => Promise<T>,\n request_id: string,\n ctx: AdmissionContext,\n ): Promise<{ decision: AdmissionDecision; result?: T }> {\n const decision = await controller.admit(request_id, ctx);\n if (decision.result === 'rejected') {\n return { decision };\n }\n // For degraded, still execute but caller knows it's degraded\n const result = await queue.add(fn);\n return { decision, result: result as T };\n },\n\n get pending(): number {\n return queue.pending;\n },\n\n get size(): number {\n return queue.size;\n },\n };\n\n return controller;\n};\n","/**\n * Event bus log subscriber for routing events.\n *\n * Subscribes to all RoutingEventMap events and logs them via pino.\n * Per D-74: child logger with component context.\n * Per D-75: info for decisions, warn for degraded, debug for scoring.\n * Per D-79: circuit breaker transitions at info.\n * Per D-80: cooldown set/expired at info.\n * Per D-81: admission at info (admitted) or warn (rejected/degraded).\n */\n\nimport type pino from 'pino';\nimport type { EventEmitter } from 'eventemitter3';\nimport type { RoutingEventMap } from './events.js';\n\n/**\n * Creates a log subscriber for routing events.\n *\n * Subscribes to all 6 event types on the provided event bus and logs\n * each at the appropriate level using a child logger with component context.\n *\n * @param eventBus - Typed routing event bus.\n * @param logger - Base pino logger (child with component:'routing' is created).\n * @returns A dispose function that removes all listeners.\n */\nexport const createLogSubscriber = (\n eventBus: EventEmitter<RoutingEventMap>,\n logger: pino.Logger,\n): (() => void) => {\n const log = logger.child({ component: 'routing' });\n\n const onCircuitStateChange = (payload: {\n target_id: string;\n from: string;\n to: string;\n reason: string;\n }): void => {\n log.info(\n {\n event: 'circuit_state_change',\n target_id: payload.target_id,\n from: payload.from,\n to: payload.to,\n reason: payload.reason,\n },\n 'Circuit breaker transition',\n );\n };\n\n const onCooldownSet = (payload: {\n target_id: string;\n until_ms: number;\n error_class: string;\n }): void => {\n log.info(\n {\n event: 'cooldown_set',\n target_id: payload.target_id,\n duration_ms: payload.until_ms - Date.now(),\n error_class: payload.error_class,\n },\n 'Cooldown set',\n );\n };\n\n const onCooldownExpired = (payload: { target_id: string }): void => {\n log.info(\n {\n event: 'cooldown_expired',\n target_id: payload.target_id,\n },\n 'Cooldown expired',\n );\n };\n\n const onAdmissionDecision = (payload: {\n request_id: string;\n result: string;\n reason: string;\n }): void => {\n const fields = {\n event: 'admission_decision',\n request_id: payload.request_id,\n result: payload.result,\n reason: payload.reason,\n };\n\n if (payload.result === 'admitted' || payload.result === 'queued') {\n log.info(fields, 'Admission decision');\n } else {\n log.warn(fields, 'Admission decision');\n }\n };\n\n const onHealthUpdated = (payload: {\n target_id: string;\n old_score: number;\n new_score: number;\n }): void => {\n log.debug(\n {\n event: 'health_updated',\n target_id: payload.target_id,\n old_score: payload.old_score,\n new_score: payload.new_score,\n },\n 'Health score updated',\n );\n };\n\n const onTargetExcluded = (payload: {\n target_id: string;\n reason: string;\n }): void => {\n log.debug(\n {\n event: 'target_excluded',\n target_id: payload.target_id,\n reason: payload.reason,\n },\n 'Target excluded',\n );\n };\n\n eventBus.on('circuit_state_change', onCircuitStateChange);\n eventBus.on('cooldown_set', onCooldownSet);\n eventBus.on('cooldown_expired', onCooldownExpired);\n eventBus.on('admission_decision', onAdmissionDecision);\n eventBus.on('health_updated', onHealthUpdated);\n eventBus.on('target_excluded', onTargetExcluded);\n\n return () => {\n eventBus.off('circuit_state_change', onCircuitStateChange);\n eventBus.off('cooldown_set', onCooldownSet);\n eventBus.off('cooldown_expired', onCooldownExpired);\n eventBus.off('admission_decision', onAdmissionDecision);\n eventBus.off('health_updated', onHealthUpdated);\n eventBus.off('target_excluded', onTargetExcluded);\n };\n};\n","/**\n * Nested retry-failover orchestrator per D-19.\n *\n * Implements the two-loop structure:\n * - Outer loop: failover across targets (bounded by failoverBudget)\n * - Inner loop: retry on same target (bounded by retryBudget)\n *\n * Decision tree per attempt:\n * 1. Success -> return immediately, record success\n * 2. ModelUnavailable -> early failover (break inner, try next target)\n * 3. Non-retryable (Auth, Permission, Quota, Policy, Region) -> abort entirely\n * 4. Retryable + budget remaining -> retry with backoff\n * 5. Retryable + budget exhausted -> failover to next target\n *\n * Composes: selectTarget (policy engine), createRetryPolicy (retry),\n * circuit breakers, cooldown manager, concurrency tracker.\n */\n\nimport type { EventEmitter } from 'eventemitter3';\nimport type { RoutingEventMap } from './events.js';\nimport type {\n CircuitBreaker,\n RoutingWeights,\n SelectionRecord,\n ConcurrencyTrackerApi,\n} from './types.js';\nimport type { CooldownManager } from './cooldown.js';\nimport type { RegistrySnapshot, TargetState } from '../registry/types.js';\n\n/**\n * Minimal registry interface used by the failover orchestrator.\n * Decoupled from concrete TargetRegistry class for testability.\n */\nexport interface FailoverRegistry {\n getSnapshot(): RegistrySnapshot;\n recordObservation(id: string, observation: 0 | 1): void;\n updateLatency(id: string, ms: number): void;\n updateState(id: string, newState: TargetState): boolean;\n setCooldown(id: string, untilMs: number): void;\n}\nimport type pino from 'pino';\nimport type { ErrorClass } from '../errors/taxonomy.js';\nimport type { BackoffParams } from '../retry/backoff.js';\nimport { isRetryable, getTargetStateTransition } from '../errors/taxonomy.js';\nimport { selectTarget } from './policy-engine.js';\nimport { createRetryPolicy } from '../retry/retry-policy.js';\nimport { computeCooldownMs } from './cooldown.js';\n\n/**\n * Record of a single attempt within the failover loop.\n */\nexport interface FailoverAttempt {\n readonly target_id: string;\n /** 1-based attempt number within this target. */\n readonly attempt_no: number;\n /** 0-based failover iteration. */\n readonly failover_no: number;\n readonly outcome: 'success' | 'retry' | 'failover' | 'abort';\n readonly error_class?: string;\n readonly latency_ms: number;\n readonly selection: SelectionRecord;\n}\n\n/**\n * Result of the failover orchestrator: success with value or failure with reason.\n */\nexport type FailoverResult =\n | {\n readonly outcome: 'success';\n readonly target_id: string;\n readonly attempts: readonly FailoverAttempt[];\n readonly total_retries: number;\n readonly total_failovers: number;\n readonly value: unknown;\n }\n | {\n readonly outcome: 'failure';\n readonly reason: string;\n readonly attempts: readonly FailoverAttempt[];\n readonly total_retries: number;\n readonly total_failovers: number;\n readonly last_error_class?: string;\n };\n\n/**\n * Function type for executing a request attempt against a target.\n * Provided by the caller (Phase 3 execution layer).\n */\nexport type AttemptFn = (target_id: string) => Promise<{\n success: boolean;\n value?: unknown;\n error_class?: ErrorClass;\n latency_ms: number;\n}>;\n\n/**\n * Dependencies for the failover orchestrator.\n */\nexport interface FailoverDeps {\n readonly registry: FailoverRegistry;\n readonly circuitBreakers: ReadonlyMap<string, CircuitBreaker>;\n readonly concurrency: ConcurrencyTrackerApi;\n readonly cooldownManager: CooldownManager;\n readonly eventBus?: EventEmitter<RoutingEventMap>;\n readonly weights: RoutingWeights;\n readonly maxLatencyMs: number;\n readonly retryBudget: number;\n readonly failoverBudget: number;\n readonly backoffParams: BackoffParams;\n /** Optional pino logger for structured failover logging (Phase 8). */\n readonly logger?: pino.Logger;\n}\n\n/**\n * Failover orchestrator interface.\n */\nexport interface FailoverOrchestrator {\n execute(\n request_id: string,\n attemptFn: AttemptFn,\n requiredCapabilities: readonly string[],\n ): Promise<FailoverResult>;\n}\n\n/**\n * Creates a nested retry-failover orchestrator.\n *\n * The outer loop iterates up to failoverBudget + 1 targets.\n * The inner loop iterates up to retryBudget + 1 attempts per target.\n * Maximum theoretical attempts = (failoverBudget + 1) * (retryBudget + 1).\n *\n * @param deps - Orchestrator dependencies.\n * @returns FailoverOrchestrator instance.\n */\nexport const createFailoverOrchestrator = (\n deps: FailoverDeps,\n): FailoverOrchestrator => ({\n async execute(\n request_id: string,\n attemptFn: AttemptFn,\n requiredCapabilities: readonly string[],\n ): Promise<FailoverResult> {\n const log = deps.logger?.child({ component: 'failover', request_id });\n const attempts: FailoverAttempt[] = [];\n const failedTargets = new Set<string>();\n let totalRetries = 0;\n let totalFailovers = 0;\n let lastErrorClass: string | undefined;\n\n log?.info(\n { event: 'failover_start', retry_budget: deps.retryBudget, failover_budget: deps.failoverBudget },\n 'Failover loop started',\n );\n\n // Outer failover loop: iterate up to failoverBudget + 1 targets\n for (\n let failoverNo = 0;\n failoverNo <= deps.failoverBudget;\n failoverNo++\n ) {\n // Check for expired cooldowns before selecting\n deps.cooldownManager.checkExpired(Date.now());\n\n const snapshot = deps.registry.getSnapshot();\n const selection = selectTarget(\n snapshot,\n deps.circuitBreakers,\n requiredCapabilities,\n deps.weights,\n deps.maxLatencyMs,\n Date.now(),\n request_id,\n failedTargets,\n );\n\n if (!selection.selected) {\n log?.warn(\n { event: 'no_eligible_target', failover_no: failoverNo },\n 'No eligible target available',\n );\n return {\n outcome: 'failure',\n reason: 'no eligible target available',\n attempts,\n total_retries: totalRetries,\n total_failovers: totalFailovers,\n last_error_class: lastErrorClass,\n };\n }\n\n const targetId = selection.selected.target_id;\n const retryPolicy = createRetryPolicy(\n deps.retryBudget,\n deps.backoffParams,\n );\n\n // Inner retry loop: iterate up to retryBudget + 1 attempts on this target\n for (let retry = 0; retry <= deps.retryBudget; retry++) {\n const attemptNo = retry + 1;\n\n // Acquire concurrency slot\n const acquired = deps.concurrency.acquire(targetId);\n if (!acquired) {\n // No concurrency headroom -- treat as target failure, failover\n log?.warn(\n { event: 'concurrency_full', target_id: targetId, failover_no: failoverNo },\n 'No concurrency headroom — failing over',\n );\n failedTargets.add(targetId);\n break;\n }\n\n let attemptResult: Awaited<ReturnType<AttemptFn>>;\n try {\n attemptResult = await attemptFn(targetId);\n } finally {\n deps.concurrency.release(targetId);\n }\n\n if (attemptResult.success) {\n // Record success on circuit breaker and registry\n const cb = deps.circuitBreakers.get(targetId);\n if (cb) {\n await cb.recordSuccess();\n }\n deps.registry.recordObservation(targetId, 1);\n deps.registry.updateLatency(targetId, attemptResult.latency_ms);\n\n log?.info(\n { event: 'attempt_success', target_id: targetId, attempt_no: attemptNo, failover_no: failoverNo, latency_ms: attemptResult.latency_ms },\n 'Attempt succeeded',\n );\n\n attempts.push({\n target_id: targetId,\n attempt_no: attemptNo,\n failover_no: failoverNo,\n outcome: 'success',\n latency_ms: attemptResult.latency_ms,\n selection,\n });\n\n return {\n outcome: 'success',\n target_id: targetId,\n attempts,\n total_retries: totalRetries,\n total_failovers: totalFailovers,\n value: attemptResult.value,\n };\n }\n\n // Failure path\n const errorClass = attemptResult.error_class!;\n lastErrorClass = errorClass.class;\n const cb = deps.circuitBreakers.get(targetId);\n if (cb) {\n await cb.recordFailure();\n }\n deps.registry.recordObservation(targetId, 0);\n\n // Apply target state transition if applicable\n const stateTransition = getTargetStateTransition(errorClass);\n if (stateTransition) {\n deps.registry.updateState(targetId, stateTransition);\n }\n\n // Set cooldown for RateLimited\n if (errorClass.class === 'RateLimited') {\n const cooldownMs = computeCooldownMs(\n errorClass,\n retry,\n deps.backoffParams,\n deps.backoffParams.max_ms,\n );\n deps.cooldownManager.setCooldown(\n targetId,\n cooldownMs,\n errorClass.class,\n );\n }\n\n // ModelUnavailable -> early failover (D-19)\n if (errorClass.class === 'ModelUnavailable') {\n log?.info(\n { event: 'early_failover', target_id: targetId, error_class: errorClass.class, failover_no: failoverNo },\n 'Early failover — ModelUnavailable',\n );\n attempts.push({\n target_id: targetId,\n attempt_no: attemptNo,\n failover_no: failoverNo,\n outcome: 'failover',\n error_class: errorClass.class,\n latency_ms: attemptResult.latency_ms,\n selection,\n });\n failedTargets.add(targetId);\n totalFailovers++;\n break; // break inner retry loop -> next failover\n }\n\n // Non-retryable -> abort entirely (D-12)\n if (!isRetryable(errorClass)) {\n log?.warn(\n { event: 'abort', target_id: targetId, error_class: errorClass.class },\n 'Non-retryable error — aborting',\n );\n attempts.push({\n target_id: targetId,\n attempt_no: attemptNo,\n failover_no: failoverNo,\n outcome: 'abort',\n error_class: errorClass.class,\n latency_ms: attemptResult.latency_ms,\n selection,\n });\n return {\n outcome: 'failure',\n reason: `non-retryable: ${errorClass.class}`,\n attempts,\n total_retries: totalRetries,\n total_failovers: totalFailovers,\n last_error_class: errorClass.class,\n };\n }\n\n // Retryable: check budget via retry policy\n const decision = retryPolicy.decide(\n {\n error_class: errorClass,\n detection_mode: 'direct',\n confidence: 'high',\n raw_signal: { detection_mode: 'direct' },\n },\n retry,\n );\n\n if (decision.action === 'exhausted') {\n // Retry budget exhausted on this target -> failover\n log?.info(\n { event: 'retry_budget_exhausted', target_id: targetId, failover_no: failoverNo },\n 'Retry budget exhausted — failing over',\n );\n attempts.push({\n target_id: targetId,\n attempt_no: attemptNo,\n failover_no: failoverNo,\n outcome: 'failover',\n error_class: errorClass.class,\n latency_ms: attemptResult.latency_ms,\n selection,\n });\n failedTargets.add(targetId);\n totalFailovers++;\n break; // next failover\n }\n\n // Retry with delay\n attempts.push({\n target_id: targetId,\n attempt_no: attemptNo,\n failover_no: failoverNo,\n outcome: 'retry',\n error_class: errorClass.class,\n latency_ms: attemptResult.latency_ms,\n selection,\n });\n totalRetries++;\n\n if (decision.action === 'retry') {\n log?.info(\n { event: 'retry', target_id: targetId, attempt_no: attemptNo, error_class: errorClass.class, delay_ms: decision.delay_ms },\n 'Retrying after delay',\n );\n await new Promise((resolve) =>\n setTimeout(resolve, decision.delay_ms),\n );\n }\n }\n\n // Inner loop exhausted or broke for failover -- continue outer loop\n }\n\n // Failover budget exhausted\n log?.warn(\n { event: 'failover_budget_exhausted', total_retries: totalRetries, total_failovers: totalFailovers },\n 'Failover budget exhausted',\n );\n return {\n outcome: 'failure',\n reason: 'failover budget exhausted',\n attempts,\n total_retries: totalRetries,\n total_failovers: totalFailovers,\n last_error_class: lastErrorClass,\n };\n },\n});\n","/**\n * Append-only stream buffer with confirmed boundary per D-30.\n *\n * Accumulates StreamChunks during a streaming response.\n * On interruption, confirmed() returns all chunks received so far,\n * and snapshot() returns the concatenated confirmed text for\n * stream stitching.\n */\n\nimport type { StreamChunk, StreamBuffer } from './types.js';\n\n/**\n * Creates a new StreamBuffer instance.\n *\n * The buffer is append-only: chunks can be added but never removed.\n * This preserves a reliable confirmed boundary for stream resume.\n *\n * @returns A StreamBuffer instance.\n */\nexport const createStreamBuffer = (): StreamBuffer => {\n const chunks: StreamChunk[] = [];\n\n return {\n /**\n * Appends a chunk to the buffer.\n *\n * @param chunk - The stream chunk to append.\n * @returns The index of the appended chunk (0-based).\n */\n append(chunk: StreamChunk): number {\n chunks.push(chunk);\n return chunks.length - 1;\n },\n\n /**\n * Returns a readonly copy of all accumulated chunks.\n *\n * The returned array is a shallow copy; mutations to it\n * do not affect the internal buffer.\n *\n * @returns Readonly array of confirmed chunks.\n */\n confirmed(): readonly StreamChunk[] {\n return [...chunks];\n },\n\n /**\n * Returns the total character count across all confirmed chunks.\n *\n * Used to compute visible_offset for segment provenance.\n *\n * @returns Total character count.\n */\n confirmedCharCount(): number {\n return chunks.reduce((sum, c) => sum + c.text.length, 0);\n },\n\n /**\n * Returns the concatenated text of all confirmed chunks.\n *\n * This is the confirmed output that can be preserved on\n * interruption and used as prefix for stream stitching.\n *\n * @returns Concatenated confirmed text.\n */\n snapshot(): string {\n return chunks.map((c) => c.text).join('');\n },\n };\n};\n","/**\n * Multi-segment stream stitcher with provenance metadata per D-31 through D-33.\n *\n * Assembles output from multiple segments (potentially from different targets\n * after failover) into a single StitchedOutput with per-segment provenance\n * and continuation boundary markers.\n *\n * Cross-target continuations are annotated as non_deterministic per D-33/TRAN-02\n * because the output may not be semantically consistent across model boundaries.\n */\n\nimport type {\n ContinuationMode,\n SegmentProvenance,\n StitchedOutput,\n StreamBuffer,\n} from './types.js';\n\n/**\n * StreamStitcher interface for assembling multi-segment output.\n */\nexport interface StreamStitcher {\n addSegment(\n buffer: StreamBuffer,\n provenance: Omit<SegmentProvenance, 'visible_offset'>,\n ): void;\n assemble(): StitchedOutput;\n segmentCount(): number;\n}\n\n/**\n * Internal segment entry combining text with full provenance.\n */\ninterface SegmentEntry {\n readonly text: string;\n readonly provenance: SegmentProvenance;\n}\n\n/**\n * Determines the continuation mode based on target and model relationship per D-31.\n *\n * - Same target: same_target_resume (deterministic)\n * - Different target, same model: same_model_alternate_target\n * - Different target, different model: cross_model_semantic (non-deterministic)\n *\n * Note: controlled_reexecution is set by the orchestrator when no viable\n * continuation target exists, not by the stitcher.\n *\n * @param oldTargetId - The target ID of the previous segment.\n * @param newTargetId - The target ID of the new segment.\n * @param sameModel - Whether both targets serve the same model.\n * @returns The appropriate ContinuationMode.\n */\nexport const determineContinuationMode = (\n oldTargetId: string,\n newTargetId: string,\n sameModel: boolean,\n): ContinuationMode => {\n if (oldTargetId === newTargetId) {\n return 'same_target_resume';\n }\n return sameModel ? 'same_model_alternate_target' : 'cross_model_semantic';\n};\n\n/**\n * Creates a new StreamStitcher instance.\n *\n * The stitcher accumulates segments via addSegment() and produces\n * a final StitchedOutput via assemble() with:\n * - Concatenated text from all segments\n * - Per-segment provenance with computed visible_offset\n * - continuation_boundaries marking join points between segments\n *\n * @param _requestId - The correlation request ID (reserved for future audit use).\n * @returns A StreamStitcher instance.\n */\nexport const createStreamStitcher = (_requestId: string): StreamStitcher => {\n const segments: SegmentEntry[] = [];\n\n return {\n /**\n * Adds a segment to the stitcher.\n *\n * Computes visible_offset as the cumulative character count\n * of all previously added segments.\n *\n * @param buffer - The stream buffer containing the segment's chunks.\n * @param provenance - Segment provenance without visible_offset (computed here).\n */\n addSegment(\n buffer: StreamBuffer,\n provenance: Omit<SegmentProvenance, 'visible_offset'>,\n ): void {\n const visibleOffset = segments.reduce(\n (sum, entry) => sum + entry.text.length,\n 0,\n );\n segments.push({\n text: buffer.snapshot(),\n provenance: { ...provenance, visible_offset: visibleOffset },\n });\n },\n\n /**\n * Assembles the final stitched output.\n *\n * @returns StitchedOutput with concatenated text, segments, and boundaries.\n */\n assemble(): StitchedOutput {\n const text = segments.map((s) => s.text).join('');\n const provenanceList = segments.map((s) => s.provenance);\n const continuationBoundaries = provenanceList\n .slice(1)\n .map((p) => p.visible_offset);\n\n return {\n text,\n segments: provenanceList,\n continuation_boundaries: continuationBoundaries,\n };\n },\n\n /**\n * Returns the number of segments added so far.\n *\n * @returns Segment count.\n */\n segmentCount(): number {\n return segments.length;\n },\n };\n};\n","/**\n * Audit collector for per-request audit trail accumulation.\n *\n * Subscribes to routing events and accumulates FailoverAttempt\n * and SegmentProvenance records per request. On flush(), emits\n * a complete AuditRecord to pino with all AUDT-02 fields\n * (request_id, attempt_no, segment_no, selected_target, candidates,\n * selection_reason, failure_class, retry_no, failover_no, latency_ms, outcome).\n *\n * flush() is always called in a finally block even on zero-attempt\n * failures per Pitfall 3.\n */\n\nimport type pino from 'pino';\nimport type { FailoverAttempt } from '../routing/failover.js';\nimport type { SegmentProvenance } from './types.js';\nimport { createRequestLogger } from '../audit/logger.js';\n\n/**\n * AuditCollector interface for accumulating and flushing audit records.\n *\n * Single-use per request: after flush(), the collector emits\n * its accumulated data and is considered complete.\n */\nexport interface AuditCollector {\n /** Records a failover attempt. */\n recordAttempt(attempt: FailoverAttempt): void;\n /** Records a segment provenance entry. */\n recordSegment(segment: SegmentProvenance): void;\n /** Flushes the accumulated audit record to pino. */\n flush(\n outcome: 'success' | 'failure',\n finalTarget?: string,\n stats?: { total_retries?: number; total_failovers?: number; latency_ms?: number },\n ): void;\n}\n\n/**\n * Creates an AuditCollector for a specific request.\n *\n * The collector accumulates FailoverAttempt and SegmentProvenance\n * records and flushes them as a single pino log entry with\n * event_type 'request_complete'.\n *\n * @param logger - The base pino logger (a child logger with request_id is created internally).\n * @param requestId - The correlation request ID for this request.\n * @returns An AuditCollector instance.\n */\nexport const createAuditCollector = (\n logger: pino.Logger,\n requestId: string,\n): AuditCollector => {\n const requestLogger = createRequestLogger(logger, requestId);\n const attempts: FailoverAttempt[] = [];\n const segments: SegmentProvenance[] = [];\n\n return {\n recordAttempt(attempt) {\n attempts.push(attempt);\n },\n\n recordSegment(segment) {\n segments.push(segment);\n },\n\n flush(outcome, finalTarget, stats) {\n requestLogger.info({\n event_type: 'request_complete',\n outcome,\n final_target: finalTarget,\n total_attempts: attempts.length,\n total_segments: segments.length,\n total_retries: stats?.total_retries,\n total_failovers: stats?.total_failovers,\n latency_ms: stats?.latency_ms,\n attempts: [...attempts],\n segments: [...segments],\n });\n },\n };\n};\n","/**\n * Execution orchestrator: wires ModeAdapter + FailoverOrchestrator +\n * StreamStitcher + AuditCollector into a single execute call.\n *\n * Produces ExecutionResult with full provenance metadata including\n * segments, continuation_modes, targets_involved, degraded flag (D-38),\n * and heuristic_detection flag (D-37).\n *\n * AuditCollector.flush() is ALWAYS called via try/finally even on\n * zero-attempt failures (Pitfall 3).\n */\n\nimport type pino from 'pino';\nimport type {\n ModeAdapter,\n AdapterRequest,\n AdapterResult,\n ExecutionResult,\n ExecutionProvenance,\n ContinuationMode,\n StreamBuffer,\n} from './types.js';\nimport type {\n FailoverOrchestrator,\n FailoverResult,\n} from '../routing/failover.js';\nimport type { DeploymentMode } from '../mode/types.js';\nimport { generateCorrelationId, createRequestLogger } from '../audit/logger.js';\nimport { createAuditCollector } from './audit-collector.js';\nimport { createStreamBuffer } from './stream-buffer.js';\nimport { createStreamStitcher } from './stream-stitcher.js';\n\n/**\n * Dependencies for the execution orchestrator.\n */\nexport interface ExecutionDeps {\n /** Mode adapter for executing requests against targets. */\n readonly adapter: ModeAdapter;\n /** Failover orchestrator for retry-failover logic. */\n readonly failover: FailoverOrchestrator;\n /** Base pino logger for audit trail. */\n readonly logger: pino.Logger;\n /** Current deployment mode. */\n readonly mode: DeploymentMode;\n}\n\n/**\n * Execution orchestrator interface.\n */\nexport interface ExecutionOrchestrator {\n /** Executes a request through the full pipeline. */\n execute(request: AdapterRequest): Promise<ExecutionResult>;\n}\n\n/**\n * Internal value carried through the failover loop.\n *\n * Captures the adapter result and stream buffer from a successful attempt.\n */\ninterface AttemptValue {\n readonly buffer: StreamBuffer;\n readonly adapterResult: AdapterResult;\n}\n\n/**\n * Creates an execution orchestrator that composes adapter, failover,\n * stream stitcher, and audit collector into an end-to-end pipeline.\n *\n * @param deps - Execution dependencies.\n * @returns An ExecutionOrchestrator instance.\n */\nexport const createExecutionOrchestrator = (\n deps: ExecutionDeps,\n): ExecutionOrchestrator => ({\n async execute(request: AdapterRequest): Promise<ExecutionResult> {\n const requestId = request.request_id || generateCorrelationId();\n const auditCollector = createAuditCollector(deps.logger, requestId);\n const stitcher = createStreamStitcher(requestId);\n const startMs = Date.now();\n\n const heuristicFlags: boolean[] = [];\n let outcome: 'success' | 'failure' = 'failure';\n let finalTarget: string | undefined;\n let summaryAttempts = 0;\n let summaryRetries = 0;\n let summaryFailovers = 0;\n let summaryTargets: string[] = [];\n\n try {\n const failoverResult: FailoverResult = await deps.failover.execute(\n requestId,\n async (targetId) => {\n const buffer = createStreamBuffer();\n const adapterResult = await deps.adapter.execute(targetId, request);\n\n // Accumulate chunks into buffer\n for (const chunk of adapterResult.chunks) {\n buffer.append(chunk);\n }\n\n heuristicFlags.push(\n adapterResult.detection_mode === 'heuristic',\n );\n\n const value: AttemptValue = { buffer, adapterResult };\n return {\n success: adapterResult.success,\n value,\n error_class: adapterResult.error_class,\n latency_ms: adapterResult.latency_ms,\n };\n },\n [],\n );\n\n // Record all attempts to audit collector\n for (const attempt of failoverResult.attempts) {\n auditCollector.recordAttempt(attempt);\n }\n\n // Capture summary data for finally-block logging\n summaryAttempts = failoverResult.attempts.length;\n summaryRetries = failoverResult.total_retries;\n summaryFailovers = failoverResult.total_failovers;\n summaryTargets = [...new Set(failoverResult.attempts.map((a) => a.target_id))];\n\n if (failoverResult.outcome === 'success') {\n outcome = 'success';\n finalTarget = failoverResult.target_id;\n const attemptValue = failoverResult.value as AttemptValue;\n\n // Add segment to stitcher\n const continuationMode: ContinuationMode =\n stitcher.segmentCount() === 0\n ? 'same_target_resume'\n : 'same_target_resume';\n\n stitcher.addSegment(attemptValue.buffer, {\n request_id: requestId,\n segment_id: stitcher.segmentCount(),\n source_target_id: failoverResult.target_id,\n continuation_mode: continuationMode,\n non_deterministic: false,\n });\n\n const segmentProvenance = stitcher.assemble().segments;\n for (const seg of segmentProvenance) {\n auditCollector.recordSegment(seg);\n }\n\n const stitchedOutput = stitcher.assemble();\n const isDegraded = deps.mode === 'plugin-only';\n const isHeuristic = heuristicFlags.some(Boolean);\n\n const uniqueModes = [\n ...new Set(stitchedOutput.segments.map((s) => s.continuation_mode)),\n ];\n const uniqueTargets = [\n ...new Set(stitchedOutput.segments.map((s) => s.source_target_id)),\n ];\n\n const provenance: ExecutionProvenance = {\n request_id: requestId,\n segments: stitchedOutput.segments,\n continuation_modes: uniqueModes,\n targets_involved: uniqueTargets,\n total_attempts: failoverResult.attempts.length,\n degraded: isDegraded,\n degraded_reason: isDegraded\n ? 'plugin-only mode: limited failover capability'\n : undefined,\n heuristic_detection: isHeuristic,\n };\n\n return {\n success: true,\n output: stitchedOutput.text,\n provenance,\n };\n }\n\n // Failure path\n const isDegraded = deps.mode === 'plugin-only';\n const isHeuristic = heuristicFlags.some(Boolean);\n\n const provenance: ExecutionProvenance = {\n request_id: requestId,\n segments: [],\n continuation_modes: [],\n targets_involved: [],\n total_attempts: failoverResult.attempts.length,\n degraded: isDegraded,\n degraded_reason: isDegraded\n ? 'plugin-only mode: limited failover capability'\n : undefined,\n heuristic_detection: isHeuristic,\n };\n\n return {\n success: false,\n output: '',\n provenance,\n };\n } finally {\n auditCollector.flush(outcome, finalTarget);\n\n // Per-request summary log (D-83)\n const requestLogger = createRequestLogger(deps.logger, requestId);\n const endMs = Date.now();\n requestLogger.info({\n event: 'request_summary',\n component: 'execution',\n outcome,\n total_attempts: summaryAttempts,\n total_failovers: summaryFailovers,\n total_retries: summaryRetries,\n latency_ms: endMs - startMs,\n targets_used: summaryTargets,\n final_target: finalTarget ?? null,\n }, 'Request complete');\n }\n },\n});\n","/**\n * Plugin-only mode adapter per D-27, D-28.\n *\n * In plugin-only mode, the adapter operates within OpenCode's plugin lifecycle.\n * The chat.params hook is param-adjust-only (D-16, D-28): it can adjust\n * temperature, topP, topK, maxOutputTokens, and options but CANNOT redirect\n * requests to different providers or models.\n *\n * Error detection is heuristic-only because plugin-only mode lacks access\n * to raw HTTP status codes (Pitfall 1). Classification is based on\n * error message patterns from the chat.message error event.\n *\n * This adapter is a stub for Phase 3. The real implementation requires\n * integration with OpenCode plugin lifecycle hooks (chat.params, chat.message)\n * which cannot be unit-tested in isolation. The interface contract is\n * established here; full wiring happens in Phase 4 integration testing.\n */\n\nimport type { ModeAdapter, AdapterRequest, AdapterResult } from '../types.js';\nimport type { AdapterDeps } from './types.js';\n\n/**\n * Creates a plugin-only mode adapter.\n *\n * Per D-50, D-51: targetId maps to TargetEntry.profile for credential resolution.\n * The adapter receives target_id which encodes the profile. The credential lookup\n * uses the registry's TargetEntry.profile to resolve the correct auth entry from\n * OpenCode's provider context.\n *\n * @param _deps - Adapter dependencies (classifier, reserved for Phase 4 wiring).\n * @returns A ModeAdapter for plugin-only deployment mode.\n */\nexport const createPluginAdapter = (_deps: AdapterDeps): ModeAdapter => ({\n /**\n * Executes a request in plugin-only mode.\n *\n * Phase 3 stub: returns a not-yet-implemented result.\n * Phase 4 will wire this to OpenCode plugin lifecycle hooks.\n *\n * @param _targetId - The target to execute against.\n * @param _request - The adapter request payload.\n * @returns AdapterResult with heuristic detection mode.\n */\n async execute(\n _targetId: string,\n _request: AdapterRequest,\n ): Promise<AdapterResult> {\n const start = Date.now();\n return {\n success: false,\n chunks: [],\n error_class: undefined,\n latency_ms: Date.now() - start,\n detection_mode: 'heuristic' as const,\n };\n },\n});\n","/**\n * Server-companion mode adapter per D-27, D-29.\n *\n * In server-companion mode, the adapter communicates with the OpenCode\n * server's HTTP/WebSocket API via the @opencode-ai/sdk client.\n *\n * Error detection is direct: the SDK's ApiError provides statusCode\n * and responseHeaders (including Retry-After) for precise classification\n * (per Pitfall 5).\n *\n * This adapter is a stub for Phase 3. The real implementation requires\n * an HTTP client to the companion server, which is wired in Phase 4\n * integration testing.\n */\n\nimport type { ModeAdapter, AdapterRequest, AdapterResult } from '../types.js';\nimport type { AdapterDeps } from './types.js';\n\n/**\n * Creates a server-companion mode adapter.\n *\n * Per D-51: targetId maps to TargetEntry.profile. Server/SDK adapters pass the\n * profile identifier to the OpenCode SDK for credential lookup, enabling\n * per-profile authentication when multiple auth profiles exist for the same provider.\n *\n * @param _deps - Adapter dependencies (classifier, reserved for Phase 4 wiring).\n * @returns A ModeAdapter for server-companion deployment mode.\n */\nexport const createServerAdapter = (_deps: AdapterDeps): ModeAdapter => ({\n /**\n * Executes a request in server-companion mode.\n *\n * Phase 3 stub: returns a not-yet-implemented result.\n * Phase 4 will wire this to the OpenCode SDK client, extracting\n * statusCode, responseHeaders['retry-after'], and responseBody\n * from SDK ApiError for direct error classification.\n *\n * @param _targetId - The target to execute against.\n * @param _request - The adapter request payload.\n * @returns AdapterResult with direct detection mode.\n */\n async execute(\n _targetId: string,\n _request: AdapterRequest,\n ): Promise<AdapterResult> {\n const start = Date.now();\n return {\n success: false,\n chunks: [],\n error_class: undefined,\n latency_ms: Date.now() - start,\n detection_mode: 'direct' as const,\n };\n },\n});\n","/**\n * SDK-control mode adapter per D-27, D-29.\n *\n * In SDK-control mode, the adapter uses the @opencode-ai/sdk client\n * to directly control the OpenCode server, managing sessions,\n * provider selection, and auth credential injection.\n *\n * Error detection is direct: the SDK provides full HTTP status codes\n * and response headers for precise error classification.\n *\n * This adapter is a stub for Phase 3. The real implementation requires\n * the OpenCode SDK client with session management, which is wired\n * in Phase 4 integration testing.\n */\n\nimport type { ModeAdapter, AdapterRequest, AdapterResult } from '../types.js';\nimport type { AdapterDeps } from './types.js';\n\n/**\n * Creates an SDK-control mode adapter.\n *\n * @param _deps - Adapter dependencies (classifier, reserved for Phase 4 wiring).\n * @returns A ModeAdapter for SDK-control deployment mode.\n */\nexport const createSdkAdapter = (_deps: AdapterDeps): ModeAdapter => ({\n /**\n * Executes a request in SDK-control mode.\n *\n * Phase 3 stub: returns a not-yet-implemented result.\n * Phase 4 will wire this to the OpenCode SDK client with full\n * session management and provider control capabilities.\n *\n * @param _targetId - The target to execute against.\n * @param _request - The adapter request payload.\n * @returns AdapterResult with direct detection mode.\n */\n async execute(\n _targetId: string,\n _request: AdapterRequest,\n ): Promise<AdapterResult> {\n const start = Date.now();\n return {\n success: false,\n chunks: [],\n error_class: undefined,\n latency_ms: Date.now() - start,\n detection_mode: 'direct' as const,\n };\n },\n});\n","/**\n * Adapter factory: selects the correct ModeAdapter by DeploymentMode.\n *\n * Provides a single entry point for creating the appropriate adapter\n * based on the resolved deployment mode. Uses exhaustive switch\n * with never default for type safety.\n */\n\nimport type { DeploymentMode } from '../../mode/types.js';\nimport type { ModeAdapter } from '../types.js';\nimport type { AdapterDeps } from './types.js';\nimport { createPluginAdapter } from './plugin-adapter.js';\nimport { createServerAdapter } from './server-adapter.js';\nimport { createSdkAdapter } from './sdk-adapter.js';\n\n/**\n * Creates the appropriate ModeAdapter for the given deployment mode.\n *\n * @param mode - The resolved deployment mode.\n * @param deps - Shared adapter dependencies.\n * @returns The ModeAdapter implementation for the specified mode.\n * @throws Error if an unknown deployment mode is provided (compile-time exhaustive check).\n */\nexport const createModeAdapter = (\n mode: DeploymentMode,\n deps: AdapterDeps,\n): ModeAdapter => {\n switch (mode) {\n case 'plugin-only':\n return createPluginAdapter(deps);\n case 'server-companion':\n return createServerAdapter(deps);\n case 'sdk-control':\n return createSdkAdapter(deps);\n default: {\n const _exhaustive: never = mode;\n throw new Error(`Unknown deployment mode: ${String(_exhaustive)}`);\n }\n }\n};\n","/**\n * Config reload with diff-apply logic per D-42, D-43.\n *\n * computeConfigDiff: Three-pass diff (added, removed, modified) per Pitfall 4.\n * applyConfigDiff: Applies diff to registry. Removed targets are Disabled\n * (not deleted) to protect in-flight requests per Pitfall 1.\n */\n\nimport type { SwitcherConfig, TargetConfig } from '../config/schema.js';\nimport type { TargetRegistry } from '../registry/registry.js';\nimport { INITIAL_HEALTH_SCORE } from '../registry/health.js';\nimport type { TargetEntry, TargetState } from '../registry/types.js';\n\n/** The result of diffing old and new configuration. */\nexport interface ConfigDiff {\n readonly added: readonly TargetConfig[];\n readonly removed: readonly string[];\n readonly modified: readonly TargetConfig[];\n}\n\n/**\n * Computes a three-pass diff between old and new configs per Pitfall 4.\n *\n * Pass 1: Find targets in newConfig not in oldConfig (added)\n * Pass 2: Find targets in oldConfig not in newConfig (removed)\n * Pass 3: For intersection, compare mutable fields (modified)\n */\nexport const computeConfigDiff = (\n oldConfig: SwitcherConfig,\n newConfig: SwitcherConfig,\n): ConfigDiff => {\n const oldTargets = oldConfig.targets ?? [];\n const newTargets = newConfig.targets ?? [];\n const oldIds = new Set(oldTargets.map((t) => t.target_id));\n const newIds = new Set(newTargets.map((t) => t.target_id));\n const oldMap = new Map(oldTargets.map((t) => [t.target_id, t]));\n\n const added = newTargets.filter((t) => !oldIds.has(t.target_id));\n const removed = oldTargets\n .filter((t) => !newIds.has(t.target_id))\n .map((t) => t.target_id);\n\n const modified = newTargets.filter((t) => {\n if (!oldIds.has(t.target_id)) {\n return false;\n }\n const old = oldMap.get(t.target_id);\n if (!old) {\n return false;\n }\n return hasConfigChanged(old, t);\n });\n\n return { added, removed, modified };\n};\n\n/** Checks whether mutable config fields have changed between two target configs. */\nconst hasConfigChanged = (\n oldTarget: TargetConfig,\n newTarget: TargetConfig,\n): boolean => {\n if (oldTarget.profile !== newTarget.profile) return true;\n if (oldTarget.enabled !== newTarget.enabled) return true;\n if (oldTarget.operator_priority !== newTarget.operator_priority) return true;\n if (JSON.stringify(oldTarget.policy_tags) !== JSON.stringify(newTarget.policy_tags)) return true;\n if (JSON.stringify(oldTarget.capabilities) !== JSON.stringify(newTarget.capabilities)) return true;\n if (oldTarget.retry_budget !== newTarget.retry_budget) return true;\n if (oldTarget.failover_budget !== newTarget.failover_budget) return true;\n if (oldTarget.concurrency_limit !== newTarget.concurrency_limit) return true;\n return false;\n};\n\n/**\n * Applies a config diff to the registry.\n *\n * - Added targets: creates fresh TargetEntry with INITIAL_HEALTH_SCORE\n * - Removed targets: sets state to Disabled (not deleted) per Pitfall 1\n * - Modified targets: rebuilds entry with updated config fields\n */\nexport const applyConfigDiff = (\n registry: TargetRegistry,\n diff: ConfigDiff,\n): void => {\n // Add new targets\n for (const tc of diff.added) {\n const entry: TargetEntry = {\n target_id: tc.target_id,\n provider_id: tc.provider_id,\n profile: tc.profile,\n endpoint_id: tc.endpoint_id,\n capabilities: [...tc.capabilities],\n enabled: tc.enabled,\n state: 'Active' as TargetState,\n health_score: INITIAL_HEALTH_SCORE,\n cooldown_until: null,\n latency_ema_ms: 0,\n failure_score: 0,\n operator_priority: tc.operator_priority,\n policy_tags: [...tc.policy_tags],\n };\n registry.addTarget(entry);\n }\n\n // Disable removed targets (not delete -- protect in-flight requests)\n for (const id of diff.removed) {\n registry.updateState(id, 'Disabled');\n }\n\n // Update modified targets by removing and re-adding with updated config\n for (const tc of diff.modified) {\n const existing = registry.getTarget(tc.target_id);\n if (existing) {\n // Preserve runtime state (health_score, latency, failure_score, cooldown)\n // but update config-driven fields\n const updated: TargetEntry = {\n ...existing,\n provider_id: tc.provider_id,\n profile: tc.profile,\n endpoint_id: tc.endpoint_id,\n capabilities: [...tc.capabilities],\n enabled: tc.enabled,\n operator_priority: tc.operator_priority,\n policy_tags: [...tc.policy_tags],\n };\n registry.removeTarget(tc.target_id);\n registry.addTarget(updated);\n }\n }\n};\n","/**\n * Pure operator command functions per D-39.\n *\n * All commands take OperatorDeps and return structured results.\n * No separate operator state -- all mutations go through TargetRegistry (D-40).\n * All commands work without code changes (OPER-05) -- they are runtime function calls.\n */\n\nimport type {\n OperatorDeps,\n ListTargetsResult,\n TargetActionResult,\n InspectResult,\n ReloadResult,\n RequestTraceBuffer,\n RequestTraceEntry,\n TargetView,\n} from './types.js';\nimport type { TargetState } from '../registry/types.js';\nimport { computeConfigDiff, applyConfigDiff } from './reload.js';\nimport { validateConfig } from '../config/loader.js';\nimport { ConfigValidationError } from '../config/loader.js';\n\n/**\n * Creates a ring buffer for request trace storage.\n *\n * Uses Map for O(1) lookup and array for insertion order tracking.\n * When size exceeds capacity, oldest entries are evicted.\n *\n * @param capacity - Maximum number of entries to store.\n */\nexport const createRequestTraceBuffer = (\n capacity: number,\n): RequestTraceBuffer => {\n const entries = new Map<string, RequestTraceEntry>();\n const order: string[] = [];\n\n return {\n record(entry: RequestTraceEntry): void {\n // If this request_id already exists, remove from order tracking\n if (entries.has(entry.request_id)) {\n const idx = order.indexOf(entry.request_id);\n if (idx !== -1) {\n order.splice(idx, 1);\n }\n }\n\n // Evict oldest if at capacity\n while (order.length >= capacity) {\n const oldest = order.shift();\n if (oldest !== undefined) {\n entries.delete(oldest);\n }\n }\n\n entries.set(entry.request_id, entry);\n order.push(entry.request_id);\n },\n\n lookup(requestId: string): RequestTraceEntry | undefined {\n return entries.get(requestId);\n },\n\n size(): number {\n return entries.size;\n },\n };\n};\n\n/**\n * Lists all targets with enriched circuit breaker state.\n * Per D-39: returns target_id, state, health_score, circuit_breaker_state,\n * cooldown_until, enabled, latency_ema_ms, failure_score, operator_priority.\n */\nexport const listTargets = (deps: OperatorDeps): ListTargetsResult => {\n const allTargets = deps.registry.getAllTargets();\n const targets: ReadonlyArray<TargetView> = allTargets.map((t) => {\n const cb = deps.circuitBreakers.get(t.target_id);\n const cbState: TargetState = cb ? cb.state() : 'Active';\n return {\n target_id: t.target_id,\n provider_id: t.provider_id,\n profile: t.profile,\n state: t.state,\n health_score: t.health_score,\n circuit_breaker_state: cbState,\n cooldown_until: t.cooldown_until,\n enabled: t.enabled,\n latency_ema_ms: t.latency_ema_ms,\n failure_score: t.failure_score,\n operator_priority: t.operator_priority,\n };\n });\n\n return { targets, count: targets.length };\n};\n\n/** Helper to create a target action result. */\nconst targetAction = (\n deps: OperatorDeps,\n targetId: string,\n action: string,\n newState: TargetState,\n): TargetActionResult => {\n const updated = deps.registry.updateState(targetId, newState);\n if (!updated) {\n return { success: false, target_id: targetId, action, error: 'target not found' };\n }\n return { success: true, target_id: targetId, action };\n};\n\n/** Pauses a target by setting state to Disabled. Per research: reuse Disabled with semantic action name. */\nexport const pauseTarget = (\n deps: OperatorDeps,\n targetId: string,\n): TargetActionResult => targetAction(deps, targetId, 'pause', 'Disabled');\n\n/** Resumes a target by setting state to Active. */\nexport const resumeTarget = (\n deps: OperatorDeps,\n targetId: string,\n): TargetActionResult => targetAction(deps, targetId, 'resume', 'Active');\n\n/** Drains a target by setting state to Draining. No new requests will be routed. */\nexport const drainTarget = (\n deps: OperatorDeps,\n targetId: string,\n): TargetActionResult => targetAction(deps, targetId, 'drain', 'Draining');\n\n/** Disables a target by setting state to Disabled. */\nexport const disableTarget = (\n deps: OperatorDeps,\n targetId: string,\n): TargetActionResult => targetAction(deps, targetId, 'disable', 'Disabled');\n\n/** Inspects a request by looking up its trace in the ring buffer. */\nexport const inspectRequest = (\n deps: OperatorDeps,\n requestId: string,\n): InspectResult => {\n const trace = deps.traceBuffer.lookup(requestId);\n if (!trace) {\n return { found: false, request_id: requestId };\n }\n return { found: true, request_id: requestId, trace };\n};\n\n/**\n * Reloads configuration with diff-apply logic.\n *\n * 1. Validates raw config via validateConfig\n * 2. On validation failure: returns diagnostics, no changes applied (D-43)\n * 3. On success: computes diff, applies to registry, swaps config reference\n */\nexport const reloadConfig = (\n deps: OperatorDeps,\n rawConfig: unknown,\n): ReloadResult => {\n try {\n const newConfig = validateConfig(rawConfig);\n const currentConfig = deps.configRef.current();\n const diff = computeConfigDiff(currentConfig, newConfig);\n applyConfigDiff(deps.registry, diff);\n deps.configRef.swap(newConfig);\n\n return {\n success: true,\n added: diff.added.map((t) => t.target_id),\n removed: [...diff.removed],\n modified: diff.modified.map((t) => t.target_id),\n };\n } catch (err) {\n if (err instanceof ConfigValidationError) {\n return {\n success: false,\n added: [],\n removed: [],\n modified: [],\n diagnostics: err.diagnostics,\n };\n }\n throw err;\n }\n};\n","/**\n * Bearer token authentication middleware for server-companion mode.\n *\n * Per D-44: Server-companion mode operator endpoints require Bearer token\n * authentication. Plugin-only mode commands inherit OpenCode session auth.\n *\n * Per Pitfall 3: Uses crypto.timingSafeEqual for constant-time token\n * comparison to prevent timing attacks.\n */\n\nimport { timingSafeEqual } from 'node:crypto';\n\n/** Result of bearer token validation. */\nexport interface AuthResult {\n readonly authorized: boolean;\n readonly reason?: string;\n}\n\n/**\n * Validates a Bearer token from the Authorization header.\n *\n * @param authHeader - The raw Authorization header value, or undefined if absent.\n * @param expectedToken - The expected token to compare against.\n * @returns AuthResult indicating whether the request is authorized.\n */\nexport const validateBearerToken = (\n authHeader: string | undefined,\n expectedToken: string,\n): AuthResult => {\n if (authHeader === undefined) {\n return { authorized: false, reason: 'missing Authorization header' };\n }\n\n if (!authHeader.startsWith('Bearer ')) {\n return { authorized: false, reason: 'invalid Authorization scheme' };\n }\n\n const token = authHeader.slice(7); // 'Bearer '.length === 7\n\n // Length check before timingSafeEqual: the function requires equal-length\n // buffers. Different lengths immediately reveal mismatch without timing leak\n // because the length itself is not secret information.\n if (token.length !== expectedToken.length) {\n return { authorized: false, reason: 'invalid token' };\n }\n\n const tokenBuffer = Buffer.from(token);\n const expectedBuffer = Buffer.from(expectedToken);\n\n if (!timingSafeEqual(tokenBuffer, expectedBuffer)) {\n return { authorized: false, reason: 'invalid token' };\n }\n\n return { authorized: true };\n};\n","/**\n * OpenCode plugin tool wrappers for operator commands.\n *\n * Per D-39 and OPER-05: Each operator command is exposed as an OpenCode\n * plugin tool with Zod-validated args. Plugin tools return JSON-stringified\n * results from the pure command functions.\n *\n * Uses @opencode-ai/plugin/tool for tool definition with Zod schema.\n */\n\nimport { tool } from '@opencode-ai/plugin/tool';\nimport type { ToolDefinition } from '@opencode-ai/plugin/tool';\nimport type { OperatorDeps } from './types.js';\nimport {\n listTargets,\n pauseTarget,\n resumeTarget,\n drainTarget,\n disableTarget,\n inspectRequest,\n reloadConfig,\n} from './commands.js';\n\nconst { schema: z } = tool;\n\n/**\n * Creates operator tool definitions bound to the given dependencies.\n *\n * Each tool wraps a pure operator command function, validates args via Zod,\n * and returns JSON-stringified results.\n *\n * @param deps - Operator dependencies (registry, circuit breakers, config, logger, trace buffer).\n */\n/** Map of all operator tool definitions keyed by command name. */\nexport interface OperatorTools {\n readonly listTargets: ToolDefinition;\n readonly pauseTarget: ToolDefinition;\n readonly resumeTarget: ToolDefinition;\n readonly drainTarget: ToolDefinition;\n readonly disableTarget: ToolDefinition;\n readonly inspectRequest: ToolDefinition;\n readonly reloadConfig: ToolDefinition;\n}\n\nexport const createOperatorTools = (deps: OperatorDeps): OperatorTools => ({\n listTargets: tool({\n description:\n 'List all routing targets with health scores, states, and circuit breaker status.',\n args: {},\n async execute() {\n deps.logger.info({ op: 'listTargets' }, 'operator: listTargets');\n const result = listTargets(deps);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n pauseTarget: tool({\n description:\n 'Pause a target, preventing new requests from being routed to it.',\n args: { target_id: z.string().min(1) },\n async execute(args) {\n deps.logger.info(\n { op: 'pauseTarget', target_id: args.target_id },\n 'operator: pauseTarget',\n );\n const result = pauseTarget(deps, args.target_id);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n resumeTarget: tool({\n description:\n 'Resume a previously paused or disabled target, allowing new requests.',\n args: { target_id: z.string().min(1) },\n async execute(args) {\n deps.logger.info(\n { op: 'resumeTarget', target_id: args.target_id },\n 'operator: resumeTarget',\n );\n const result = resumeTarget(deps, args.target_id);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n drainTarget: tool({\n description:\n 'Drain a target, allowing in-flight requests to complete but preventing new ones.',\n args: { target_id: z.string().min(1) },\n async execute(args) {\n deps.logger.info(\n { op: 'drainTarget', target_id: args.target_id },\n 'operator: drainTarget',\n );\n const result = drainTarget(deps, args.target_id);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n disableTarget: tool({\n description: 'Disable a target entirely, removing it from routing.',\n args: { target_id: z.string().min(1) },\n async execute(args) {\n deps.logger.info(\n { op: 'disableTarget', target_id: args.target_id },\n 'operator: disableTarget',\n );\n const result = disableTarget(deps, args.target_id);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n inspectRequest: tool({\n description:\n 'Inspect a request trace by ID, showing attempts, segments, and outcome.',\n args: { request_id: z.string().min(1) },\n async execute(args) {\n deps.logger.info(\n { op: 'inspectRequest', request_id: args.request_id },\n 'operator: inspectRequest',\n );\n const result = inspectRequest(deps, args.request_id);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n reloadConfig: tool({\n description:\n 'Reload routing configuration with diff-apply. Validates new config before applying.',\n args: { config: z.record(z.string(), z.unknown()) },\n async execute(args) {\n deps.logger.info({ op: 'reloadConfig' }, 'operator: reloadConfig');\n const result = reloadConfig(deps, args.config);\n return JSON.stringify(result, null, 2);\n },\n }),\n});\n","/**\n * Profile store CRUD operations.\n *\n * Pure functions for in-memory store manipulation (addProfile, removeProfile,\n * listProfiles, nextProfileId) plus file I/O helpers (loadProfiles, saveProfiles).\n *\n * File writes are atomic: write to .tmp then rename (D-67).\n * Default paths target ~/.local/share/o-switcher/profiles.json (D-62).\n */\n\nimport { readFile, writeFile, rename, mkdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport type pino from 'pino';\nimport type { ProfileStore, AuthCredential, ProfileEntry } from './types.js';\n\n/** Default directory for O-Switcher profile storage. */\nexport const PROFILES_DIR = join(homedir(), '.local', 'share', 'o-switcher');\n\n/** Default path to the profiles JSON file. */\nexport const PROFILES_PATH = join(PROFILES_DIR, 'profiles.json');\n\n/**\n * Loads the profile store from disk.\n * Returns empty store if file does not exist.\n */\nexport const loadProfiles = async (\n path: string = PROFILES_PATH,\n): Promise<ProfileStore> => {\n try {\n const content = await readFile(path, 'utf-8');\n return JSON.parse(content) as ProfileStore;\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n return {};\n }\n throw err;\n }\n};\n\n/**\n * Saves the profile store to disk atomically.\n * Writes to a .tmp file first, then renames to the target path (D-67).\n * Creates parent directories if they do not exist.\n *\n * @param store - Profile store to persist.\n * @param path - Target file path.\n * @param logger - Optional pino logger for disk write logging.\n */\nexport const saveProfiles = async (\n store: ProfileStore,\n path: string = PROFILES_PATH,\n logger?: pino.Logger,\n): Promise<void> => {\n const dir = dirname(path);\n await mkdir(dir, { recursive: true });\n const tmpPath = `${path}.tmp`;\n await writeFile(tmpPath, JSON.stringify(store, null, 2), 'utf-8');\n await rename(tmpPath, path);\n logger?.info({ path }, 'Profiles saved to disk');\n};\n\n/**\n * Determines whether two credentials are identical.\n */\nconst credentialsMatch = (a: AuthCredential, b: AuthCredential): boolean => {\n if (a.type !== b.type) return false;\n if (a.type === 'api-key' && b.type === 'api-key') {\n return a.key === b.key;\n }\n if (a.type === 'oauth' && b.type === 'oauth') {\n return (\n a.refresh === b.refresh &&\n a.access === b.access &&\n a.expires === b.expires &&\n a.accountId === b.accountId\n );\n }\n return false;\n};\n\n/**\n * Adds a profile to the store. Pure function — returns a new store.\n *\n * Assigns a sequential ID via nextProfileId (e.g., openai-1, openai-2).\n * Skips if credentials match an existing entry for the same provider (dedup).\n */\nexport const addProfile = (\n store: ProfileStore,\n provider: string,\n credentials: AuthCredential,\n): ProfileStore => {\n // Check for duplicate credentials within the same provider\n const isDuplicate = Object.values(store).some(\n (entry) =>\n entry.provider === provider && credentialsMatch(entry.credentials, credentials),\n );\n if (isDuplicate) {\n return store;\n }\n\n const id = nextProfileId(store, provider);\n const entry: ProfileEntry = {\n id,\n provider,\n type: credentials.type,\n credentials,\n created: new Date().toISOString(),\n };\n return { ...store, [id]: entry };\n};\n\n/**\n * Removes a profile by ID. Pure function — returns new store and removal status.\n */\nexport const removeProfile = (\n store: ProfileStore,\n id: string,\n): { store: ProfileStore; removed: boolean } => {\n if (store[id] === undefined) {\n return { store, removed: false };\n }\n const { [id]: _removed, ...rest } = store;\n return { store: rest, removed: true };\n};\n\n/**\n * Lists all profiles sorted by created date (oldest first).\n */\nexport const listProfiles = (store: ProfileStore): ProfileEntry[] => {\n return Object.values(store).sort(\n (a, b) => new Date(a.created).getTime() - new Date(b.created).getTime(),\n );\n};\n\n/**\n * Computes the next sequential profile ID for a provider.\n *\n * Finds the maximum N in existing \"provider-N\" entries and returns \"provider-(N+1)\".\n * Returns \"provider-1\" when no profiles exist for the provider.\n */\nexport const nextProfileId = (\n store: ProfileStore,\n provider: string,\n): string => {\n const prefix = `${provider}-`;\n const maxN = Object.keys(store)\n .filter((key) => key.startsWith(prefix))\n .map((key) => Number(key.slice(prefix.length)))\n .filter((n) => !Number.isNaN(n))\n .reduce((max, n) => Math.max(max, n), 0);\n\n return `${provider}-${maxN + 1}`;\n};\n","/**\n * Auth.json file watcher with debounce and credential comparison.\n *\n * Watches OpenCode's auth.json for changes, saves the PREVIOUS credential\n * to O-Switcher's profile store before accepting the new one (D-65, D-66).\n *\n * On first run with empty profiles, initializes from current auth.json (D-72).\n * Debounce at 100ms collapses rapid fs.watch events (D-67).\n */\n\nimport { readFile, watch } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport type pino from 'pino';\nimport {\n loadProfiles,\n saveProfiles,\n addProfile,\n PROFILES_PATH,\n} from './store.js';\nimport type { ProfileStore, AuthCredential } from './types.js';\n\n/** Default path to OpenCode's auth.json. */\nexport const AUTH_JSON_PATH = join(\n homedir(),\n '.local',\n 'share',\n 'opencode',\n 'auth.json',\n);\n\n/** Debounce interval for fs.watch events (ms). Per D-67. */\nconst DEBOUNCE_MS = 100;\n\n/** Watcher interface with start/stop lifecycle. */\nexport interface AuthWatcher {\n start(): Promise<void>;\n stop(): void;\n}\n\n/** Options for creating an auth watcher. */\nexport interface AuthWatcherOptions {\n readonly authJsonPath?: string;\n readonly profilesPath?: string;\n readonly logger?: pino.Logger;\n}\n\n/** Parsed auth.json entry shape. */\ninterface AuthEntry {\n readonly type?: string;\n readonly [key: string]: unknown;\n}\n\n/** Parsed auth.json content. */\ntype AuthJson = Record<string, AuthEntry>;\n\n/**\n * Reads auth.json from disk. Returns empty object if missing or unreadable.\n */\nconst readAuthJson = async (path: string): Promise<AuthJson> => {\n try {\n const content = await readFile(path, 'utf-8');\n return JSON.parse(content) as AuthJson;\n } catch {\n return {};\n }\n};\n\n/**\n * Converts an auth.json entry to an AuthCredential.\n */\nconst toCredential = (entry: AuthEntry): AuthCredential => {\n if (entry.type === 'oauth' || (entry.refresh !== undefined && entry.access !== undefined)) {\n return {\n type: 'oauth',\n refresh: String(entry.refresh ?? ''),\n access: String(entry.access ?? ''),\n expires: Number(entry.expires ?? 0),\n accountId: entry.accountId !== undefined ? String(entry.accountId) : undefined,\n };\n }\n return {\n type: 'api-key',\n key: String(entry.key ?? ''),\n };\n};\n\n/**\n * Compares two auth entries for deep equality (JSON serialization).\n */\nconst entriesEqual = (a: AuthEntry | undefined, b: AuthEntry | undefined): boolean => {\n if (a === undefined && b === undefined) return true;\n if (a === undefined || b === undefined) return false;\n return JSON.stringify(a) === JSON.stringify(b);\n};\n\n/**\n * Creates a file watcher for OpenCode's auth.json.\n *\n * Watches for credential changes and saves previous credentials to the\n * O-Switcher profile store before they are overwritten.\n */\nexport const createAuthWatcher = (options?: AuthWatcherOptions): AuthWatcher => {\n const authPath = options?.authJsonPath ?? AUTH_JSON_PATH;\n const profPath = options?.profilesPath ?? PROFILES_PATH;\n const log = options?.logger?.child({ component: 'profile-watcher' });\n\n let lastKnownAuth: AuthJson = {};\n let abortController: AbortController | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let watchPromise: Promise<void> | null = null;\n\n /**\n * Processes a detected change in auth.json.\n * For each provider entry that changed, saves the PREVIOUS credential.\n */\n const processChange = async (): Promise<void> => {\n const newAuth = await readAuthJson(authPath);\n let store = await loadProfiles(profPath);\n let changed = false;\n\n for (const [provider, entry] of Object.entries(newAuth)) {\n if (!entry) continue;\n\n const previousEntry = lastKnownAuth[provider];\n\n if (previousEntry !== undefined && !entriesEqual(previousEntry, entry)) {\n // Credential changed — save the PREVIOUS credential\n log?.info({ provider, action: 'credential_changed' }, 'Credential change detected — saving previous credential');\n const prevCredential = toCredential(previousEntry);\n const newStore = addProfile(store, provider, prevCredential);\n if (newStore !== store) {\n store = newStore;\n changed = true;\n }\n } else if (previousEntry === undefined) {\n // New provider — save the new credential directly\n log?.info({ provider, action: 'new_provider' }, 'New provider detected');\n const credential = toCredential(entry);\n const newStore = addProfile(store, provider, credential);\n if (newStore !== store) {\n store = newStore;\n changed = true;\n }\n }\n }\n\n if (changed) {\n await saveProfiles(store, profPath);\n log?.info({ profiles_saved: true }, 'Profiles saved to disk');\n }\n\n lastKnownAuth = newAuth;\n };\n\n /**\n * Debounced handler for fs.watch events.\n */\n const onFileChange = (): void => {\n if (debounceTimer !== null) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n processChange().catch((err: unknown) => {\n log?.warn({ err }, 'Error processing auth change');\n });\n }, DEBOUNCE_MS);\n };\n\n /**\n * Starts the file watcher. Runs async fs.watch loop.\n */\n const start = async (): Promise<void> => {\n // 1. Load current state\n const currentAuth = await readAuthJson(authPath);\n const currentStore = await loadProfiles(profPath);\n log?.info({ providers: Object.keys(currentAuth) }, 'Auth watcher started');\n\n // 2. D-72: If profiles store is empty AND auth.json has entries,\n // initialize profiles from auth.json\n if (\n Object.keys(currentStore).length === 0 &&\n Object.keys(currentAuth).length > 0\n ) {\n let store: ProfileStore = {};\n for (const [provider, entry] of Object.entries(currentAuth)) {\n if (!entry) continue;\n const credential = toCredential(entry);\n store = addProfile(store, provider, credential);\n }\n await saveProfiles(store, profPath);\n log?.info({ profiles_initialized: Object.keys(store).length }, 'Initialized profiles from auth.json');\n }\n\n // 3. Set last known state\n lastKnownAuth = currentAuth;\n\n // 4. Start watching\n abortController = new AbortController();\n const parentDir = dirname(authPath);\n\n watchPromise = (async () => {\n try {\n const watcher = watch(parentDir, {\n signal: abortController!.signal,\n });\n for await (const event of watcher) {\n // Only react to changes in the auth.json file itself\n if (event.filename === 'auth.json' || event.filename === null) {\n onFileChange();\n }\n }\n } catch (err: unknown) {\n const name = (err as Error).name;\n // AbortError is expected on stop()\n if (name !== 'AbortError') {\n // Silently ignore other watch errors (e.g., ENOENT for missing dir)\n }\n }\n })();\n };\n\n /**\n * Stops the file watcher and cleans up.\n */\n const stop = (): void => {\n if (debounceTimer !== null) {\n clearTimeout(debounceTimer);\n debounceTimer = null;\n }\n if (abortController !== null) {\n abortController.abort();\n abortController = null;\n }\n watchPromise = null;\n log?.info('Auth watcher stopped');\n };\n\n return { start, stop };\n};\n","/**\n * OpenCode plugin tool definitions for profile management.\n *\n * Per D-68, D-69, D-70: profiles-list and profiles-remove tools.\n * Follows the exact pattern from src/operator/plugin-tools.ts.\n *\n * Tools are stateless — they call loadProfiles/saveProfiles on each invocation,\n * so they can be created eagerly before plugin state is initialized.\n */\n\nimport { tool } from '@opencode-ai/plugin/tool';\nimport type { ToolDefinition } from '@opencode-ai/plugin/tool';\nimport { loadProfiles, removeProfile, listProfiles, saveProfiles } from './store.js';\n\nconst { schema: z } = tool;\n\n/** Map of profile tool definitions keyed by command name. */\nexport interface ProfileTools {\n readonly profilesList: ToolDefinition;\n readonly profilesRemove: ToolDefinition;\n}\n\n/** Options for creating profile tools. */\nexport interface ProfileToolsOptions {\n readonly profilesPath?: string;\n}\n\n/**\n * Creates profile tool definitions.\n *\n * Each tool operates on the profiles.json file directly (load/save per call).\n * No shared state required — tools are safe to create eagerly.\n *\n * @param options - Optional path override for profiles.json (useful for testing).\n */\nexport const createProfileTools = (options?: ProfileToolsOptions): ProfileTools => ({\n profilesList: tool({\n description:\n 'List all saved auth profiles with provider, type, and creation date.',\n args: {},\n async execute() {\n const store = await loadProfiles(options?.profilesPath);\n const profiles = listProfiles(store);\n const result = profiles.map((entry) => ({\n id: entry.id,\n provider: entry.provider,\n type: entry.type,\n created: entry.created,\n }));\n return JSON.stringify(result, null, 2);\n },\n }),\n\n profilesRemove: tool({\n description: 'Remove a saved auth profile by ID.',\n args: { id: z.string().min(1) },\n async execute(args) {\n const store = await loadProfiles(options?.profilesPath);\n const { store: newStore, removed } = removeProfile(store, args.id);\n if (removed) {\n await saveProfiles(newStore, options?.profilesPath);\n return JSON.stringify({ success: true, id: args.id });\n }\n return JSON.stringify({\n success: false,\n id: args.id,\n error: 'Profile not found',\n });\n },\n }),\n});\n"],"mappings":"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","names":["pino","crypto","import_zod","import_cockatiel","import_eventemitter3","PQueue","decision","cb","isDegraded","isHeuristic","provenance","import_node_crypto","z","entry","import_promises","import_node_os","import_node_path","import_tool","z"]}