nexus-agents 2.26.1 → 2.28.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.
- package/README.md +7 -7
- package/dist/{chunk-X33QNBGA.js → chunk-E7EX2KQJ.js} +3 -5
- package/dist/{chunk-X33QNBGA.js.map → chunk-E7EX2KQJ.js.map} +1 -1
- package/dist/{chunk-BOWNZMPH.js → chunk-L2SHSW4T.js} +3017 -1300
- package/dist/chunk-L2SHSW4T.js.map +1 -0
- package/dist/{chunk-ARNVVQ5W.js → chunk-LKSTILEE.js} +1213 -117
- package/dist/chunk-LKSTILEE.js.map +1 -0
- package/dist/{chunk-L3LQ3RP5.js → chunk-QZEAD6AG.js} +10339 -6289
- package/dist/chunk-QZEAD6AG.js.map +1 -0
- package/dist/{chunk-LCHCASB7.js → chunk-UGNLR4NZ.js} +2 -2
- package/dist/{chunk-UVQ7R4C4.js → chunk-YSDUVCCZ.js} +137 -717
- package/dist/chunk-YSDUVCCZ.js.map +1 -0
- package/dist/cli.d.ts +8 -1
- package/dist/cli.js +644 -216
- package/dist/cli.js.map +1 -1
- package/dist/{dist-Y5F6UM2N.js → dist-H5XNXVAV.js} +1384 -1295
- package/dist/dist-H5XNXVAV.js.map +1 -0
- package/dist/doctor-deep-BDE2PHVX.js +11 -0
- package/dist/index.d.ts +4299 -7411
- package/dist/index.js +588 -132
- package/dist/index.js.map +1 -1
- package/dist/{setup-command-VNF3KTCJ.js → setup-command-SS7LMN7Y.js} +5 -6
- package/dist/setup-config-DSMOOLVW.js +9 -0
- package/dist/workflows/templates/code-review.yaml +1 -1
- package/dist/workflows/templates/refactoring.yaml +1 -1
- package/dist/workflows/templates/research-review.yaml +19 -4
- package/dist/workflows/templates/security-audit.yaml +1 -1
- package/dist/workflows/templates/standards-review.yaml +1 -1
- package/package.json +12 -12
- package/src/workflows/templates/code-review.yaml +1 -1
- package/src/workflows/templates/refactoring.yaml +1 -1
- package/src/workflows/templates/research-review.yaml +19 -4
- package/src/workflows/templates/security-audit.yaml +1 -1
- package/src/workflows/templates/standards-review.yaml +1 -1
- package/dist/chunk-ARNVVQ5W.js.map +0 -1
- package/dist/chunk-BOWNZMPH.js.map +0 -1
- package/dist/chunk-L3LQ3RP5.js.map +0 -1
- package/dist/chunk-LCDOP543.js +0 -365
- package/dist/chunk-LCDOP543.js.map +0 -1
- package/dist/chunk-PGNRXCYY.js +0 -776
- package/dist/chunk-PGNRXCYY.js.map +0 -1
- package/dist/chunk-UVQ7R4C4.js.map +0 -1
- package/dist/dist-Y5F6UM2N.js.map +0 -1
- package/dist/doctor-deep-I2J5CRFG.js +0 -13
- package/dist/setup-config-VQSWWJ5O.js +0 -9
- /package/dist/{chunk-LCHCASB7.js.map → chunk-UGNLR4NZ.js.map} +0 -0
- /package/dist/{doctor-deep-I2J5CRFG.js.map → doctor-deep-BDE2PHVX.js.map} +0 -0
- /package/dist/{setup-command-VNF3KTCJ.js.map → setup-command-SS7LMN7Y.js.map} +0 -0
- /package/dist/{setup-config-VQSWWJ5O.js.map → setup-config-DSMOOLVW.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/tools/weather-report-types.ts","../src/mcp/gateway/gateway-keywords.ts","../src/mcp/gateway/tier-classifier.ts","../src/mcp/gateway/tier-recommender.ts","../src/adapters/rate-limit-detector.ts","../src/mcp/middleware/tool-metrics.ts","../src/agents/heartbeat-monitor.ts","../src/mcp/tools/weather-report.ts"],"sourcesContent":["/**\n * Type definitions for the Weather Report MCP tool.\n *\n * Surfaces observed model performance as a living \"weather report\"\n * and computes adaptive routing bonuses from outcome data.\n *\n * @module mcp/tools/weather-report-types\n * (Source: Issue #865 — Weather report with adaptive routing)\n */\n\nimport { z } from 'zod';\nimport type { TaskCategory } from '../../config/task-specialization-types.js';\nimport type { GroupStats } from '../../orchestration/outcomes/outcome-types.js';\nimport { CLI_NAMES, type CliNameLiteral } from '../../config/model-capabilities-types.js';\n\n// ============================================================================\n// Input Schema\n// ============================================================================\n\nexport const WeatherReportInputSchema = z.object({\n /** Filter by CLI name. */\n cli: z.enum(CLI_NAMES).optional().describe('Filter by CLI'),\n /** Filter by task category. */\n category: z\n .enum([\n 'architecture',\n 'code_generation',\n 'code_review',\n 'research',\n 'security_review',\n 'planning',\n 'documentation',\n 'testing',\n 'devops',\n 'exploration',\n ])\n .optional()\n .describe('Filter by task category'),\n /** Include adaptive routing bonus data. */\n includeAdaptive: z\n .boolean()\n .optional()\n .default(true)\n .describe('Include adaptive routing bonuses (default: true)'),\n});\n\n/** Validated MCP input (includeAdaptive is always populated after Zod parse). */\nexport type WeatherReportInput = z.infer<typeof WeatherReportInputSchema>;\n\n/** Options for generateWeatherReport (all fields optional). */\nexport interface WeatherReportOptions {\n readonly cli?: CliNameLiteral;\n readonly category?: string;\n readonly includeAdaptive?: boolean;\n}\n\n// ============================================================================\n// Output Types\n// ============================================================================\n\n/** Per-CLI performance stats in the weather report. */\nexport interface CliWeather {\n readonly cli: string;\n readonly totalTasks: number;\n readonly successRate: number;\n readonly avgDurationMs: number;\n readonly byCategory: ReadonlyMap<string, GroupStats>;\n}\n\n/** Adaptive bonus for a CLI+category pair. */\nexport interface AdaptiveBonus {\n readonly cli: string;\n readonly category: TaskCategory;\n readonly staticBonus: number;\n readonly adaptiveBonus: number;\n readonly sampleCount: number;\n readonly sufficient: boolean;\n}\n\n/** Tier recommendation surfaced in the weather report (#895). */\nexport interface TierRecommendationEntry {\n readonly category: string;\n readonly direction: 'promote' | 'demote';\n readonly currentTier: number;\n readonly recommendedTier: number;\n readonly successRate: number;\n readonly sampleCount: number;\n readonly reason: string;\n}\n\n/** Learning insight for a CLI+category pair (Issue #901, Phase 4). */\nexport interface LearningInsight {\n readonly cli: string;\n readonly category: TaskCategory;\n readonly trend: 'improving' | 'declining' | 'stable';\n readonly confidence: number;\n readonly adjustedBaseline: number;\n readonly sampleCount: number;\n}\n\n/** Recommended CLI→category mapping for LinUCB cold-start (Epic #952, Phase 6). */\nexport interface RecommendedMapping {\n readonly category: TaskCategory;\n readonly recommendedCli: string;\n readonly successRate: number;\n readonly sampleCount: number;\n readonly confidence: 'high' | 'medium' | 'low';\n}\n\n/** Rate limit stats per provider (Issue #996). */\nexport interface RateLimitReport {\n readonly provider: string;\n readonly totalHits: number;\n readonly lastHitAt: number;\n readonly avgRetryAfterMs: number | undefined;\n}\n\n/** Per-tool performance stats (Issue #1022). */\nexport interface ToolPerformanceEntry {\n readonly toolName: string;\n readonly totalCalls: number;\n readonly successRate: number;\n readonly avgDurationMs: number;\n readonly errorCount: number;\n}\n\n/** Failure breakdown entry for the weather report (Issue #1025). */\nexport interface FailureBreakdownEntry {\n readonly category: string;\n readonly count: number;\n readonly percentage: number;\n}\n\n/** Per-expert-role performance stats from worker dispatch outcomes (Issue #1324). */\nexport interface ExpertPerformanceEntry {\n readonly role: string;\n readonly totalTasks: number;\n readonly successRate: number;\n readonly avgDurationMs: number;\n readonly dominantErrorPattern?: string;\n}\n\n/** Agent health summary from heartbeat monitor (Issue #1032). */\nexport interface AgentHealthSummary {\n readonly activeSessions: number;\n readonly stalledSessions: number;\n readonly sessions: readonly AgentSessionEntry[];\n}\n\n/** Single agent session health entry. */\nexport interface AgentSessionEntry {\n readonly sessionId: string;\n readonly expertId: string;\n readonly health: 'alive' | 'slow' | 'stalled';\n readonly elapsedMs: number;\n readonly timeSinceHeartbeatMs: number;\n readonly heartbeatCount: number;\n}\n\n/** Full weather report response. */\nexport interface WeatherReportResponse {\n readonly overall: {\n readonly totalTasks: number;\n readonly successRate: number;\n readonly avgDurationMs: number;\n };\n readonly cliWeather: readonly CliWeather[];\n readonly adaptiveBonuses: readonly AdaptiveBonus[];\n /** Outcome-driven tier change recommendations (#895). */\n readonly tierRecommendations: readonly TierRecommendationEntry[];\n /** Adaptive learning insights per CLI+category (#901). */\n readonly learningInsights?: readonly LearningInsight[];\n /** Recommended CLI mappings per category for LinUCB priors (Epic #952). */\n readonly recommendedMappings?: readonly RecommendedMapping[];\n /** Rate limit utilization per provider (Issue #996). */\n readonly rateLimits?: readonly RateLimitReport[];\n /** Per-tool invocation metrics (Issue #1022). */\n readonly toolPerformance?: readonly ToolPerformanceEntry[];\n /** Failure breakdown by category (Issue #1025). */\n readonly failureBreakdown?: readonly FailureBreakdownEntry[];\n /** Agent health from heartbeat monitor (Issue #1032). */\n readonly agentHealth?: AgentHealthSummary;\n /** Per-expert-role performance from worker dispatch outcomes (Issue #1324). */\n readonly expertPerformance?: readonly ExpertPerformanceEntry[];\n readonly explorationRate: number;\n readonly coldStartThreshold: number;\n readonly collectedAt: string;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport const WeatherReportConfigSchema = z.object({\n /** Minimum observations before adjusting bonuses (lowered for faster activation). */\n coldStartThreshold: z.number().int().min(1).max(1000).default(3),\n /** Exploration rate: fraction of random routing (0.0-1.0). */\n explorationRate: z.number().min(0).max(1).default(0.1),\n /** Max adaptive bonus adjustment (+/-). */\n maxBonusAdjustment: z.number().min(0).max(10).default(5),\n});\n\nexport type WeatherReportConfig = z.infer<typeof WeatherReportConfigSchema>;\n\n/** Creates default configuration. */\nexport function createDefaultWeatherConfig(): WeatherReportConfig {\n return WeatherReportConfigSchema.parse({});\n}\n","/**\n * Gateway Keyword Constants\n *\n * Single source of truth for security and architecture keywords used by\n * both the tier classifier and governance enforcer. Extracted to prevent\n * divergence between the two modules (DRY).\n *\n * @module mcp/gateway/gateway-keywords\n */\n\n/** Keywords that indicate security-related work (case-insensitive substring match). */\nexport const SECURITY_KEYWORDS = [\n 'security',\n 'vulnerabilit',\n 'cve-',\n 'exploit',\n 'injection',\n 'xss',\n 'csrf',\n 'auth',\n 'penetration',\n 'threat',\n 'malware',\n 'credentials',\n 'secrets',\n 'encryption',\n 'certificate',\n] as const;\n\n/** Keywords that indicate architecture-related work (case-insensitive substring match). */\nexport const ARCHITECTURE_KEYWORDS = [\n 'architecture',\n 'breaking change',\n 'breaking api',\n 'api change',\n 'migration',\n 'refactor.*system',\n 'redesign',\n 'microservice',\n 'monolith',\n 'deprecation',\n 'schema change',\n 'database',\n 'infrastructure',\n] as const;\n\n/** Roles that always trigger promotion to Tier 3. */\nexport const PROMOTED_ROLES = new Set(['security_expert', 'architecture_expert']);\n","/**\n * Request Tier Classifier\n *\n * Pure function that classifies incoming MCP tool requests into tiers\n * for the orchestration gateway. No side effects, no I/O.\n *\n * Tier 1 (DIRECT): Read-only tools — direct dispatch + logging\n * Tier 2 (ANALYZED): Model-selection tools — task analysis first\n * Tier 3 (ORCHESTRATED): Complex/risky tools — full orchestration pipeline\n *\n * Security and architecture-related requests are always promoted to Tier 3.\n *\n * @module mcp/gateway/tier-classifier\n * (Source: Issue #892, Epic #888)\n */\n\nimport { SECURITY_KEYWORDS, ARCHITECTURE_KEYWORDS, PROMOTED_ROLES } from './gateway-keywords.js';\n\n/** Request processing tier. Higher = more orchestration overhead. */\nexport enum RequestTier {\n /** Direct dispatch with structured logging. */\n DIRECT = 1,\n /** Task analysis + model selection via delegate_to_model. */\n ANALYZED = 2,\n /** Full orchestration + decomposition + voting. */\n ORCHESTRATED = 3,\n}\n\n/** Per-tool tier override map (from nexus-agents.yaml). */\nexport type TierOverrides = Record<string, RequestTier>;\n\n/**\n * Default tier assignment for all 20 registered MCP tools.\n * Tier 1: read-only, no model invocation needed.\n * Tier 2: requires model selection or expert creation.\n * Tier 3: requires full orchestration, decomposition, or consensus.\n */\nexport const TOOL_TIER_MAP: Readonly<Record<string, RequestTier>> = {\n // Tier 1 — Read-only\n list_experts: RequestTier.DIRECT,\n list_workflows: RequestTier.DIRECT,\n memory_query: RequestTier.DIRECT,\n memory_stats: RequestTier.DIRECT,\n weather_report: RequestTier.DIRECT,\n research_query: RequestTier.DIRECT,\n research_analyze: RequestTier.DIRECT,\n research_catalog_review: RequestTier.DIRECT,\n\n // Tier 2 — Model selection\n delegate_to_model: RequestTier.ANALYZED,\n create_expert: RequestTier.ANALYZED,\n execute_expert: RequestTier.ANALYZED,\n research_add: RequestTier.ANALYZED,\n research_discover: RequestTier.ANALYZED,\n registry_import: RequestTier.ANALYZED,\n\n // Tier 3 — Full orchestration\n orchestrate: RequestTier.ORCHESTRATED,\n consensus_vote: RequestTier.ORCHESTRATED,\n execute_spec: RequestTier.ORCHESTRATED,\n run_workflow: RequestTier.ORCHESTRATED,\n run_graph_workflow: RequestTier.ORCHESTRATED,\n issue_triage: RequestTier.ORCHESTRATED,\n};\n\n/**\n * Classifies an MCP tool request into a processing tier.\n *\n * @param toolName - The MCP tool being invoked\n * @param params - The tool's input parameters\n * @param overrides - Optional per-tool tier overrides\n * @returns The appropriate RequestTier for this request\n */\nexport function classifyRequestTier(\n toolName: string,\n params: Record<string, unknown>,\n overrides?: TierOverrides\n): RequestTier {\n const defaultTier = TOOL_TIER_MAP[toolName] ?? RequestTier.ANALYZED;\n const effectiveTier = overrides?.[toolName] ?? defaultTier;\n\n // Tier 1 tools (from canonical map, not overridden) skip promotion checks\n if (defaultTier === RequestTier.DIRECT && effectiveTier === RequestTier.DIRECT) {\n return RequestTier.DIRECT;\n }\n\n // Security/architecture promotion always wins — overrides cannot suppress it\n if (effectiveTier < RequestTier.ORCHESTRATED && shouldPromote(params)) {\n return RequestTier.ORCHESTRATED;\n }\n\n return effectiveTier;\n}\n\n/**\n * Checks if request params contain security or architecture keywords\n * that warrant promotion to Tier 3.\n */\nfunction shouldPromote(params: Record<string, unknown>): boolean {\n // Check role-based promotion\n const role = params['role'];\n if (typeof role === 'string' && PROMOTED_ROLES.has(role)) {\n return true;\n }\n\n // Check text content for keyword matches\n const textFields = ['task', 'proposal', 'prompt'];\n for (const field of textFields) {\n const value = params[field];\n if (typeof value === 'string' && containsPromotionKeyword(value)) {\n return true;\n }\n }\n\n return false;\n}\n\n/** Map from config string tier names to RequestTier enum values. */\nconst TIER_NAME_TO_ENUM: Readonly<Record<string, RequestTier>> = {\n DIRECT: RequestTier.DIRECT,\n ANALYZED: RequestTier.ANALYZED,\n ORCHESTRATED: RequestTier.ORCHESTRATED,\n};\n\n/**\n * Converts string tier override map (from config schema) to RequestTier enum map.\n * Ignores entries with invalid tier names.\n *\n * @param overrides - String-keyed tier names from GatewayConfigSchema\n * @returns Enum-valued TierOverrides, or undefined if empty/undefined\n */\nexport function parseTierOverrides(\n overrides: Record<string, string> | undefined\n): TierOverrides | undefined {\n if (overrides === undefined) return undefined;\n const result: TierOverrides = {};\n for (const [tool, tierName] of Object.entries(overrides)) {\n const tier = TIER_NAME_TO_ENUM[tierName];\n if (tier !== undefined) {\n result[tool] = tier;\n }\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/** Checks if text contains any security or architecture promotion keyword. */\nfunction containsPromotionKeyword(text: string): boolean {\n const lower = text.toLowerCase();\n for (const kw of SECURITY_KEYWORDS) {\n if (lower.includes(kw)) return true;\n }\n for (const kw of ARCHITECTURE_KEYWORDS) {\n if (new RegExp(kw, 'i').test(text)) return true;\n }\n return false;\n}\n","/**\n * Outcome-Driven Tier Promotion Recommender\n *\n * Analyzes task outcome data to recommend tier changes for MCP tools.\n * Recommendations are advisory only — humans approve changes via config.\n *\n * Thresholds (from Issue #895):\n * - Promote: >30% failure rate at current tier → recommend next tier\n * - Demote: >95% success rate over 50+ executions → eligible for demotion\n * - Minimum sample: 20 executions before any recommendation\n *\n * @module mcp/gateway/tier-recommender\n * (Source: Issue #895, Epic #888)\n */\n\nimport type { PerformanceSummary, GroupStats } from '../../orchestration/outcomes/outcome-types.js';\nimport { RequestTier, TOOL_TIER_MAP } from './tier-classifier.js';\n\n/** Recommendation direction. */\nexport type TierDirection = 'promote' | 'demote';\n\n/** A single tier change recommendation. */\nexport interface TierRecommendation {\n /** Category that triggered this recommendation. */\n category: string;\n /** Current tier for tools in this category. */\n currentTier: RequestTier;\n /** Recommended tier. */\n recommendedTier: RequestTier;\n /** Direction of the recommendation. */\n direction: TierDirection;\n /** Observed success rate (0-1). */\n successRate: number;\n /** Number of observations. */\n sampleCount: number;\n /** Human-readable reason. */\n reason: string;\n}\n\n/** Configuration for tier recommendation thresholds. */\nexport interface TierRecommenderConfig {\n /** Minimum executions before making any recommendation. */\n readonly minSamples: number;\n /** Failure rate threshold for promotion (0-1). */\n readonly promoteFailureRate: number;\n /** Success rate threshold for demotion (0-1). */\n readonly demoteSuccessRate: number;\n /** Minimum executions for demotion eligibility. */\n readonly demoteMinSamples: number;\n}\n\n/** Default configuration per issue spec. */\nconst DEFAULT_CONFIG: TierRecommenderConfig = {\n minSamples: 20,\n promoteFailureRate: 0.3,\n demoteSuccessRate: 0.95,\n demoteMinSamples: 50,\n};\n\n/** Maps categories to their typical tool tier (best effort). */\nfunction getCategoryTier(category: string): RequestTier {\n // Tools that tend to be used for each category\n const categoryToolMap: Record<string, string> = {\n research: 'research_query',\n exploration: 'research_discover',\n code_generation: 'delegate_to_model',\n code_review: 'run_workflow',\n architecture: 'orchestrate',\n security_review: 'orchestrate',\n planning: 'orchestrate',\n documentation: 'run_workflow',\n testing: 'run_workflow',\n devops: 'delegate_to_model',\n };\n\n const tool = categoryToolMap[category];\n if (tool !== undefined) {\n return TOOL_TIER_MAP[tool] ?? RequestTier.ANALYZED;\n }\n return RequestTier.ANALYZED;\n}\n\n/**\n * Generates tier recommendations from outcome data.\n *\n * @param summary - Performance summary from OutcomeStore.summarize()\n * @param config - Optional threshold overrides\n * @returns Array of tier change recommendations (may be empty)\n */\nexport function generateTierRecommendations(\n summary: PerformanceSummary,\n config?: Partial<TierRecommenderConfig>\n): TierRecommendation[] {\n const cfg = { ...DEFAULT_CONFIG, ...config };\n const recommendations: TierRecommendation[] = [];\n\n for (const [category, stats] of summary.byCategory) {\n const rec = evaluateCategory(category, stats, cfg);\n if (rec !== null) recommendations.push(rec);\n }\n\n return recommendations;\n}\n\n/** Evaluates a single category for promotion or demotion. */\nfunction evaluateCategory(\n category: string,\n stats: GroupStats,\n cfg: TierRecommenderConfig\n): TierRecommendation | null {\n if (stats.count < cfg.minSamples) return null;\n\n const currentTier = getCategoryTier(category);\n const failureRate = 1 - stats.successRate;\n\n // Check for promotion (too many failures at current tier)\n if (failureRate > cfg.promoteFailureRate && currentTier < RequestTier.ORCHESTRATED) {\n const recommendedTier = currentTier + 1;\n return {\n category,\n currentTier,\n recommendedTier,\n direction: 'promote',\n successRate: stats.successRate,\n sampleCount: stats.count,\n reason: `${category}: ${(failureRate * 100).toFixed(0)}% failure rate over ${String(stats.count)} tasks — recommend promoting to Tier ${String(recommendedTier)}`,\n };\n }\n\n // Check for demotion (consistently successful at current tier)\n if (\n stats.successRate > cfg.demoteSuccessRate &&\n stats.count >= cfg.demoteMinSamples &&\n currentTier > RequestTier.DIRECT\n ) {\n const recommendedTier = currentTier - 1;\n return {\n category,\n currentTier,\n recommendedTier,\n direction: 'demote',\n successRate: stats.successRate,\n sampleCount: stats.count,\n reason: `${category}: ${(stats.successRate * 100).toFixed(0)}% success rate over ${String(stats.count)} tasks — eligible for demotion to Tier ${String(recommendedTier)}`,\n };\n }\n\n return null;\n}\n","/**\n * Rate Limit Detection and Tracking\n *\n * Detects rate limit errors from model adapter responses and tracks\n * rate limit events for weather report metrics.\n *\n * @module adapters/rate-limit-detector\n * (Source: Issue #996 — Rate limit error surfacing)\n */\n\nimport { RateLimitError, getErrorMessage } from '../core/index.js';\n\n// ============================================================================\n// Detection\n// ============================================================================\n\nconst RATE_LIMIT_PATTERNS = [\n 'rate limit',\n 'rate_limit',\n 'too many requests',\n '429',\n 'quota exceeded',\n 'throttl',\n 'requests per minute',\n 'tokens per minute',\n] as const;\n\n/**\n * Detects whether an error is a rate limit error.\n * Pattern-matches against common provider error messages.\n */\nexport function isRateLimitLikeError(error: unknown): boolean {\n const message = getErrorMessage(error).toLowerCase();\n return RATE_LIMIT_PATTERNS.some((p) => message.includes(p));\n}\n\n/**\n * Parses retry-after metadata from an error message.\n * Providers often include timing hints in error messages.\n */\nexport function parseRetryAfterMs(errorMessage: string): number | undefined {\n const lower = errorMessage.toLowerCase();\n\n // Match \"retry after X seconds\" or \"retry-after: X\"\n const secondsMatch = /retry[- ]?after[:\\s]+(\\d+(?:\\.\\d+)?)\\s*(?:s|sec)/i.exec(lower);\n if (secondsMatch !== null) {\n const parsed = parseFloat(secondsMatch[1] ?? '0');\n return Math.ceil(parsed * 1000);\n }\n\n // Match \"retry after X ms\" or \"wait X milliseconds\"\n const msMatch = /(?:retry[- ]?after|wait)[:\\s]+(\\d+)\\s*(?:ms|millisecond)/i.exec(lower);\n if (msMatch !== null) {\n return parseInt(msMatch[1] ?? '0', 10);\n }\n\n // Match \"try again in X seconds\"\n const againMatch = /try again in (\\d+(?:\\.\\d+)?)\\s*(?:s|sec)/i.exec(lower);\n if (againMatch !== null) {\n const parsed = parseFloat(againMatch[1] ?? '0');\n return Math.ceil(parsed * 1000);\n }\n\n return undefined;\n}\n\n/**\n * Wraps a generic error as a RateLimitError with parsed metadata.\n */\nexport function toRateLimitError(error: unknown, provider?: string): RateLimitError {\n const message = getErrorMessage(error);\n const retryAfterMs = parseRetryAfterMs(message);\n return new RateLimitError(message, {\n ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),\n ...(provider !== undefined ? { provider } : {}),\n ...(error instanceof Error ? { cause: error } : {}),\n });\n}\n\n// ============================================================================\n// Tracking\n// ============================================================================\n\n/** A single rate limit event record. */\nexport interface RateLimitEvent {\n readonly provider: string;\n readonly timestamp: number;\n readonly retryAfterMs: number | undefined;\n}\n\n/** Aggregate stats for rate limit events per provider. */\nexport interface RateLimitStats {\n readonly provider: string;\n readonly totalHits: number;\n readonly lastHitAt: number;\n readonly avgRetryAfterMs: number | undefined;\n}\n\nconst MAX_EVENTS = 200;\nconst events: RateLimitEvent[] = [];\n\n/** Records a rate limit event for tracking. */\nexport function recordRateLimitEvent(event: RateLimitEvent): void {\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events.splice(0, events.length - MAX_EVENTS);\n }\n}\n\n/** Gets rate limit stats grouped by provider. */\nexport function getRateLimitStats(): readonly RateLimitStats[] {\n const grouped = new Map<string, RateLimitEvent[]>();\n for (const event of events) {\n const existing = grouped.get(event.provider);\n if (existing !== undefined) {\n existing.push(event);\n } else {\n grouped.set(event.provider, [event]);\n }\n }\n\n const stats: RateLimitStats[] = [];\n for (const [provider, providerEvents] of grouped) {\n const retryValues = providerEvents\n .map((e) => e.retryAfterMs)\n .filter((v): v is number => v !== undefined);\n const avgRetry =\n retryValues.length > 0\n ? retryValues.reduce((a, b) => a + b, 0) / retryValues.length\n : undefined;\n const lastEvent = providerEvents[providerEvents.length - 1];\n\n stats.push({\n provider,\n totalHits: providerEvents.length,\n lastHitAt: lastEvent?.timestamp ?? 0,\n ...(avgRetry !== undefined\n ? { avgRetryAfterMs: Math.round(avgRetry) }\n : { avgRetryAfterMs: undefined }),\n });\n }\n\n return stats;\n}\n\n/** Clears all tracked rate limit events. Useful for testing. */\nexport function clearRateLimitEvents(): void {\n events.length = 0;\n}\n","/**\n * Tool usage metrics recorder (Issue #1022)\n *\n * Lightweight, bounded, in-memory store for MCP tool invocation metrics.\n * Records tool name, duration, and success/failure for every tool call.\n * Used by the weather report to surface per-tool analytics.\n *\n * @module mcp/middleware/tool-metrics\n */\n\nimport { getTimeProvider } from '../../core/index.js';\nimport type { Middleware, ToolResult } from './middleware-chain.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** A single recorded tool invocation metric. */\nexport interface ToolMetric {\n readonly toolName: string;\n readonly durationMs: number;\n readonly success: boolean;\n readonly timestamp: string;\n}\n\n/** Aggregated stats for a single tool. */\nexport interface ToolStats {\n readonly toolName: string;\n readonly totalCalls: number;\n readonly successRate: number;\n readonly avgDurationMs: number;\n readonly errorCount: number;\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\nconst MAX_ENTRIES = 5_000;\nconst metrics: ToolMetric[] = [];\n\n/** Record a tool invocation metric. */\nexport function recordToolMetric(metric: ToolMetric): void {\n metrics.push(metric);\n if (metrics.length > MAX_ENTRIES) {\n metrics.splice(0, metrics.length - MAX_ENTRIES);\n }\n}\n\n/** Get all recorded tool metrics (read-only snapshot). */\nexport function getToolMetrics(): readonly ToolMetric[] {\n return [...metrics];\n}\n\n/** Aggregate metrics into per-tool stats. */\nexport function getToolStats(): readonly ToolStats[] {\n const groups = new Map<string, ToolMetric[]>();\n\n for (const m of metrics) {\n const list = groups.get(m.toolName);\n if (list !== undefined) {\n list.push(m);\n } else {\n groups.set(m.toolName, [m]);\n }\n }\n\n const stats: ToolStats[] = [];\n for (const [toolName, list] of groups) {\n const sc = list.filter((m) => m.success).length;\n const td = list.reduce((s, m) => s + m.durationMs, 0);\n stats.push({\n toolName,\n totalCalls: list.length,\n successRate: sc / list.length,\n avgDurationMs: td / list.length,\n errorCount: list.length - sc,\n });\n }\n\n return stats.sort((a, b) => b.totalCalls - a.totalCalls);\n}\n\n/** Clear all recorded metrics (for testing). */\nexport function clearToolMetrics(): void {\n metrics.length = 0;\n}\n\n// ============================================================================\n// Middleware\n// ============================================================================\n\n/**\n * Creates a middleware that records tool invocation metrics.\n * Should be placed as the outermost middleware (before audit)\n * to capture the full request lifecycle including middleware overhead.\n */\nexport function createMetricsMiddleware(): Middleware {\n return async (args, ctx, next): Promise<ToolResult> => {\n const startTime = getTimeProvider().now();\n\n try {\n const result = await next(args, ctx);\n const durationMs = getTimeProvider().now() - startTime;\n\n recordToolMetric({\n toolName: ctx.requestContext.toolName,\n durationMs,\n success: result.isError !== true,\n timestamp: new Date().toISOString(),\n });\n\n return result;\n } catch (error) {\n const durationMs = getTimeProvider().now() - startTime;\n\n recordToolMetric({\n toolName: ctx.requestContext.toolName,\n durationMs,\n success: false,\n timestamp: new Date().toISOString(),\n });\n\n throw error;\n }\n };\n}\n","/**\n * Heartbeat-based liveness monitor for expert agent sessions.\n *\n * Tracks active expert executions with periodic heartbeats.\n * Detects stalled sessions that stop making progress, enabling\n * faster detection than wall-clock timeouts alone.\n *\n * @module agents/heartbeat-monitor\n * (Source: Issue #1032 — Agent heartbeat health monitor)\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Health status of an expert session. */\nexport type SessionHealth = 'alive' | 'slow' | 'stalled';\n\n/** Snapshot of a single expert session. */\nexport interface ExpertSessionSnapshot {\n readonly sessionId: string;\n readonly expertId: string;\n readonly startedAt: number;\n readonly lastHeartbeat: number;\n readonly heartbeatCount: number;\n readonly health: SessionHealth;\n readonly elapsedMs: number;\n readonly timeSinceHeartbeatMs: number;\n}\n\n/** Aggregate health report for all active sessions. */\nexport interface AgentHealthReport {\n readonly activeSessions: number;\n readonly stalledSessions: number;\n readonly sessions: readonly ExpertSessionSnapshot[];\n}\n\n/** Configuration for the heartbeat monitor. */\nexport interface HeartbeatConfig {\n /** Time without heartbeat before marking 'slow' (ms). */\n readonly slowThresholdMs: number;\n /** Time without heartbeat before marking 'stalled' (ms). */\n readonly stalledThresholdMs: number;\n /** Absolute max lifetime for any session (ms). Safety cap. */\n readonly absoluteMaxMs: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// Canonical source: config/timeouts.ts (Issue #1046)\nimport { HEARTBEAT_TIMEOUTS } from '../config/timeouts.js';\n\nconst DEFAULT_SLOW_THRESHOLD_MS = HEARTBEAT_TIMEOUTS.slowThresholdMs;\nconst DEFAULT_STALLED_THRESHOLD_MS = HEARTBEAT_TIMEOUTS.stalledThresholdMs;\nconst DEFAULT_ABSOLUTE_MAX_MS = HEARTBEAT_TIMEOUTS.absoluteMaxMs;\n\n// ============================================================================\n// Internal Session State\n// ============================================================================\n\ninterface SessionEntry {\n readonly expertId: string;\n readonly startedAt: number;\n lastHeartbeat: number;\n heartbeatCount: number;\n /** Previous health state for transition detection (Issue #1088 Phase 4). */\n previousHealth: SessionHealth;\n}\n\n/** Health transition info returned by getSessionHealth(). */\nexport interface HealthTransition {\n readonly sessionId: string;\n readonly agentId: string;\n readonly health: SessionHealth;\n readonly previousHealth: SessionHealth;\n readonly changed: boolean;\n readonly elapsedMs: number;\n readonly heartbeatCount: number;\n}\n\n// ============================================================================\n// HeartbeatMonitor\n// ============================================================================\n\n/**\n * Tracks expert session liveness via heartbeats.\n *\n * - `startSession()` begins tracking a new expert execution\n * - `heartbeat()` resets the liveness timer for a session\n * - `endSession()` stops tracking\n * - `getHealth()` returns aggregate health report\n * - `isStalled()` checks if a specific session is stalled\n */\nexport class HeartbeatMonitor {\n private readonly config: HeartbeatConfig;\n private readonly sessions = new Map<string, SessionEntry>();\n\n constructor(config?: Partial<HeartbeatConfig>) {\n this.config = {\n slowThresholdMs: config?.slowThresholdMs ?? DEFAULT_SLOW_THRESHOLD_MS,\n stalledThresholdMs: config?.stalledThresholdMs ?? DEFAULT_STALLED_THRESHOLD_MS,\n absoluteMaxMs: config?.absoluteMaxMs ?? DEFAULT_ABSOLUTE_MAX_MS,\n };\n }\n\n /** Start tracking a new expert session. Returns session ID. */\n startSession(expertId: string): string {\n const sessionId = `hb-${expertId}-${String(Date.now())}`;\n const now = Date.now();\n this.sessions.set(sessionId, {\n expertId,\n startedAt: now,\n lastHeartbeat: now,\n heartbeatCount: 0,\n previousHealth: 'alive',\n });\n return sessionId;\n }\n\n /** Record a heartbeat for an active session. */\n heartbeat(sessionId: string): void {\n const entry = this.sessions.get(sessionId);\n if (entry === undefined) return;\n entry.lastHeartbeat = Date.now();\n entry.heartbeatCount++;\n }\n\n /** Stop tracking a session. */\n endSession(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n /** Check if a session has exceeded the stalled threshold. */\n isStalled(sessionId: string): boolean {\n const entry = this.sessions.get(sessionId);\n if (entry === undefined) return false;\n const elapsed = Date.now() - entry.lastHeartbeat;\n return elapsed >= this.config.stalledThresholdMs;\n }\n\n /** Check if a session has exceeded the absolute max lifetime. */\n isExpired(sessionId: string): boolean {\n const entry = this.sessions.get(sessionId);\n if (entry === undefined) return false;\n return Date.now() - entry.startedAt >= this.config.absoluteMaxMs;\n }\n\n /** Get aggregate health report for all active sessions. */\n getHealth(): AgentHealthReport {\n const now = Date.now();\n const sessions: ExpertSessionSnapshot[] = [];\n let stalledCount = 0;\n\n for (const [sessionId, entry] of this.sessions) {\n const timeSince = now - entry.lastHeartbeat;\n const health = this.classifyHealth(timeSince);\n if (health === 'stalled') stalledCount++;\n\n sessions.push({\n sessionId,\n expertId: entry.expertId,\n startedAt: entry.startedAt,\n lastHeartbeat: entry.lastHeartbeat,\n heartbeatCount: entry.heartbeatCount,\n health,\n elapsedMs: now - entry.startedAt,\n timeSinceHeartbeatMs: timeSince,\n });\n }\n\n return {\n activeSessions: this.sessions.size,\n stalledSessions: stalledCount,\n sessions,\n };\n }\n\n /**\n * Get health state with transition detection for a session.\n * Updates previousHealth on each call to track transitions.\n * (Issue #1088 Phase 4 — observability)\n */\n getSessionHealth(sessionId: string): HealthTransition | undefined {\n const entry = this.sessions.get(sessionId);\n if (entry === undefined) return undefined;\n const now = Date.now();\n const timeSince = now - entry.lastHeartbeat;\n const health = this.classifyHealth(timeSince);\n const changed = health !== entry.previousHealth;\n const result: HealthTransition = {\n sessionId,\n agentId: entry.expertId,\n health,\n previousHealth: entry.previousHealth,\n changed,\n elapsedMs: now - entry.startedAt,\n heartbeatCount: entry.heartbeatCount,\n };\n entry.previousHealth = health;\n return result;\n }\n\n /** Number of currently tracked sessions. */\n get activeCount(): number {\n return this.sessions.size;\n }\n\n private classifyHealth(timeSinceMs: number): SessionHealth {\n if (timeSinceMs >= this.config.stalledThresholdMs) return 'stalled';\n if (timeSinceMs >= this.config.slowThresholdMs) return 'slow';\n return 'alive';\n }\n}\n\n// ============================================================================\n// Singleton\n// ============================================================================\n\nlet globalMonitor: HeartbeatMonitor | undefined;\n\n/** Get or create the global heartbeat monitor singleton. */\nexport function getHeartbeatMonitor(): HeartbeatMonitor {\n globalMonitor ??= new HeartbeatMonitor();\n return globalMonitor;\n}\n\n/** Reset global monitor (for testing). */\nexport function resetHeartbeatMonitor(): void {\n globalMonitor = undefined;\n}\n","/**\n * nexus-agents/mcp - Weather Report\n *\n * Computes a living performance dashboard from task outcome data\n * and calculates adaptive routing bonuses using epsilon-greedy\n * exploration/exploitation tradeoff.\n *\n * @module mcp/tools/weather-report\n * (Source: Issue #865 — Weather report with adaptive routing)\n */\n\nimport type { PerformanceSummary, GroupStats } from '../../orchestration/outcomes/outcome-types.js';\nimport { getOutcomeStore } from '../../orchestration/outcomes/index.js';\nimport type { TaskCategory } from '../../config/task-specialization-types.js';\nimport { TASK_CATEGORIES } from '../../config/task-specialization-types.js';\nimport { getSpecialization } from '../../config/task-specialization.js';\nimport type { CliNameLiteral } from '../../config/model-capabilities-types.js';\nimport type {\n WeatherReportOptions,\n WeatherReportResponse,\n CliWeather,\n AdaptiveBonus,\n WeatherReportConfig,\n TierRecommendationEntry,\n LearningInsight,\n RecommendedMapping,\n ToolPerformanceEntry,\n FailureBreakdownEntry,\n ExpertPerformanceEntry,\n} from './weather-report-types.js';\nimport type { RateLimitReport } from './weather-report-types.js';\nimport { createDefaultWeatherConfig } from './weather-report-types.js';\nimport { generateTierRecommendations } from '../gateway/tier-recommender.js';\nimport { computeAdaptiveThresholds } from '../../orchestration/outcomes/adaptive-thresholds.js';\nimport { getRateLimitStats } from '../../adapters/rate-limit-detector.js';\nimport { getToolStats } from '../middleware/tool-metrics.js';\nimport { getHeartbeatMonitor } from '../../agents/heartbeat-monitor.js';\nimport type { AgentHealthSummary } from './weather-report-types.js';\n\n// ============================================================================\n// Public API\n// ============================================================================\n\nconst CLI_NAMES = ['claude', 'gemini', 'codex', 'opencode'] as const;\n\n/**\n * Generates the weather report from current outcome data.\n */\nexport function generateWeatherReport(\n input: WeatherReportOptions,\n config?: Partial<WeatherReportConfig>\n): WeatherReportResponse {\n const cfg = { ...createDefaultWeatherConfig(), ...config };\n const store = getOutcomeStore();\n const includeAdaptive = input.includeAdaptive ?? true;\n\n const summary = store.summarize(buildQuery(input.cli, input.category));\n\n const cliWeather = buildCliWeather(summary, input);\n const adaptiveBonuses = includeAdaptive ? computeAdaptiveBonuses(cfg) : [];\n const tierRecommendations = buildTierRecommendations(summary);\n const rateLimits = buildRateLimitReport();\n const toolPerformance = buildToolPerformance();\n const failureBreakdown = buildFailureBreakdown(input);\n const agentHealth = buildAgentHealth();\n const expertPerformance = buildExpertPerformance();\n const base = {\n overall: {\n totalTasks: summary.totalTasks,\n successRate: summary.successRate,\n avgDurationMs: summary.avgDurationMs,\n },\n cliWeather,\n adaptiveBonuses,\n tierRecommendations,\n ...(rateLimits.length > 0 ? { rateLimits } : {}),\n ...(toolPerformance.length > 0 ? { toolPerformance } : {}),\n ...(failureBreakdown.length > 0 ? { failureBreakdown } : {}),\n ...(agentHealth !== undefined ? { agentHealth } : {}),\n ...(expertPerformance.length > 0 ? { expertPerformance } : {}),\n explorationRate: cfg.explorationRate,\n coldStartThreshold: cfg.coldStartThreshold,\n collectedAt: new Date().toISOString(),\n };\n\n if (includeAdaptive) {\n return {\n ...base,\n learningInsights: buildLearningInsights(),\n recommendedMappings: buildRecommendedMappings(),\n };\n }\n\n return base;\n}\n\n/** Builds agent health from heartbeat monitor (Issue #1032). */\nfunction buildAgentHealth(): AgentHealthSummary | undefined {\n const monitor = getHeartbeatMonitor();\n if (monitor.activeCount === 0) return undefined;\n const health = monitor.getHealth();\n return {\n activeSessions: health.activeSessions,\n stalledSessions: health.stalledSessions,\n sessions: health.sessions.map((s) => ({\n sessionId: s.sessionId,\n expertId: s.expertId,\n health: s.health,\n elapsedMs: s.elapsedMs,\n timeSinceHeartbeatMs: s.timeSinceHeartbeatMs,\n heartbeatCount: s.heartbeatCount,\n })),\n };\n}\n\n/** Builds rate limit report from tracked events (Issue #996). */\nfunction buildRateLimitReport(): readonly RateLimitReport[] {\n return getRateLimitStats().map((s) => ({\n provider: s.provider,\n totalHits: s.totalHits,\n lastHitAt: s.lastHitAt,\n avgRetryAfterMs: s.avgRetryAfterMs,\n }));\n}\n\n/**\n * Calculates adaptive specialization bonus for a given CLI+category.\n * Returns the adjustment on top of the static bonus.\n *\n * - Below cold-start threshold: returns 0 (no adjustment)\n * - Above threshold: scales bonus by observed success rate vs baseline\n * - Clamped to [-maxBonusAdjustment, +maxBonusAdjustment]\n */\nexport function getAdaptiveBonus(\n cli: string,\n category: TaskCategory,\n config?: Partial<WeatherReportConfig>\n): number {\n const cfg = { ...createDefaultWeatherConfig(), ...config };\n const store = getOutcomeStore();\n const cliName = cli as CliNameLiteral;\n\n const outcomes = store.query({ cli: cliName, category });\n if (outcomes.length < cfg.coldStartThreshold) return 0;\n\n const thresholds = computeAdaptiveThresholds(store, cliName, category);\n const successRate = outcomes.filter((o) => o.success).length / outcomes.length;\n const delta = successRate - thresholds.baseline;\n\n // Scale: +30% above baseline → +maxBonus (adaptive, not hardcoded)\n const maxBonus = thresholds.maxBonus > 0 ? thresholds.maxBonus : cfg.maxBonusAdjustment;\n const scaled = (delta / 0.3) * maxBonus;\n return clamp(scaled, -maxBonus, maxBonus);\n}\n\n/**\n * Determines if exploration should override normal routing.\n * Uses epsilon-greedy: returns true with probability = explorationRate.\n */\nexport function shouldExplore(config?: Partial<WeatherReportConfig>): boolean {\n const cfg = { ...createDefaultWeatherConfig(), ...config };\n return Math.random() < cfg.explorationRate;\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\nfunction buildQuery(\n cli?: string,\n category?: string\n): { cli?: CliNameLiteral; category?: TaskCategory } {\n const query: { cli?: CliNameLiteral; category?: TaskCategory } = {};\n if (cli !== undefined) query.cli = cli as CliNameLiteral;\n if (category !== undefined) query.category = category as TaskCategory;\n return query;\n}\n\nfunction buildCliWeather(\n summary: PerformanceSummary,\n input: WeatherReportOptions\n): readonly CliWeather[] {\n const clis = input.cli !== undefined ? [input.cli] : [...CLI_NAMES];\n\n return clis.map((cli) => {\n const stats = summary.byCli.get(cli);\n const store = getOutcomeStore();\n const cliOutcomes = store.query({ cli: cli });\n\n // Build per-category breakdown for this CLI\n const byCategory = new Map<string, GroupStats>();\n for (const cat of TASK_CATEGORIES) {\n const catOutcomes = cliOutcomes.filter((o) => o.category === cat);\n if (catOutcomes.length > 0) {\n const sc = catOutcomes.filter((o) => o.success).length;\n const td = catOutcomes.reduce((s, o) => s + o.durationMs, 0);\n byCategory.set(cat, {\n count: catOutcomes.length,\n successRate: sc / catOutcomes.length,\n avgDurationMs: td / catOutcomes.length,\n });\n }\n }\n\n return {\n cli,\n totalTasks: stats?.count ?? 0,\n successRate: stats?.successRate ?? 0,\n avgDurationMs: stats?.avgDurationMs ?? 0,\n byCategory,\n };\n });\n}\n\nfunction computeAdaptiveBonuses(cfg: WeatherReportConfig): readonly AdaptiveBonus[] {\n const bonuses: AdaptiveBonus[] = [];\n\n for (const cli of CLI_NAMES) {\n for (const category of TASK_CATEGORIES) {\n const spec = getSpecialization(category);\n const staticBonus = getStaticBonusForCli(cli, spec);\n const store = getOutcomeStore();\n const outcomes = store.query({ cli, category });\n const sampleCount = outcomes.length;\n const sufficient = sampleCount >= cfg.coldStartThreshold;\n const adaptiveAdj = sufficient ? getAdaptiveBonus(cli, category, cfg) : 0;\n\n // Only include entries with actual data or non-zero bonuses\n if (sampleCount > 0 || staticBonus > 0 || adaptiveAdj !== 0) {\n bonuses.push({\n cli,\n category,\n staticBonus,\n adaptiveBonus: Math.round(adaptiveAdj * 10) / 10,\n sampleCount,\n sufficient,\n });\n }\n }\n }\n\n return bonuses;\n}\n\n/** Gets the static specialization bonus for a CLI in a given spec. */\nfunction getStaticBonusForCli(\n cli: string,\n spec: { primaryCli: string; secondaryCli: string; bonus: number }\n): number {\n if (cli === spec.primaryCli) return spec.bonus;\n if (cli === spec.secondaryCli) return Math.floor(spec.bonus / 2);\n return 0;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Builds learning insights from adaptive thresholds (#901). */\nfunction buildLearningInsights(): readonly LearningInsight[] {\n const store = getOutcomeStore();\n const insights: LearningInsight[] = [];\n\n for (const cli of CLI_NAMES) {\n for (const category of TASK_CATEGORIES) {\n const thresholds = computeAdaptiveThresholds(store, cli, category);\n if (thresholds.sampleCount > 0) {\n insights.push({\n cli,\n category,\n trend: thresholds.trend,\n confidence: thresholds.confidence,\n adjustedBaseline: thresholds.baseline,\n sampleCount: thresholds.sampleCount,\n });\n }\n }\n }\n\n return insights;\n}\n\n/** Builds recommended CLI mappings per category for LinUCB cold-start (#952). */\nfunction buildRecommendedMappings(): readonly RecommendedMapping[] {\n const store = getOutcomeStore();\n const mappings: RecommendedMapping[] = [];\n\n for (const category of TASK_CATEGORIES) {\n let bestCli = '';\n let bestRate = -1;\n let bestCount = 0;\n\n for (const cli of CLI_NAMES) {\n const outcomes = store.query({ cli, category });\n if (outcomes.length === 0) continue;\n const rate = outcomes.filter((o) => o.success).length / outcomes.length;\n if (rate > bestRate || (rate === bestRate && outcomes.length > bestCount)) {\n bestCli = cli;\n bestRate = rate;\n bestCount = outcomes.length;\n }\n }\n\n if (bestCli !== '') {\n const confidence = bestCount >= 20 ? 'high' : bestCount >= 10 ? 'medium' : 'low';\n mappings.push({\n category,\n recommendedCli: bestCli,\n successRate: bestRate,\n sampleCount: bestCount,\n confidence: confidence,\n });\n }\n }\n\n return mappings;\n}\n\n/** Worker model prefix used by recordWorkerOutcomes (Issue #1323). */\nconst WORKER_MODEL_PREFIX = 'worker-';\n\n/** Finds the most common failure category among failed outcomes. */\nfunction findDominantError(\n failed: ReadonlyArray<{ failureCategory?: string | undefined }>\n): string | undefined {\n if (failed.length === 0) return undefined;\n const counts = new Map<string, number>();\n for (const f of failed) {\n const cat = f.failureCategory ?? 'unknown';\n counts.set(cat, (counts.get(cat) ?? 0) + 1);\n }\n let maxCount = 0;\n let dominant: string | undefined;\n for (const [cat, count] of counts) {\n if (count > maxCount) {\n maxCount = count;\n dominant = cat;\n }\n }\n return dominant;\n}\n\n/** Builds per-expert-role performance from worker dispatch outcomes (Issue #1324). */\nfunction buildExpertPerformance(): readonly ExpertPerformanceEntry[] {\n const store = getOutcomeStore();\n const allOutcomes = store.query();\n const workerOutcomes = allOutcomes.filter((o) => o.model.startsWith(WORKER_MODEL_PREFIX));\n if (workerOutcomes.length === 0) return [];\n\n const byRole = new Map<string, typeof workerOutcomes>();\n for (const o of workerOutcomes) {\n const role = o.model.slice(WORKER_MODEL_PREFIX.length);\n const existing = byRole.get(role) ?? [];\n existing.push(o);\n byRole.set(role, existing);\n }\n\n const entries: ExpertPerformanceEntry[] = [];\n for (const [role, outcomes] of byRole) {\n const successes = outcomes.filter((o) => o.success).length;\n const totalDuration = outcomes.reduce((s, o) => s + o.durationMs, 0);\n const dominantErrorPattern = findDominantError(outcomes.filter((o) => !o.success));\n\n entries.push({\n role,\n totalTasks: outcomes.length,\n successRate: successes / outcomes.length,\n avgDurationMs: Math.round(totalDuration / outcomes.length),\n ...(dominantErrorPattern !== undefined ? { dominantErrorPattern } : {}),\n });\n }\n\n return entries.sort((a, b) => b.totalTasks - a.totalTasks);\n}\n\n/** Builds failure breakdown from failed outcomes (Issue #1025). */\nfunction buildFailureBreakdown(input: WeatherReportOptions): readonly FailureBreakdownEntry[] {\n const store = getOutcomeStore();\n const outcomes = store.query(buildQuery(input.cli, input.category));\n const failed = outcomes.filter((o) => !o.success);\n if (failed.length === 0) return [];\n\n const counts = new Map<string, number>();\n for (const o of failed) {\n const cat = o.failureCategory ?? 'unknown';\n counts.set(cat, (counts.get(cat) ?? 0) + 1);\n }\n\n const entries: FailureBreakdownEntry[] = [];\n for (const [category, count] of counts) {\n entries.push({\n category,\n count,\n percentage: Math.round((count / failed.length) * 1000) / 10,\n });\n }\n return entries.sort((a, b) => b.count - a.count);\n}\n\n/** Builds per-tool performance stats from recorded metrics (#1022). */\nfunction buildToolPerformance(): readonly ToolPerformanceEntry[] {\n return getToolStats().map((s) => ({\n toolName: s.toolName,\n totalCalls: s.totalCalls,\n successRate: Math.round(s.successRate * 1000) / 1000,\n avgDurationMs: Math.round(s.avgDurationMs),\n errorCount: s.errorCount,\n }));\n}\n\n/** Generates tier recommendations from outcome summary (#895). */\nfunction buildTierRecommendations(summary: PerformanceSummary): readonly TierRecommendationEntry[] {\n return generateTierRecommendations(summary).map((r) => ({\n category: r.category,\n direction: r.direction,\n currentTier: r.currentTier,\n recommendedTier: r.recommendedTier,\n successRate: r.successRate,\n sampleCount: r.sampleCount,\n reason: r.reason,\n }));\n}\n"],"mappings":"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","names":["CLI_NAMES","CLI_NAMES"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/setup-command.ts","../src/cli/setup-types.ts","../src/cli/setup-environment.ts","../src/cli/setup-mcp.ts","../src/cli/setup-rules.ts","../src/cli/setup-formatting.ts","../src/cli/setup-data-dir.ts","../src/cli/doctor.ts","../src/cli/doctor-formatting.ts","../src/cli/setup-opencode.ts","../src/cli/setup-gemini.ts","../src/cli/setup-codex.ts","../src/cli/setup-wizard.ts"],"sourcesContent":["/* eslint-disable max-lines -- Cohesive setup command module (governance: 400-600 OK if cohesive) */\n/**\n * nexus-agents setup command\n *\n * Configures Claude CLI integration with nexus-agents MCP server.\n * Generates MCP configuration snippet and .claude/rules/nexus-agents.md.\n *\n * @module cli/setup-command\n * (Source: Issue #363 - Auto-configure Claude CLI integration)\n * (Source: Issue #425 - Interactive setup wizard)\n */\n\nimport { existsSync } from 'node:fs';\nimport type { SetupOptions, SetupResult, SetupStep, EnvironmentInfo } from './setup-types.js';\nimport { SetupOptionsSchema } from './setup-types.js';\nimport { getTimeProvider, getErrorMessage } from '../core/index.js';\nimport {\n detectEnvironment,\n generateMcpSnippet,\n generateRulesContent,\n createRulesFile,\n getRulesFilePath,\n formatStatus,\n formatHeader,\n formatCodeBlock,\n isInteractive,\n configureMcpServer,\n // Hook configuration (Issue #416)\n configureHooks,\n generateHookSnippet,\n} from './setup-helpers.js';\nimport type { McpConfigResult, HookConfigResult } from './setup-helpers.js';\nimport { initDataDirectories } from './setup-data-dir.js';\nimport type { DataDirInitResult } from './setup-data-dir.js';\nimport { runConfigInitSync } from './setup-config.js';\nimport { detectOpenCodeCli, configureOpenCode } from './setup-opencode.js';\nimport { detectGeminiCli, configureGemini } from './setup-gemini.js';\nimport { detectCodexCli, configureCodex } from './setup-codex.js';\nimport { VERSION } from '../version.js';\nimport { runWizard } from './setup-wizard.js';\n\n// ============================================================================\n// Output Helpers\n// ============================================================================\n\n/**\n * Writes a line to stdout.\n */\nfunction writeLine(text: string): void {\n process.stdout.write(text + '\\n');\n}\n\n/**\n * Writes an empty line.\n */\nfunction writeEmptyLine(): void {\n process.stdout.write('\\n');\n}\n\n/**\n * Prints MCP configuration result section.\n */\nfunction printMcpResult(mcpResult: McpConfigResult, snippet: string | undefined): void {\n writeLine(formatHeader('MCP Configuration'));\n writeLine('─'.repeat(40));\n if (mcpResult.success) {\n writeLine(mcpResult.message);\n writeLine('Run `/mcp` in Claude Code to verify.');\n } else {\n writeLine(`Failed: ${mcpResult.message}`);\n if (snippet !== undefined) {\n writeEmptyLine();\n writeLine('Manual fallback - run:');\n writeEmptyLine();\n writeLine(formatCodeBlock(`claude mcp add-json nexus-agents '${snippet}'`));\n }\n }\n writeEmptyLine();\n}\n\n/**\n * Prints rules file section.\n */\nfunction printRulesFile(rulesPath: string): void {\n writeLine(formatHeader('Rules File'));\n writeLine('─'.repeat(40));\n writeLine(`Created: ${rulesPath}`);\n writeLine('Claude will now have context about nexus-agents tools.');\n writeEmptyLine();\n}\n\n/**\n * Prints hooks configuration result section.\n * (Source: Issue #416)\n */\nfunction printHooksResult(hookResult: HookConfigResult, snippet: string | undefined): void {\n writeLine(formatHeader('Hooks Configuration'));\n writeLine('─'.repeat(40));\n if (hookResult.success) {\n writeLine(hookResult.message);\n writeLine('Hooks will track sessions, metrics, and validate tool use.');\n } else {\n writeLine(`Note: ${hookResult.message}`);\n if (snippet !== undefined) {\n writeEmptyLine();\n writeLine('Manual fallback - add to ~/.claude/settings.json:');\n writeEmptyLine();\n writeLine(formatCodeBlock(snippet));\n }\n }\n writeEmptyLine();\n}\n\n/**\n * Prints warnings section.\n */\nfunction printWarnings(warnings: readonly string[]): void {\n writeLine(formatHeader('Warnings'));\n writeLine('─'.repeat(40));\n for (const warning of warnings) {\n writeLine(`⚠ ${warning}`);\n }\n writeEmptyLine();\n}\n\n/**\n * Prints errors section.\n */\nfunction printErrors(errors: readonly string[]): void {\n writeLine(formatHeader('Errors'));\n writeLine('─'.repeat(40));\n for (const error of errors) {\n writeLine(`✗ ${error}`);\n }\n writeEmptyLine();\n}\n\n/**\n * Prints next steps section.\n */\nfunction printNextSteps(mcpConfigured: boolean, hasMcpSnippet: boolean): void {\n writeLine(formatHeader('Next Steps'));\n writeLine('─'.repeat(40));\n if (hasMcpSnippet && !mcpConfigured) {\n writeLine('1. Configure MCP manually (see above)');\n writeLine('2. Restart Claude Code');\n }\n writeLine('3. Run: nexus-agents doctor');\n writeLine('4. Try: nexus-agents orchestrate \"Hello World\"');\n writeEmptyLine();\n}\n\n/**\n * Prints steps with status indicators.\n */\nfunction printSteps(steps: readonly SetupStep[], verbose: boolean): void {\n for (const step of steps) {\n const status = formatStatus(step.status);\n const duration = step.durationMs !== undefined ? ` (${String(step.durationMs)}ms)` : '';\n writeLine(`${status} ${step.name}${verbose ? duration : ''}`);\n if (step.message !== undefined && (verbose || step.status === 'failed')) {\n writeLine(` ${step.message}`);\n }\n }\n writeEmptyLine();\n}\n\n/**\n * Prints result summary line.\n */\nfunction printSummary(success: boolean): void {\n const summary = success ? '✓ Setup completed successfully!' : '✗ Setup completed with errors';\n writeLine(success ? `\\x1b[32m${summary}\\x1b[0m` : `\\x1b[31m${summary}\\x1b[0m`);\n writeEmptyLine();\n}\n\n// ============================================================================\n// Setup Steps\n// ============================================================================\n\n/**\n * Runs the environment detection step.\n */\nfunction runDetectionStep(projectRoot: string): { env: EnvironmentInfo; step: SetupStep } {\n const time = getTimeProvider();\n const startTime = time.now();\n const env = detectEnvironment(projectRoot);\n\n return {\n env,\n step: {\n name: 'Environment Detection',\n status: 'success',\n message: `Platform: ${env.platform}, Claude CLI: ${env.claudeCli.installed ? (env.claudeCli.version ?? 'installed') : 'not found'}`,\n durationMs: time.now() - startTime,\n },\n };\n}\n\n/** MCP step result type. */\ntype McpStepResult = {\n step: SetupStep;\n snippet: string | undefined;\n mcpResult: McpConfigResult | undefined;\n};\n\n/** Creates an MCP step result. */\nfunction makeMcpResult(\n status: SetupStep['status'],\n message: string,\n startTime: number,\n snippet?: string,\n mcpResult?: McpConfigResult\n): McpStepResult {\n return {\n step: {\n name: 'MCP Configuration',\n status,\n message,\n durationMs: getTimeProvider().now() - startTime,\n },\n snippet,\n mcpResult,\n };\n}\n\n/**\n * Runs the MCP configuration step.\n */\nfunction runMcpConfigStep(env: EnvironmentInfo, options: SetupOptions): McpStepResult {\n const startTime = getTimeProvider().now();\n\n if (options.skipMcp) {\n return makeMcpResult('skipped', 'Skipped (--skip-mcp)', startTime);\n }\n\n const useNpx = !env.claudeCli.installed;\n const snippet = generateMcpSnippet(useNpx);\n\n if (!env.claudeCli.installed) {\n const mcpResult: McpConfigResult = {\n success: false,\n alreadyConfigured: false,\n message: 'Claude CLI not installed',\n };\n return makeMcpResult(\n 'warning',\n 'Claude CLI not found - manual configuration required',\n startTime,\n snippet,\n mcpResult\n );\n }\n\n const mcpResult = configureMcpServer(useNpx, options.force, options.scope);\n const status = mcpResult.success\n ? mcpResult.alreadyConfigured\n ? 'skipped'\n : 'success'\n : 'failed';\n return makeMcpResult(\n status,\n mcpResult.message,\n startTime,\n mcpResult.success ? undefined : snippet,\n mcpResult\n );\n}\n\n/** Creates a rules step result. */\nfunction makeRulesResult(\n status: SetupStep['status'],\n message: string,\n startTime: number,\n rulesPath?: string\n): { step: SetupStep; rulesPath: string | undefined } {\n return {\n step: { name: 'Rules File', status, message, durationMs: getTimeProvider().now() - startTime },\n rulesPath,\n };\n}\n\n/** Creates a hooks step result. */\nfunction makeHooksResult(\n status: SetupStep['status'],\n message: string,\n startTime: number,\n hookResult?: HookConfigResult\n): { step: SetupStep; hookSnippet: string | undefined; hookResult: HookConfigResult | undefined } {\n return {\n step: {\n name: 'Hooks Configuration',\n status,\n message,\n durationMs: getTimeProvider().now() - startTime,\n },\n hookSnippet: hookResult?.success === false ? generateHookSnippet() : undefined,\n hookResult,\n };\n}\n\n/**\n * Runs the rules file generation step.\n */\nfunction runRulesStep(\n env: EnvironmentInfo,\n options: SetupOptions\n): { step: SetupStep; rulesPath: string | undefined } {\n const startTime = getTimeProvider().now();\n\n if (options.skipRules) {\n return makeRulesResult('skipped', 'Skipped (--skip-rules)', startTime);\n }\n\n const rulesPath = getRulesFilePath(env.projectInfo.root);\n if (existsSync(rulesPath) && !options.force) {\n return makeRulesResult(\n 'skipped',\n 'Rules file already exists (use --force to overwrite)',\n startTime\n );\n }\n\n try {\n const createdPath = createRulesFile(env.projectInfo.root, options.dryRun);\n const msg = options.dryRun ? `Would create: ${createdPath}` : `Created: ${createdPath}`;\n return makeRulesResult('success', msg, startTime, createdPath);\n } catch (error) {\n const msg = getErrorMessage(error);\n return makeRulesResult('failed', `Failed to create rules file: ${msg}`, startTime);\n }\n}\n\n/**\n * Runs the hooks configuration step.\n * (Source: Issue #416 - Setup command hook configuration)\n */\nfunction runHooksStep(\n env: EnvironmentInfo,\n options: SetupOptions\n): { step: SetupStep; hookSnippet: string | undefined; hookResult: HookConfigResult | undefined } {\n const startTime = getTimeProvider().now();\n\n if (options.skipHooks) {\n return makeHooksResult('skipped', 'Skipped (--skip-hooks)', startTime);\n }\n\n // If Claude CLI is not installed, we can't configure automatically\n if (!env.claudeCli.installed) {\n return makeHooksResult(\n 'warning',\n 'Claude CLI not found - manual hook configuration required',\n startTime,\n {\n success: false,\n alreadyConfigured: false,\n message: 'Claude CLI not installed',\n }\n );\n }\n\n // If dry-run, just report what would happen\n if (options.dryRun) {\n return makeHooksResult(\n 'success',\n 'Would configure nexus-agents hooks in Claude Code settings',\n startTime\n );\n }\n\n // Configure using Claude CLI\n const hookResult = configureHooks(options.force);\n const status = hookResult.success\n ? hookResult.alreadyConfigured\n ? 'skipped'\n : 'success'\n : 'failed';\n\n return makeHooksResult(status, hookResult.message, startTime, hookResult);\n}\n\n/**\n * Runs the OpenCode MCP configuration step (#1253).\n */\nfunction runOpenCodeStep(options: SetupOptions): SetupStep {\n const startTime = getTimeProvider().now();\n if (options.skipOpencode) {\n return {\n name: 'OpenCode MCP',\n status: 'skipped',\n message: 'Skipped (--skip-opencode)',\n durationMs: 0,\n };\n }\n const cliInfo = detectOpenCodeCli();\n if (!cliInfo.installed) {\n return {\n name: 'OpenCode MCP',\n status: 'skipped',\n message: 'OpenCode CLI not installed',\n durationMs: getTimeProvider().now() - startTime,\n };\n }\n const result = configureOpenCode(options.force, options.dryRun);\n return {\n name: 'OpenCode MCP',\n status: result.success ? (result.alreadyConfigured ? 'skipped' : 'success') : 'failed',\n message: result.message,\n durationMs: getTimeProvider().now() - startTime,\n };\n}\n\n/**\n * Runs the Gemini CLI MCP configuration step (#1259).\n */\nfunction runGeminiStep(options: SetupOptions): SetupStep {\n const startTime = getTimeProvider().now();\n if (options.skipGemini) {\n return {\n name: 'Gemini MCP',\n status: 'skipped',\n message: 'Skipped (--skip-gemini)',\n durationMs: 0,\n };\n }\n const cliInfo = detectGeminiCli();\n if (!cliInfo.installed) {\n return {\n name: 'Gemini MCP',\n status: 'skipped',\n message: 'Gemini CLI not installed',\n durationMs: getTimeProvider().now() - startTime,\n };\n }\n const result = configureGemini(options.force, options.dryRun, options.scope);\n return {\n name: 'Gemini MCP',\n status: result.success ? (result.alreadyConfigured ? 'skipped' : 'success') : 'failed',\n message: result.message,\n durationMs: getTimeProvider().now() - startTime,\n };\n}\n\n/**\n * Runs the data directory initialization step (#1249).\n */\nfunction runDataDirStep(options: SetupOptions): { step: SetupStep; result: DataDirInitResult } {\n const startTime = getTimeProvider().now();\n const dataDirResult = initDataDirectories(options.dryRun);\n return {\n step: {\n name: 'Data Directory',\n status: dataDirResult.success\n ? dataDirResult.created.length > 0\n ? 'success'\n : 'skipped'\n : 'failed',\n message: dataDirResult.success\n ? dataDirResult.created.length > 0\n ? `Created ${String(dataDirResult.created.length)} directories`\n : 'All directories already exist'\n : `Failed: ${dataDirResult.error ?? 'Unknown error'}`,\n durationMs: getTimeProvider().now() - startTime,\n },\n result: dataDirResult,\n };\n}\n\n/**\n * Runs the Codex CLI MCP configuration step (#1263).\n */\nfunction runCodexStep(options: SetupOptions): SetupStep {\n const startTime = getTimeProvider().now();\n if (options.skipCodex) {\n return {\n name: 'Codex MCP',\n status: 'skipped',\n message: 'Skipped (--skip-codex)',\n durationMs: 0,\n };\n }\n const cliInfo = detectCodexCli();\n if (!cliInfo.installed) {\n return {\n name: 'Codex MCP',\n status: 'skipped',\n message: 'Codex CLI not installed',\n durationMs: getTimeProvider().now() - startTime,\n };\n }\n const result = configureCodex(options.force, options.dryRun);\n return {\n name: 'Codex MCP',\n status: result.success ? (result.alreadyConfigured ? 'skipped' : 'success') : 'failed',\n message: result.message,\n durationMs: getTimeProvider().now() - startTime,\n };\n}\n\n/**\n * Runs the config file generation step (#1252).\n */\nfunction runConfigStep(projectRoot: string, options: SetupOptions): SetupStep {\n const startTime = getTimeProvider().now();\n if (options.skipConfig) {\n return {\n name: 'Configuration',\n status: 'skipped',\n message: 'Skipped (--skip-config)',\n durationMs: 0,\n };\n }\n const result = runConfigInitSync(projectRoot, options.force, options.dryRun);\n return {\n name: 'Configuration',\n status: result.success ? (result.created ? 'success' : 'skipped') : 'failed',\n message: result.message,\n durationMs: getTimeProvider().now() - startTime,\n };\n}\n\n/** Checks a named step's status, returning a check or issue string. */\nfunction checkStepStatus(steps: readonly SetupStep[], name: string, label: string): string {\n const step = steps.find((s) => s.name === name);\n const ok = step?.status === 'success' || step?.status === 'skipped';\n return ok ? `${label} OK` : `${label} failed`;\n}\n\n/**\n * Runs post-setup validation step (#1271).\n * Checks that critical setup outcomes are in place.\n */\nfunction runValidationStep(steps: readonly SetupStep[]): SetupStep {\n const startTime = getTimeProvider().now();\n\n const mcpSteps = steps.filter((s) => s.name.includes('MCP'));\n const mcpFailed = mcpSteps.filter((s) => s.status === 'failed').length;\n const mcpCheck =\n mcpFailed > 0\n ? `${String(mcpFailed)} MCP config(s) failed`\n : `${String(mcpSteps.length)} MCP configs OK`;\n\n const results = [\n mcpCheck,\n checkStepStatus(steps, 'Data Directory', 'Data dirs'),\n checkStepStatus(steps, 'Configuration', 'Config'),\n ];\n const hasIssues = results.some((r) => r.includes('failed'));\n\n return {\n name: 'Validation',\n status: hasIssues ? 'warning' : 'success',\n message: `${results.join(', ')}. Run \\`nexus-agents doctor\\` for full health check`,\n durationMs: getTimeProvider().now() - startTime,\n };\n}\n\n// ============================================================================\n// Main Command Helpers\n// ============================================================================\n\n/**\n * Adds Claude CLI warnings if not installed.\n */\nfunction addClaudeCliWarnings(warnings: string[], installed: boolean): void {\n if (!installed) {\n warnings.push(\n 'Claude CLI not found. Install it with: npm install -g @anthropic-ai/claude-code'\n );\n warnings.push('The MCP snippet uses npx to run nexus-agents (works without global install).');\n }\n}\n\n/**\n * Collects errors from failed steps.\n */\nfunction collectErrors(steps: readonly SetupStep[]): string[] {\n return steps.filter((s) => s.status === 'failed').map((s) => s.message ?? `${s.name} failed`);\n}\n\n/** Result context for building final result. */\ninterface SetupResultContext {\n startTime: number;\n steps: SetupStep[];\n warnings: string[];\n mcpResult: McpConfigResult | undefined;\n snippet: string | undefined;\n hookResult: HookConfigResult | undefined;\n hookSnippet: string | undefined;\n rulesPath: string | undefined;\n dataDirResult?: DataDirInitResult;\n}\n\n/** Checks if a config result represents a new (non-existing) success. */\nfunction isNewSuccess(result: McpConfigResult | HookConfigResult | undefined): boolean {\n return result?.success === true && !result.alreadyConfigured;\n}\n\n/** Builds the final setup result from context. */\nfunction buildSetupResult(ctx: SetupResultContext): SetupResult {\n const errors = collectErrors(ctx.steps);\n return {\n success: errors.length === 0,\n steps: ctx.steps,\n warnings: ctx.warnings,\n errors,\n durationMs: getTimeProvider().now() - ctx.startTime,\n ...(isNewSuccess(ctx.mcpResult) && { mcpConfigured: true }),\n ...(ctx.snippet !== undefined && { mcpSnippet: ctx.snippet }),\n ...(isNewSuccess(ctx.hookResult) && { hooksConfigured: true }),\n ...(ctx.hookSnippet !== undefined && { hookSnippet: ctx.hookSnippet }),\n ...(ctx.rulesPath !== undefined && { rulesPath: ctx.rulesPath }),\n ...(ctx.dataDirResult !== undefined && {\n dataDirPath: ctx.dataDirResult.rootPath,\n dataDirsCreated: ctx.dataDirResult.created.length,\n }),\n };\n}\n\n// ============================================================================\n// Main Command\n// ============================================================================\n\n/**\n * Runs the setup command.\n */\nexport function runSetup(options: Partial<SetupOptions> = {}): SetupResult {\n const startTime = getTimeProvider().now();\n const parsedOptions = SetupOptionsSchema.parse(options);\n const projectRoot = process.cwd();\n\n const warnings: string[] = [];\n\n // Step 1: Environment Detection\n const { env, step: detectionStep } = runDetectionStep(projectRoot);\n addClaudeCliWarnings(warnings, env.claudeCli.installed);\n\n // Step 2: MCP Configuration\n const { step: mcpStep, snippet, mcpResult } = runMcpConfigStep(env, parsedOptions);\n\n // Step 3: Rules File\n const { step: rulesStep, rulesPath } = runRulesStep(env, parsedOptions);\n\n // Step 4: Hooks Configuration (Issue #416)\n const { step: hooksStep, hookSnippet, hookResult } = runHooksStep(env, parsedOptions);\n\n // Step 5: Data Directory Initialization (#1249)\n const { step: dataDirStep, result: dataDirResult } = runDataDirStep(parsedOptions);\n\n // Step 6: OpenCode MCP Configuration (#1253)\n const openCodeStep = runOpenCodeStep(parsedOptions);\n\n // Step 7: Gemini MCP Configuration (#1259)\n const geminiStep = runGeminiStep(parsedOptions);\n\n // Step 8: Codex MCP Configuration (#1263)\n const codexStep = runCodexStep(parsedOptions);\n\n const configStep = runConfigStep(projectRoot, parsedOptions); // Step 9\n const steps = [\n detectionStep,\n mcpStep,\n rulesStep,\n hooksStep,\n dataDirStep,\n openCodeStep,\n geminiStep,\n codexStep,\n configStep,\n ];\n steps.push(runValidationStep(steps)); // Step 10: Validation (#1271)\n\n return buildSetupResult({\n startTime,\n steps,\n warnings,\n mcpResult,\n snippet,\n hookResult,\n hookSnippet,\n rulesPath,\n dataDirResult,\n });\n}\n\n/** Prints optional detail sections (MCP, hooks, rules, data dir). */\nfunction printDetailSections(result: SetupResult): void {\n if (result.mcpSnippet !== undefined || result.mcpConfigured === true) {\n const mcpResult: McpConfigResult =\n result.mcpConfigured === true\n ? {\n success: true,\n alreadyConfigured: false,\n message: 'Added nexus-agents MCP server to Claude Code',\n }\n : { success: false, alreadyConfigured: false, message: 'Manual configuration required' };\n printMcpResult(mcpResult, result.mcpSnippet);\n }\n if (result.hookSnippet !== undefined || result.hooksConfigured === true) {\n const hookResult: HookConfigResult =\n result.hooksConfigured === true\n ? {\n success: true,\n alreadyConfigured: false,\n message: 'Configured nexus-agents hooks in Claude Code settings',\n }\n : { success: false, alreadyConfigured: false, message: 'Manual configuration required' };\n printHooksResult(hookResult, result.hookSnippet);\n }\n if (result.rulesPath !== undefined) printRulesFile(result.rulesPath);\n if (result.dataDirPath !== undefined) printDataDirSection(result);\n}\n\n/** Prints the data directory section. */\nfunction printDataDirSection(result: SetupResult): void {\n writeLine(formatHeader('Data Directory'));\n writeLine('─'.repeat(40));\n const count = result.dataDirsCreated ?? 0;\n const msg =\n count > 0\n ? `Created ${String(count)} directories under ${result.dataDirPath ?? ''}`\n : `All directories already exist at ${result.dataDirPath ?? ''}`;\n writeLine(msg);\n writeEmptyLine();\n}\n\n/**\n * Prints the setup result.\n */\nexport function printSetupResult(result: SetupResult, verbose: boolean): void {\n writeEmptyLine();\n writeLine(formatHeader(`Nexus Agents Setup v${VERSION}`));\n writeLine('═'.repeat(40));\n writeEmptyLine();\n\n printSteps(result.steps, verbose);\n printDetailSections(result);\n\n if (result.warnings.length > 0) printWarnings(result.warnings);\n if (result.errors.length > 0) printErrors(result.errors);\n printNextSteps(result.mcpConfigured === true, result.mcpSnippet !== undefined);\n printSummary(result.success);\n}\n\n/**\n * Setup command entry point (synchronous, non-interactive).\n *\n * @returns Exit code (0 = success, 1 = failure)\n */\nexport function setupCommand(options: Partial<SetupOptions> = {}): number {\n const parsedOptions = SetupOptionsSchema.parse(options);\n\n // Check for non-interactive mode in CI\n if (!isInteractive() && !parsedOptions.nonInteractive) {\n writeLine('Non-interactive environment detected.');\n writeLine('Run with --non-interactive or set CI=true.');\n return 1;\n }\n\n const result = runSetup(options);\n printSetupResult(result, parsedOptions.verbose);\n\n return result.success ? 0 : 1;\n}\n\n/** Extended options including interactive flag. */\nexport interface SetupCommandOptions extends Partial<SetupOptions> {\n interactive?: boolean;\n}\n\n/**\n * Setup command entry point with interactive wizard support.\n * (Source: Issue #425 - Interactive setup wizard)\n *\n * @returns Exit code (0 = success, 1 = failure)\n */\nexport async function setupCommandAsync(options: SetupCommandOptions = {}): Promise<number> {\n // Run interactive wizard if requested\n if (options.interactive === true) {\n const wizardOptions = await runWizard();\n\n if (wizardOptions === undefined) {\n // User cancelled the wizard\n return 1;\n }\n\n // Merge wizard options with any existing options (wizard options take precedence)\n const mergedOptions = { ...options, ...wizardOptions };\n delete (mergedOptions as SetupCommandOptions).interactive; // Remove interactive flag\n\n const result = runSetup(mergedOptions);\n printSetupResult(result, mergedOptions.verbose ?? false);\n return result.success ? 0 : 1;\n }\n\n // Fall back to synchronous command\n return setupCommand(options);\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { generateMcpSnippet, generateRulesContent, detectEnvironment };\nexport { runWizard } from './setup-wizard.js';\nexport type { SetupOptions, SetupResult };\n// SetupCommandOptions is already exported via interface definition above\nexport type { WizardAnswers, UsageMode } from './setup-wizard.js';\n","/**\n * nexus-agents setup command types\n *\n * Type definitions for the user onboarding automation system.\n *\n * @module cli/setup-types\n * (Source: Issue #363 - Auto-configure Claude CLI integration)\n */\n\nimport { z } from 'zod';\nimport type { CommandResult } from '../core/index.js';\n\n/**\n * Setup command options schema.\n */\nexport const SetupOptionsSchema = z.object({\n /** Skip interactive prompts */\n nonInteractive: z.boolean().default(false),\n /** Overwrite existing configurations */\n force: z.boolean().default(false),\n /** Skip MCP configuration */\n skipMcp: z.boolean().default(false),\n /** Skip CLAUDE.md/rules generation */\n skipRules: z.boolean().default(false),\n /** Skip hooks configuration (Issue #416) */\n skipHooks: z.boolean().default(false),\n /** Skip config file generation (#1252) */\n skipConfig: z.boolean().default(false),\n /** Skip OpenCode MCP configuration (#1253) */\n skipOpencode: z.boolean().default(false),\n /** Skip Gemini CLI MCP configuration (#1259) */\n skipGemini: z.boolean().default(false),\n /** Skip Codex CLI MCP configuration (#1263) */\n skipCodex: z.boolean().default(false),\n /** Show what would be done without making changes */\n dryRun: z.boolean().default(false),\n /** Show detailed output */\n verbose: z.boolean().default(false),\n /** Target scope for MCP config */\n scope: z.enum(['user', 'project']).default('user'),\n});\n\nexport type SetupOptions = z.infer<typeof SetupOptionsSchema>;\n\n/**\n * Claude CLI detection result.\n */\nexport interface ClaudeCliInfo {\n readonly installed: boolean;\n readonly version: string | undefined;\n readonly configPath: string;\n readonly mcpJsonPath: string;\n}\n\n/**\n * Existing MCP configuration info.\n */\nexport interface McpConfigInfo {\n readonly exists: boolean;\n readonly path: string;\n readonly hasNexusAgents: boolean;\n readonly servers: readonly string[];\n}\n\n/**\n * MCP server configuration entry.\n */\nexport interface McpServerEntry {\n readonly command: string;\n readonly args?: readonly string[];\n readonly env?: Record<string, string>;\n}\n\n/**\n * MCP JSON configuration format.\n */\nexport interface McpJsonConfig {\n readonly mcpServers?: Record<string, McpServerEntry>;\n}\n\n/**\n * Project type detection.\n */\nexport type ProjectType =\n | 'typescript'\n | 'javascript'\n | 'python'\n | 'rust'\n | 'go'\n | 'java'\n | 'unknown';\n\n/**\n * Project information.\n */\nexport interface ProjectInfo {\n readonly root: string;\n readonly hasPackageJson: boolean;\n readonly hasClaudeMd: boolean;\n readonly hasClaudeRules: boolean;\n readonly hasNexusConfig: boolean;\n readonly projectType: ProjectType;\n readonly packageName?: string;\n}\n\n/**\n * Complete environment information.\n */\nexport interface EnvironmentInfo {\n readonly platform: NodeJS.Platform;\n readonly homeDir: string;\n readonly claudeCli: ClaudeCliInfo;\n readonly existingMcpConfig: McpConfigInfo | undefined;\n readonly projectInfo: ProjectInfo;\n}\n\n/**\n * Setup step status.\n */\nexport interface SetupStep {\n readonly name: string;\n readonly status: 'pending' | 'success' | 'skipped' | 'failed' | 'warning';\n readonly message?: string;\n readonly durationMs?: number;\n}\n\n/**\n * Setup result summary.\n * Extends CommandResult base pattern (Issue #584).\n */\nexport interface SetupResult extends CommandResult {\n /** Setup steps executed */\n readonly steps: readonly SetupStep[];\n /** MCP configuration was successful via Claude CLI */\n readonly mcpConfigured?: boolean;\n /** Fallback MCP snippet for manual configuration */\n readonly mcpSnippet?: string;\n /** Hooks configuration was successful via Claude CLI (Issue #416) */\n readonly hooksConfigured?: boolean;\n /** Fallback hook snippet for manual configuration */\n readonly hookSnippet?: string;\n readonly rulesPath?: string;\n /** Data directory path if initialized (#1249) */\n readonly dataDirPath?: string;\n /** Number of data directories created (#1249) */\n readonly dataDirsCreated?: number;\n readonly warnings: readonly string[];\n readonly errors: readonly string[];\n readonly durationMs: number;\n}\n\n/**\n * Backup information for rollback.\n */\nexport interface BackupInfo {\n readonly type: 'file';\n readonly originalPath: string;\n readonly backupPath: string;\n readonly content: string;\n}\n\n/**\n * Rollback item types.\n */\nexport type RollbackItem =\n | { type: 'file-backup'; backup: BackupInfo }\n | { type: 'file-created'; path: string }\n | { type: 'file-modified'; backup: BackupInfo };\n","/**\n * nexus-agents setup environment detection\n *\n * Environment detection helpers for Claude CLI and project setup.\n *\n * @module cli/setup-environment\n * (Source: Issue #363 - Auto-configure Claude CLI integration)\n */\n\nimport { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, basename } from 'node:path';\nimport { CLI_SUBPROCESS_TIMEOUTS } from '../config/timeouts.js';\nimport type {\n ClaudeCliInfo,\n McpConfigInfo,\n ProjectInfo,\n ProjectType,\n EnvironmentInfo,\n} from './setup-types.js';\n\n/**\n * Parses Claude CLI version from output.\n */\nfunction parseClaudeVersion(output: string): string | undefined {\n const match = output.match(/(\\d+\\.\\d+\\.\\d+)/);\n return match?.[1];\n}\n\n/**\n * Detects if Claude CLI is installed and available.\n * Uses a 3-second timeout to avoid hanging in slow environments.\n */\nexport function detectClaudeCli(): ClaudeCliInfo {\n const configPath = join(homedir(), '.claude');\n const mcpJsonPath = join(homedir(), '.claude.json');\n\n try {\n const result = execSync('claude --version', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: CLI_SUBPROCESS_TIMEOUTS.envSetupMs,\n });\n const version = parseClaudeVersion(result);\n\n return {\n installed: true,\n version,\n configPath,\n mcpJsonPath,\n };\n } catch {\n return {\n installed: false,\n version: undefined,\n configPath,\n mcpJsonPath,\n };\n }\n}\n\n/** Extracts MCP servers from direct mcpServers key (project-scoped .mcp.json). */\nfunction extractDirectServers(config: Record<string, unknown>): string[] | undefined {\n const mcpServers = config['mcpServers'] as Record<string, unknown> | undefined;\n if (mcpServers === undefined) return undefined;\n return Object.keys(mcpServers);\n}\n\n/** Extracts MCP servers from projects key (~/.claude.json format). */\nfunction extractProjectServers(config: Record<string, unknown>): string[] | undefined {\n const projects = config['projects'] as Record<string, Record<string, unknown>> | undefined;\n if (projects === undefined) return undefined;\n const allServers = new Set<string>();\n for (const proj of Object.values(projects)) {\n const mcpServers = proj['mcpServers'] as Record<string, unknown> | undefined;\n if (mcpServers !== undefined) Object.keys(mcpServers).forEach((n) => allServers.add(n));\n }\n return [...allServers];\n}\n\n/** Builds McpConfigInfo from a server list. */\nfunction buildMcpInfo(path: string, servers: string[]): McpConfigInfo {\n return { exists: true, path, hasNexusAgents: servers.includes('nexus-agents'), servers };\n}\n\n/**\n * Detects existing MCP configuration.\n *\n * Handles two formats:\n * - `.mcp.json` (project-scoped): `{ mcpServers: { ... } }`\n * - `~/.claude.json` (user-scoped): `{ projects: { [path]: { mcpServers: { ... } } } }`\n */\nexport function detectMcpConfig(mcpJsonPath: string): McpConfigInfo | undefined {\n if (!existsSync(mcpJsonPath)) return undefined;\n try {\n const config = JSON.parse(readFileSync(mcpJsonPath, 'utf-8')) as Record<string, unknown>;\n const direct = extractDirectServers(config);\n if (direct !== undefined) return buildMcpInfo(mcpJsonPath, direct);\n const projected = extractProjectServers(config);\n if (projected !== undefined) return buildMcpInfo(mcpJsonPath, projected);\n return buildMcpInfo(mcpJsonPath, []);\n } catch {\n return buildMcpInfo(mcpJsonPath, []);\n }\n}\n\n/** Checks for TypeScript in package.json devDependencies. */\nfunction hasTypeScriptInPackageJson(root: string): boolean {\n try {\n const content = readFileSync(join(root, 'package.json'), 'utf-8');\n const parsed: unknown = JSON.parse(content);\n const pkg = parsed as Record<string, unknown>;\n const devDeps = pkg['devDependencies'] as Record<string, string> | undefined;\n return devDeps?.['typescript'] !== undefined;\n } catch {\n return false;\n }\n}\n\n/** Mapping of config files to project types. */\nconst CONFIG_FILE_TYPES: readonly [string, ProjectType][] = [\n ['tsconfig.json', 'typescript'],\n ['Cargo.toml', 'rust'],\n ['go.mod', 'go'],\n ['pyproject.toml', 'python'],\n ['setup.py', 'python'],\n ['pom.xml', 'java'],\n ['build.gradle', 'java'],\n];\n\n/**\n * Detects project type based on configuration files.\n */\nexport function detectProjectType(root: string): ProjectType {\n // Check config files\n for (const [file, type] of CONFIG_FILE_TYPES) {\n if (existsSync(join(root, file))) return type;\n }\n\n // Check package.json\n if (existsSync(join(root, 'package.json'))) {\n return hasTypeScriptInPackageJson(root) ? 'typescript' : 'javascript';\n }\n\n return 'unknown';\n}\n\n/**\n * Detects project information.\n */\nexport function detectProjectInfo(root: string): ProjectInfo {\n let packageName: string | undefined;\n\n if (existsSync(join(root, 'package.json'))) {\n try {\n const content = readFileSync(join(root, 'package.json'), 'utf-8');\n const pkg = JSON.parse(content) as Record<string, unknown>;\n packageName = pkg['name'] as string | undefined;\n } catch (parseErr: unknown) {\n // Non-critical: package.json parse failure, fall through to basename\n void parseErr;\n }\n }\n\n return {\n root,\n hasPackageJson: existsSync(join(root, 'package.json')),\n hasClaudeMd: existsSync(join(root, 'CLAUDE.md')),\n hasClaudeRules: existsSync(join(root, '.claude', 'rules')),\n hasNexusConfig: existsSync(join(root, 'nexus-agents.yaml')),\n projectType: detectProjectType(root),\n packageName: packageName ?? basename(root),\n };\n}\n\n/**\n * Detects complete environment information.\n */\nexport function detectEnvironment(projectRoot: string): EnvironmentInfo {\n const claudeCli = detectClaudeCli();\n const existingMcpConfig = detectMcpConfig(claudeCli.mcpJsonPath);\n const projectInfo = detectProjectInfo(projectRoot);\n\n return {\n platform: process.platform,\n homeDir: homedir(),\n claudeCli,\n existingMcpConfig,\n projectInfo,\n };\n}\n","/**\n * nexus-agents setup MCP configuration\n *\n * MCP configuration helpers using Claude CLI's `claude mcp` commands.\n *\n * @module cli/setup-mcp\n * (Source: Issue #363 - Auto-configure Claude CLI integration)\n */\n\nimport { execSync, execFileSync } from 'node:child_process';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { McpJsonConfig, McpServerEntry } from './setup-types.js';\nimport { getErrorMessage } from '../core/index.js';\n\n/** MCP entry for nexus-agents */\nexport const NEXUS_AGENTS_MCP_ENTRY: McpServerEntry = {\n command: 'nexus-agents',\n args: ['--mode=server'],\n};\n\n/** MCP entry with npx for users who install globally */\nexport const NEXUS_AGENTS_MCP_NPX_ENTRY: McpServerEntry = {\n command: 'npx',\n args: ['-y', 'nexus-agents@latest', '--mode=server'],\n};\n\n/**\n * Result of MCP configuration attempt.\n */\nexport interface McpConfigResult {\n success: boolean;\n alreadyConfigured: boolean;\n message: string;\n}\n\n/**\n * Checks if nexus-agents MCP server is already configured in Claude CLI.\n */\nexport function isMcpServerConfigured(): boolean {\n try {\n const result = execSync('claude mcp get nexus-agents', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return result.includes('nexus-agents');\n } catch {\n return false;\n }\n}\n\n/**\n * Maps scope option to Claude CLI `-s` flag value.\n */\nfunction scopeToFlag(scope: 'user' | 'project'): string {\n return scope === 'project' ? 'local' : 'user';\n}\n\n/**\n * Removes existing MCP server configuration if present.\n */\nfunction removeExistingMcpServer(scope: 'user' | 'project' = 'user'): void {\n try {\n execSync(`claude mcp remove nexus-agents -s ${scopeToFlag(scope)}`, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n } catch {\n // Ignore removal errors\n }\n}\n\n/**\n * Adds MCP server to Claude CLI.\n */\nfunction addMcpServer(useNpx: boolean, scope: 'user' | 'project' = 'user'): McpConfigResult {\n const entry = useNpx ? NEXUS_AGENTS_MCP_NPX_ENTRY : NEXUS_AGENTS_MCP_ENTRY;\n const jsonConfig = JSON.stringify(entry);\n const scopeLabel = scope === 'project' ? 'project' : 'global';\n\n try {\n execFileSync(\n 'claude',\n ['mcp', 'add-json', 'nexus-agents', jsonConfig, '-s', scopeToFlag(scope)],\n {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }\n );\n return {\n success: true,\n alreadyConfigured: false,\n message: `Added nexus-agents MCP server to Claude Code (${scopeLabel})`,\n };\n } catch (error) {\n const errorMsg = getErrorMessage(error);\n return {\n success: false,\n alreadyConfigured: false,\n message: `Failed to add MCP server: ${errorMsg}`,\n };\n }\n}\n\n/**\n * Configures nexus-agents MCP server using Claude CLI.\n *\n * Uses `claude mcp add-json` to register the server.\n * @param scope - 'user' for global (~/.claude/mcp.json), 'project' for local (.mcp.json)\n */\nexport function configureMcpServer(\n useNpx: boolean = false,\n force: boolean = false,\n scope: 'user' | 'project' = 'user'\n): McpConfigResult {\n const isConfigured = isMcpServerConfigured();\n\n // Check if already configured\n if (!force && isConfigured) {\n return {\n success: true,\n alreadyConfigured: true,\n message: 'nexus-agents MCP server already configured (use --force to reconfigure)',\n };\n }\n\n // Remove existing if forcing\n if (force && isConfigured) {\n removeExistingMcpServer(scope);\n }\n\n return addMcpServer(useNpx, scope);\n}\n\n/**\n * Generates MCP configuration snippet for manual setup (fallback).\n */\nexport function generateMcpSnippet(useNpx: boolean = false): string {\n const entry = useNpx ? NEXUS_AGENTS_MCP_NPX_ENTRY : NEXUS_AGENTS_MCP_ENTRY;\n const config: McpJsonConfig = {\n mcpServers: {\n 'nexus-agents': entry,\n },\n };\n\n return JSON.stringify(config, null, 2);\n}\n\n/**\n * Generates the full MCP config path based on scope.\n *\n * Claude Code uses:\n * - Project scope: `.mcp.json` in project root\n * - User scope: `~/.claude.json` (stores MCP config under `projects` key)\n */\nexport function getMcpJsonPath(scope: 'user' | 'project', projectRoot: string): string {\n if (scope === 'project') {\n return join(projectRoot, '.mcp.json');\n }\n return join(homedir(), '.claude.json');\n}\n\n// ============================================================================\n// Hook Configuration (Issue #411, #416)\n// ============================================================================\n\n/**\n * Generates hook configuration for Claude CLI settings.json.\n * (Source: Issue #411 - Claude CLI Hook Integration)\n */\nexport function generateHookConfig(): HookSettingsConfig {\n return {\n hooks: {\n SessionStart: [\n {\n hooks: [\n {\n type: 'command',\n command: 'nexus-agents hooks session-start',\n },\n ],\n },\n ],\n PreToolUse: [\n {\n matcher: 'Bash',\n hooks: [\n {\n type: 'command',\n command: 'nexus-agents hooks pre-tool --tool Bash --validate',\n },\n ],\n },\n ],\n PostToolUse: [\n {\n matcher: '*',\n hooks: [\n {\n type: 'command',\n command: 'nexus-agents hooks post-tool --track-metrics',\n },\n ],\n },\n ],\n Stop: [\n {\n hooks: [\n {\n type: 'command',\n command: 'nexus-agents hooks stop --check-tasks',\n },\n ],\n },\n ],\n },\n };\n}\n\n/**\n * Hook command entry structure.\n */\ninterface HookCommandEntry {\n type: 'command';\n command: string;\n}\n\n/**\n * Hook matcher entry structure.\n */\ninterface HookMatcherEntry {\n matcher?: string;\n hooks: HookCommandEntry[];\n}\n\n/**\n * Hook settings configuration structure.\n */\nexport interface HookSettingsConfig {\n hooks: {\n SessionStart?: HookMatcherEntry[];\n SessionEnd?: HookMatcherEntry[];\n PreToolUse?: HookMatcherEntry[];\n PostToolUse?: HookMatcherEntry[];\n Stop?: HookMatcherEntry[];\n };\n}\n\n/**\n * Result of hook configuration attempt.\n */\nexport interface HookConfigResult {\n success: boolean;\n alreadyConfigured: boolean;\n message: string;\n}\n\n/**\n * Checks if hooks are already configured in Claude CLI settings.\n */\nexport function areHooksConfigured(): boolean {\n try {\n const result = execSync('claude config get hooks', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n // If we get output that includes nexus-agents, hooks are configured\n return result.includes('nexus-agents');\n } catch {\n return false;\n }\n}\n\n/**\n * Reads existing hooks from Claude CLI settings.\n * Returns parsed hooks object or undefined if no hooks exist or parse fails.\n */\nexport function getExistingHooks(): HookSettingsConfig['hooks'] | undefined {\n try {\n const result = execSync('claude config get hooks', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const trimmed = result.trim();\n if (!trimmed || trimmed === 'null' || trimmed === 'undefined') {\n return undefined;\n }\n return JSON.parse(trimmed) as HookSettingsConfig['hooks'];\n } catch {\n return undefined;\n }\n}\n\n/**\n * Merges two hook arrays, combining entries without duplicating nexus-agents hooks.\n */\nfunction mergeHookArrays(\n existing: HookMatcherEntry[] | undefined,\n newHooks: HookMatcherEntry[]\n): HookMatcherEntry[] {\n if (!existing || existing.length === 0) {\n return newHooks;\n }\n\n // Filter out any existing nexus-agents hooks to avoid duplicates\n const filteredExisting = existing.filter((entry) => {\n return !entry.hooks.some((h) => h.command.startsWith('nexus-agents'));\n });\n\n // Combine existing (non-nexus) hooks with new nexus-agents hooks\n return [...filteredExisting, ...newHooks];\n}\n\n/**\n * Merges nexus-agents hooks with existing hooks configuration.\n * Preserves existing user hooks while adding/updating nexus-agents hooks.\n */\nexport function mergeHookConfigs(\n existing: HookSettingsConfig['hooks'] | undefined,\n newConfig: HookSettingsConfig['hooks']\n): HookSettingsConfig['hooks'] {\n if (!existing) {\n return newConfig;\n }\n\n const hookTypes = ['SessionStart', 'SessionEnd', 'PreToolUse', 'PostToolUse', 'Stop'] as const;\n\n const merged: HookSettingsConfig['hooks'] = {};\n\n for (const hookType of hookTypes) {\n const existingHooks = existing[hookType];\n const newHooks = newConfig[hookType];\n\n if (newHooks) {\n merged[hookType] = mergeHookArrays(existingHooks, newHooks);\n } else if (existingHooks) {\n merged[hookType] = existingHooks;\n }\n }\n\n return merged;\n}\n\n/**\n * Configures hooks in Claude CLI settings.\n * Uses `claude config set hooks` to register hook commands.\n * Merges with existing hooks instead of overwriting them (Issue #420).\n */\nexport function configureHooks(force: boolean = false): HookConfigResult {\n const isConfigured = areHooksConfigured();\n\n if (!force && isConfigured) {\n return {\n success: true,\n alreadyConfigured: true,\n message: 'Hooks already configured (use --force to reconfigure)',\n };\n }\n\n const nexusHookConfig = generateHookConfig();\n\n try {\n // Read existing hooks first to merge (Issue #420)\n const existingHooks = getExistingHooks();\n const mergedHooks = mergeHookConfigs(existingHooks, nexusHookConfig.hooks);\n\n // Use claude config set with merged hooks\n const configJson = JSON.stringify(mergedHooks);\n execFileSync('claude', ['config', 'set', 'hooks', configJson], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return {\n success: true,\n alreadyConfigured: false,\n message: existingHooks\n ? 'Merged nexus-agents hooks with existing hooks in Claude Code settings'\n : 'Configured nexus-agents hooks in Claude Code settings',\n };\n } catch (error) {\n const errorMsg = getErrorMessage(error);\n return {\n success: false,\n alreadyConfigured: false,\n message: `Failed to configure hooks: ${errorMsg}`,\n };\n }\n}\n\n/**\n * Generates hook configuration snippet for manual setup.\n */\nexport function generateHookSnippet(): string {\n const config = generateHookConfig();\n return JSON.stringify(config, null, 2);\n}\n","/**\n * nexus-agents setup rules generation\n *\n * Rules file and backup management helpers.\n *\n * @module cli/setup-rules\n * (Source: Issue #363 - Auto-configure Claude CLI integration)\n */\n\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { VERSION } from '../version.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type { BackupInfo } from './setup-types.js';\n\n/**\n * Generates the nexus-agents rules file content.\n */\nexport function generateRulesContent(): string {\n return `# Nexus-Agents Integration\n\nThis project uses [nexus-agents](https://github.com/williamzujkowski/nexus-agents) v${VERSION} for multi-agent orchestration.\n\n## MCP Tools Available\n\nWhen running with MCP server mode, these tools are available:\n\n| Tool | Description |\n| ---- | ----------- |\n| \\`orchestrate\\` | Task orchestration with Orchestrator coordination |\n| \\`create_expert\\` | Dynamic expert agent creation |\n| \\`run_workflow\\` | Execute workflow templates |\n| \\`delegate_to_model\\` | Route task to optimal model |\n| \\`list_experts\\` | List available expert types (discoverability) |\n| \\`list_workflows\\` | List available workflow templates |\n\n## Quick Commands\n\n\\`\\`\\`bash\n# Orchestrate a task with specialized experts\nnexus-agents orchestrate \"Implement feature X with tests\"\n\n# List available experts\nnexus-agents expert list\n\n# Run a workflow\nnexus-agents workflow list\nnexus-agents workflow run code-review --input='{\"url\": \"...\"}'\n\n# Check system health\nnexus-agents doctor\n\n# Generate config\nnexus-agents config init\n\\`\\`\\`\n\n## Usage Examples\n\n**Orchestrate a code review:**\n\\`\\`\\`\nUse nexus-agents to review this PR: https://github.com/owner/repo/pull/123\n\\`\\`\\`\n\n**Create a specialized expert:**\n\\`\\`\\`\nCreate a security expert to audit this codebase for vulnerabilities\n\\`\\`\\`\n\n**Run a workflow:**\n\\`\\`\\`\nRun the code-review workflow with the current changes\n\\`\\`\\`\n\n## Configuration\n\n- Config file: \\`./nexus-agents.yaml\\`\n- Generate config: \\`nexus-agents config init\\`\n- Check health: \\`nexus-agents doctor\\`\n\n---\n*Generated by nexus-agents setup v${VERSION}*\n`;\n}\n\n/**\n * Gets the rules file path.\n */\nexport function getRulesFilePath(projectRoot: string): string {\n return join(projectRoot, '.claude', 'rules', 'nexus-agents.md');\n}\n\n/**\n * Creates the rules file.\n */\nexport function createRulesFile(projectRoot: string, dryRun: boolean): string {\n const rulesPath = getRulesFilePath(projectRoot);\n const content = generateRulesContent();\n\n if (!dryRun) {\n const rulesDir = dirname(rulesPath);\n mkdirSync(rulesDir, { recursive: true });\n writeFileSync(rulesPath, content, 'utf-8');\n }\n\n return rulesPath;\n}\n\n/**\n * Creates a backup of a file.\n */\nexport function backupFile(filePath: string): BackupInfo {\n const content = readFileSync(filePath, 'utf-8');\n const backupPath = `${filePath}.backup.${String(getTimeProvider().now())}`;\n writeFileSync(backupPath, content, 'utf-8');\n\n return {\n type: 'file',\n originalPath: filePath,\n backupPath,\n content,\n };\n}\n\n/**\n * Restores a file from backup.\n */\nexport function restoreBackup(backup: BackupInfo): void {\n writeFileSync(backup.originalPath, backup.content, 'utf-8');\n}\n","/**\n * nexus-agents setup output formatting\n *\n * Output formatting helpers for setup command.\n * Re-exports from consolidated ansi-output.ts for backward compatibility.\n *\n * @module cli/setup-formatting\n * (Source: Issue #363 - Auto-configure Claude CLI integration)\n */\n\n// Re-export consolidated formatters from ansi-output.ts\nexport { formatStatus, formatHeader, formatCodeBlock, colors, symbols } from './ansi-output.js';\n\n/**\n * Checks if running in interactive mode.\n */\nexport function isInteractive(): boolean {\n if (!process.stdout.isTTY) return false;\n if (process.env['CI'] === 'true') return false;\n if (process.env['CONTINUOUS_INTEGRATION'] !== undefined) return false;\n return true;\n}\n","/**\n * nexus-agents data directory initialization\n *\n * Pre-creates ~/.nexus-agents/ directory structure with proper permissions.\n * Used by `nexus-agents setup` to ensure data directories exist before first use.\n *\n * @module cli/setup-data-dir\n * (Source: Issue #1249 - Developer experience improvements)\n */\n\nimport { mkdirSync, existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { DATA_SUBDIRECTORIES } from './doctor.js';\n\n/** Root data directory path. */\nexport const NEXUS_DATA_DIR = join(homedir(), '.nexus-agents');\n\n/** Subdirectories requiring restricted permissions (owner-only). */\nconst RESTRICTED_DIRS = new Set(['auth']);\n\n/**\n * Result of data directory initialization.\n */\nexport interface DataDirInitResult {\n readonly success: boolean;\n readonly rootPath: string;\n readonly created: readonly string[];\n readonly alreadyExisted: readonly string[];\n readonly error: string | null;\n}\n\n/**\n * Creates the ~/.nexus-agents/ directory structure.\n * Sets restrictive permissions (0o700) on auth/ directory.\n *\n * @param dryRun - If true, reports what would be created without creating.\n * @returns Result of initialization.\n */\nexport function initDataDirectories(dryRun: boolean = false): DataDirInitResult {\n const created: string[] = [];\n const alreadyExisted: string[] = [];\n\n try {\n ensureDir(NEXUS_DATA_DIR, dryRun, created, alreadyExisted);\n\n for (const subdir of DATA_SUBDIRECTORIES) {\n const mode = RESTRICTED_DIRS.has(subdir) ? 0o700 : undefined;\n ensureDir(join(NEXUS_DATA_DIR, subdir), dryRun, created, alreadyExisted, mode);\n }\n\n return { success: true, rootPath: NEXUS_DATA_DIR, created, alreadyExisted, error: null };\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n return { success: false, rootPath: NEXUS_DATA_DIR, created, alreadyExisted, error: msg };\n }\n}\n\n/** Creates a single directory if it doesn't exist, tracking the result. */\nfunction ensureDir(\n dirPath: string,\n dryRun: boolean,\n created: string[],\n alreadyExisted: string[],\n mode?: number\n): void {\n if (existsSync(dirPath)) {\n alreadyExisted.push(dirPath);\n return;\n }\n if (!dryRun) {\n mkdirSync(dirPath, { recursive: true, ...(mode !== undefined ? { mode } : {}) });\n }\n created.push(dirPath);\n}\n","/* eslint-disable max-lines -- Cohesive doctor command module (governance: 400-600 OK if cohesive) */\n/**\n * nexus-agents doctor command\n *\n * Health check utility for CLI integration validation.\n * Verifies CLI installations, versions, authentication, Node.js version,\n * API keys, configuration files, and MCP server readiness.\n *\n * (Source: Issue #91, cli-project_plan.md DevEx amendment)\n * (Source: Issue #422 - Doctor command validations)\n */\n\nimport { existsSync, readFileSync, accessSync, constants as fsConstants } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { getTimeProvider, getErrorMessage } from '../core/index.js';\nimport {\n isPersistenceEnabled,\n LEARNING_DIR,\n OUTCOMES_FILE,\n RULES_FILE,\n} from '../config/learning-persistence.js';\nimport { createAllAdapters } from '../cli-adapters/factory.js';\nimport type { CliName, HealthStatus, CapacityStatus } from '../cli-adapters/types.js';\nimport { DEFAULT_MODEL_CAPABILITIES } from '../config/model-capabilities.js';\nimport { createServer } from '../mcp/server.js';\nimport { printDoctorResults } from './doctor-formatting.js';\n\n/** Required Node.js major version. */\nconst REQUIRED_NODE_MAJOR = 22;\n\n/** API key environment variable names. */\nconst API_KEY_VARS = ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'GOOGLE_AI_API_KEY'] as const;\n\n/** Configuration file paths to check (in order of priority). */\nconst CONFIG_FILE_PATHS = ['./nexus-agents.yaml', './nexus-agents.yml'] as const;\n\n/**\n * Check result for a single CLI.\n */\nexport interface CliCheckResult {\n readonly name: CliName;\n readonly installed: boolean;\n readonly version: string;\n readonly versionStatus: 'supported' | 'outdated' | 'unsupported' | 'breaking';\n readonly authenticated: boolean;\n readonly authMethod?: string;\n readonly capacity?: CapacityStatus;\n readonly error?: string;\n readonly fix?: string;\n}\n\n/**\n * Node.js version check result.\n */\nexport interface NodeVersionCheck {\n readonly version: string;\n readonly major: number;\n readonly supported: boolean;\n}\n\n/**\n * API key check result.\n */\nexport interface ApiKeyCheck {\n readonly name: string;\n readonly configured: boolean;\n}\n\n/**\n * Configuration file check result.\n */\nexport interface ConfigFileCheck {\n readonly found: boolean;\n readonly path: string | null;\n}\n\n/**\n * Model availability advisory entry (#890).\n */\nexport interface ModelAdvisory {\n readonly modelId: string;\n readonly displayName: string;\n readonly cliName: string;\n readonly available: boolean;\n readonly reason: string;\n}\n\n/**\n * Learning persistence health check result (#1017).\n */\nexport interface LearningPersistenceCheck {\n readonly enabled: boolean;\n readonly dirExists: boolean;\n readonly dirWritable: boolean;\n readonly outcomeCount: number;\n readonly ruleCount: number;\n readonly rulesLastSaved: string | null;\n readonly error: string | null;\n}\n\n/**\n * Registry advisory summary (#890).\n */\nexport interface RegistryAdvisory {\n readonly totalModels: number;\n readonly availableModels: number;\n readonly unavailableModels: number;\n readonly models: readonly ModelAdvisory[];\n}\n\n/**\n * SQLite (better-sqlite3) availability check (#1249).\n */\nexport interface SqliteCheck {\n readonly available: boolean;\n readonly error: string | null;\n}\n\n/**\n * Data directory health check (#1249).\n * Reports status of ~/.nexus-agents/ and its subdirectories.\n */\nexport interface DataDirectoryCheck {\n readonly rootExists: boolean;\n readonly rootPath: string;\n readonly subdirectories: readonly DataSubdirStatus[];\n}\n\n/**\n * Status of a single data subdirectory.\n */\nexport interface DataSubdirStatus {\n readonly name: string;\n readonly path: string;\n readonly exists: boolean;\n}\n\n/** Standard data subdirectories under ~/.nexus-agents/. */\nexport const DATA_SUBDIRECTORIES = [\n 'memory',\n 'memory/beliefs',\n 'learning',\n 'sessions',\n 'audit',\n 'voting',\n 'auth',\n 'research',\n 'checkpoints',\n] as const;\n\n/**\n * Complete doctor check results.\n */\nexport interface DoctorResult {\n readonly clis: CliCheckResult[];\n readonly nodeVersion: NodeVersionCheck;\n readonly apiKeys: ApiKeyCheck[];\n readonly configFile: ConfigFileCheck;\n readonly mcpServerReady: boolean;\n readonly mcpClientReady: boolean;\n /** Model registry advisory — which models are available (#890). */\n readonly registryAdvisory: RegistryAdvisory;\n /** Learning persistence health check (#1017). */\n readonly learningPersistence: LearningPersistenceCheck;\n /** SQLite (better-sqlite3) availability (#1249). */\n readonly sqliteCheck: SqliteCheck;\n /** Data directory health (#1249). */\n readonly dataDirectory: DataDirectoryCheck;\n readonly allHealthy: boolean;\n readonly timestamp: Date;\n}\n\n/**\n * Gets the CLI install/upgrade fix command.\n */\nfunction getFixCommand(name: CliName, issue: 'install' | 'upgrade' | 'auth'): string {\n const commands: Record<CliName, Record<string, string>> = {\n claude: {\n install: 'npm install -g @anthropic-ai/claude-code',\n upgrade: 'npm update -g @anthropic-ai/claude-code',\n auth: 'claude auth login',\n },\n gemini: {\n install: 'npm install -g @google/gemini-cli',\n upgrade: 'npm update -g @google/gemini-cli',\n auth: 'gemini auth login',\n },\n codex: {\n install: 'npm install -g @openai/codex',\n upgrade: 'npm update -g @openai/codex',\n auth: 'codex auth login',\n },\n opencode: {\n install: 'npm install -g opencode-ai',\n upgrade: 'npm update -g opencode-ai',\n auth: 'opencode auth login',\n },\n };\n return commands[name][issue] ?? '';\n}\n\n/**\n * Creates a result for when a CLI is not found.\n */\nfunction createNotFoundResult(name: CliName, errorMsg: string): CliCheckResult {\n return {\n name,\n installed: false,\n version: 'N/A',\n versionStatus: 'unsupported',\n authenticated: false,\n error: errorMsg,\n fix: getFixCommand(name, 'install'),\n };\n}\n\n/**\n * Determines the authentication method based on CLI name.\n * CLIs use their own auth mechanisms - we report the method type\n * rather than assuming a specific one like 'OAuth'.\n */\nfunction detectAuthMethod(name: CliName): string {\n const authMethods: Record<CliName, string> = {\n claude: 'CLI auth',\n gemini: 'ADC/CLI auth',\n codex: 'CLI auth',\n opencode: 'CLI auth',\n };\n return authMethods[name];\n}\n\n/**\n * Creates a result from a successful health check.\n */\nfunction createHealthyResult(\n name: CliName,\n health: HealthStatus,\n capacity?: CapacityStatus\n): CliCheckResult {\n const authenticated = health.healthy;\n\n const result: CliCheckResult = {\n name,\n installed: true,\n version: health.version,\n versionStatus: health.versionStatus,\n authenticated,\n ...(authenticated && { authMethod: detectAuthMethod(name) }),\n ...(capacity !== undefined && { capacity }),\n };\n\n if (health.message !== undefined && health.message !== '') {\n return { ...result, error: health.message };\n }\n if (!authenticated) {\n return { ...result, fix: getFixCommand(name, 'auth') };\n }\n if (health.versionStatus === 'outdated') {\n return { ...result, fix: getFixCommand(name, 'upgrade') };\n }\n\n return result;\n}\n\n/**\n * Runs health check on a single CLI adapter.\n */\nasync function checkCli(name: CliName): Promise<CliCheckResult> {\n const adapters = createAllAdapters();\n const adapter = adapters.get(name);\n\n if (!adapter) {\n return createNotFoundResult(name, 'Adapter not available');\n }\n\n try {\n const health: HealthStatus = await adapter.healthCheck();\n let capacity: CapacityStatus | undefined;\n\n try {\n capacity = await adapter.getCapacity();\n } catch (capErr: unknown) {\n // Capacity check is optional — some adapters don't support it\n void capErr; // Logged at debug via adapter internals\n }\n\n return createHealthyResult(name, health, capacity);\n } catch (error) {\n const message = getErrorMessage(error);\n const isNotFound = message.includes('ENOENT') || message.includes('not found');\n return createNotFoundResult(name, isNotFound ? 'Not found in PATH' : message);\n }\n}\n\n/**\n * Checks the Node.js version against the required version.\n */\nfunction checkNodeVersion(): NodeVersionCheck {\n const version = process.version;\n const major = Number(version.slice(1).split('.')[0]);\n return {\n version,\n major,\n supported: major >= REQUIRED_NODE_MAJOR,\n };\n}\n\n/**\n * Checks which API keys are configured in the environment.\n * Does NOT expose the actual key values - only reports presence.\n */\nfunction checkApiKeys(): ApiKeyCheck[] {\n return API_KEY_VARS.map((name) => ({\n name,\n configured: typeof process.env[name] === 'string' && process.env[name] !== '',\n }));\n}\n\n/**\n * Checks for the existence of a configuration file.\n */\nfunction checkConfigFile(): ConfigFileCheck {\n for (const configPath of CONFIG_FILE_PATHS) {\n if (existsSync(configPath)) {\n return { found: true, path: configPath };\n }\n }\n return { found: false, path: null };\n}\n\n/**\n * Validates that the MCP server can be created successfully.\n * This is a lightweight check that verifies server instantiation works.\n */\nfunction checkMcpServerReady(): boolean {\n try {\n const result = createServer({ name: 'nexus-agents-doctor-check' });\n return result.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Builds model registry advisory based on detected CLI availability (#890).\n */\nfunction buildRegistryAdvisory(cliResults: CliCheckResult[]): RegistryAdvisory {\n const installedClis = new Set(cliResults.filter((c) => c.installed).map((c) => c.name));\n\n const models: ModelAdvisory[] = DEFAULT_MODEL_CAPABILITIES.models\n .filter((m) => m.cliName !== undefined)\n .map((m) => {\n const cliName = m.cliName as string;\n const available = installedClis.has(cliName as CliName);\n const reason = available ? `${cliName} CLI is installed` : `${cliName} CLI is not installed`;\n return { modelId: m.id, displayName: m.displayName, cliName, available, reason };\n });\n\n return {\n totalModels: models.length,\n availableModels: models.filter((m) => m.available).length,\n unavailableModels: models.filter((m) => !m.available).length,\n models,\n };\n}\n\n/** Counts non-empty lines in a JSONL file. Returns 0 if file doesn't exist. */\nfunction countJsonlLines(filePath: string): number {\n if (!existsSync(filePath)) return 0;\n return readFileSync(filePath, 'utf-8')\n .split('\\n')\n .filter((l) => l.trim().length > 0).length;\n}\n\n/** Reads rules snapshot metadata. Returns count and savedAt. */\nfunction readRulesMetadata(filePath: string): { count: number; savedAt: string | null } {\n if (!existsSync(filePath)) return { count: 0, savedAt: null };\n try {\n const raw = JSON.parse(readFileSync(filePath, 'utf-8')) as Record<string, unknown>;\n const rules = raw['rules'];\n const saved = raw['savedAt'];\n return {\n count: Array.isArray(rules) ? rules.length : 0,\n savedAt: typeof saved === 'string' ? saved : null,\n };\n } catch {\n return { count: 0, savedAt: null };\n }\n}\n\n/** Checks if a directory exists and is writable. */\nfunction checkDirAccess(dir: string): { exists: boolean; writable: boolean } {\n const exists = existsSync(dir);\n if (!exists) return { exists: false, writable: false };\n try {\n accessSync(dir, fsConstants.W_OK);\n return { exists: true, writable: true };\n } catch {\n return { exists: true, writable: false };\n }\n}\n\nconst DISABLED_CHECK: LearningPersistenceCheck = {\n enabled: false,\n dirExists: false,\n dirWritable: false,\n outcomeCount: 0,\n ruleCount: 0,\n rulesLastSaved: null,\n error: null,\n};\n\n/** Checks learning persistence health (#1017). */\nfunction checkLearningPersistence(): LearningPersistenceCheck {\n if (!isPersistenceEnabled()) return DISABLED_CHECK;\n try {\n const { exists: dirExists, writable: dirWritable } = checkDirAccess(LEARNING_DIR);\n const outcomeCount = countJsonlLines(OUTCOMES_FILE);\n const { count: ruleCount, savedAt: rulesLastSaved } = readRulesMetadata(RULES_FILE);\n return {\n enabled: true,\n dirExists,\n dirWritable,\n outcomeCount,\n ruleCount,\n rulesLastSaved,\n error: null,\n };\n } catch (error: unknown) {\n return {\n enabled: true,\n dirExists: false,\n dirWritable: false,\n outcomeCount: 0,\n ruleCount: 0,\n rulesLastSaved: null,\n error: getErrorMessage(error),\n };\n }\n}\n\n/**\n * Checks if better-sqlite3 is available (#1249).\n * Memory backends (agentic, adaptive, typed, mobimem, decay) require it.\n */\nasync function checkSqlite(): Promise<SqliteCheck> {\n try {\n await import('better-sqlite3');\n return { available: true, error: null };\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n const isNotFound = msg.includes('Cannot find') || msg.includes('MODULE_NOT_FOUND');\n return {\n available: false,\n error: isNotFound\n ? 'better-sqlite3 not installed — 5 memory backends unavailable'\n : `better-sqlite3 load error: ${msg}`,\n };\n }\n}\n\n/**\n * Checks the ~/.nexus-agents/ data directory health (#1249).\n */\nfunction checkDataDirectory(): DataDirectoryCheck {\n const rootPath = join(homedir(), '.nexus-agents');\n const rootExists = existsSync(rootPath);\n\n const subdirectories: DataSubdirStatus[] = DATA_SUBDIRECTORIES.map((name) => {\n const fullPath = join(rootPath, name);\n return { name, path: fullPath, exists: existsSync(fullPath) };\n });\n\n return { rootExists, rootPath, subdirectories };\n}\n\n/**\n * Runs the complete doctor check.\n */\nexport async function runDoctor(): Promise<DoctorResult> {\n const clis = await Promise.all([\n checkCli('claude'),\n checkCli('gemini'),\n checkCli('codex'),\n checkCli('opencode'),\n ]);\n const nodeVersion = checkNodeVersion();\n const apiKeys = checkApiKeys();\n const configFile = checkConfigFile();\n const mcpServerReady = checkMcpServerReady();\n const codexCheck = clis.find((c) => c.name === 'codex');\n const mcpClientReady = codexCheck?.installed ?? false;\n const registryAdvisory = buildRegistryAdvisory(clis);\n const learningPersistence = checkLearningPersistence();\n const sqliteCheck = await checkSqlite();\n const dataDirectory = checkDataDirectory();\n\n // At least one API key configured or one CLI authenticated\n const hasAuthMethod =\n apiKeys.some((k) => k.configured) || clis.some((c) => c.installed && c.authenticated);\n\n const allHealthy =\n nodeVersion.supported &&\n hasAuthMethod &&\n mcpServerReady &&\n clis.every((c) => c.installed && c.authenticated && c.versionStatus !== 'unsupported');\n\n return {\n clis,\n nodeVersion,\n apiKeys,\n configFile,\n mcpServerReady,\n mcpClientReady,\n registryAdvisory,\n learningPersistence,\n sqliteCheck,\n dataDirectory,\n allHealthy,\n timestamp: new Date(getTimeProvider().now()),\n };\n}\n\n/** Doctor command options. */\nexport interface DoctorOptions {\n /** Auto-fix safe issues (run setup, generate config). */\n readonly fix?: boolean;\n}\n\n/**\n * Runs the doctor command and prints results.\n * Returns exit code (0 = healthy, 1 = issues found).\n */\nexport async function doctorCommand(options: DoctorOptions = {}): Promise<number> {\n const result = await runDoctor();\n printDoctorResults(result);\n\n if (options.fix === true) {\n await runDoctorFix(result);\n }\n\n return result.allHealthy ? 0 : 1;\n}\n\n/**\n * Auto-fixes safe issues found by doctor (#1254).\n * Only runs our own code — never execs external package managers.\n */\nasync function runDoctorFix(result: DoctorResult): Promise<void> {\n const writeLine = (text: string): void => {\n process.stdout.write(text + '\\n');\n };\n\n writeLine('');\n writeLine('\\x1b[1mAuto-fix\\x1b[0m');\n writeLine('─'.repeat(40));\n\n let fixCount = 0;\n\n // Fix: data directories\n if (\n !result.dataDirectory.rootExists ||\n result.dataDirectory.subdirectories.some((d) => !d.exists)\n ) {\n const { runSetup } = await import('./setup-command.js');\n const setupResult = runSetup({\n skipMcp: true,\n skipRules: true,\n skipHooks: true,\n skipConfig: true,\n skipOpencode: true,\n });\n if (setupResult.success) {\n writeLine('✓ Created missing data directories');\n fixCount++;\n }\n }\n\n // Fix: config file\n if (!result.configFile.found) {\n const { runConfigInitSync } = await import('./setup-config.js');\n const configResult = runConfigInitSync(process.cwd(), false, false);\n if (configResult.success && configResult.created) {\n writeLine(`✓ Generated config: ${configResult.path}`);\n fixCount++;\n }\n }\n\n // Display-only: better-sqlite3\n if (!result.sqliteCheck.available) {\n writeLine('');\n writeLine('⚠ better-sqlite3 not installed (manual step required):');\n writeLine(' npm install -g better-sqlite3');\n }\n\n if (fixCount > 0) {\n writeLine('');\n writeLine(\n `\\x1b[32m${String(fixCount)} issue(s) fixed.\\x1b[0m Re-run \\x1b[1mnexus-agents doctor\\x1b[0m to verify.`\n );\n } else {\n writeLine('No auto-fixable issues found.');\n }\n writeLine('');\n}\n\n// Re-export printDoctorResults for backward compatibility\nexport { printDoctorResults } from './doctor-formatting.js';\n","/**\n * nexus-agents doctor command - Formatting utilities\n *\n * Terminal output formatting for doctor command results.\n * Extracted to comply with 400-line file limit.\n *\n * (Source: Issue #422 - Doctor command validations)\n */\n\nimport { DEFAULT_CAPABILITIES } from '../cli-adapters/types.js';\nimport type { CapacityStatus } from '../cli-adapters/types.js';\nimport type {\n CliCheckResult,\n NodeVersionCheck,\n ApiKeyCheck,\n ConfigFileCheck,\n RegistryAdvisory,\n LearningPersistenceCheck,\n SqliteCheck,\n DataDirectoryCheck,\n DoctorResult,\n} from './doctor.js';\nimport { colors, symbols, writeLine } from './ansi-output.js';\nimport { capitalize } from '../utils/text-utils.js';\n\n/** Required Node.js major version (for warning message). */\nconst REQUIRED_NODE_MAJOR = 22;\n\n/**\n * Formats a status symbol with color.\n */\nfunction formatStatus(healthy: boolean, warn = false): string {\n if (healthy) return `${colors.green}${symbols.check}${colors.reset}`;\n if (warn) return `${colors.yellow}${symbols.warn}${colors.reset}`;\n return `${colors.red}${symbols.cross}${colors.reset}`;\n}\n\n/**\n * Formats version status with color.\n */\nfunction formatVersionStatus(status: string): string {\n switch (status) {\n case 'supported':\n return `${colors.green}supported${colors.reset}`;\n case 'outdated':\n return `${colors.yellow}outdated${colors.reset}`;\n case 'unsupported':\n case 'breaking':\n return `${colors.red}${status}${colors.reset}`;\n default:\n return status;\n }\n}\n\n/**\n * Formats capacity as percentage string.\n */\nfunction formatCapacity(capacity?: CapacityStatus): string {\n if (capacity === undefined) return 'Unknown';\n const remaining = 100 - capacity.utilizationPercent;\n const remainingStr = String(remaining);\n if (remaining > 80) return `${colors.green}${remainingStr}% remaining${colors.reset}`;\n if (remaining > 20) return `${colors.yellow}${remainingStr}% remaining${colors.reset}`;\n return `${colors.red}${remainingStr}% remaining${colors.reset}`;\n}\n\n/**\n * Prints details for an installed CLI.\n */\nfunction printInstalledCliDetails(cli: CliCheckResult): void {\n writeLine(` Version: ${cli.version} (${formatVersionStatus(cli.versionStatus)})`);\n\n const authText = cli.authenticated\n ? `${colors.green}${cli.authMethod ?? 'Authenticated'}${colors.reset}`\n : `${colors.red}Not authenticated${colors.reset}`;\n writeLine(` Auth: ${authText}`);\n\n if (cli.capacity !== undefined) {\n writeLine(` Capacity: ${formatCapacity(cli.capacity)}`);\n }\n}\n\n/**\n * Prints a single CLI result.\n */\nfunction printCliResult(cli: CliCheckResult): void {\n const status = cli.installed && cli.authenticated;\n const warn = cli.installed && (!cli.authenticated || cli.versionStatus === 'outdated');\n\n writeLine(\n `${formatStatus(status, warn)} ${colors.bold}${capitalize(cli.name)} CLI${colors.reset}`\n );\n\n if (cli.installed) {\n printInstalledCliDetails(cli);\n } else {\n const errorText = cli.error ?? 'Not installed';\n writeLine(` ${colors.red}Error: ${errorText}${colors.reset}`);\n }\n\n if (cli.fix !== undefined && cli.fix !== '') {\n writeLine(` ${colors.dim}Fix: ${cli.fix}${colors.reset}`);\n }\n\n writeLine('');\n}\n\n/**\n * Prints capability summary for installed CLIs.\n */\nfunction printCapabilities(clis: CliCheckResult[]): void {\n const installedClis = clis.filter((c) => c.installed);\n\n if (installedClis.length === 0) {\n writeLine(`${formatStatus(false)} No CLIs installed`);\n return;\n }\n\n const caps = DEFAULT_CAPABILITIES;\n const bestReasoning = installedClis.reduce((best, c) =>\n caps[c.name].reasoning > caps[best.name].reasoning ? c : best\n );\n const bestContext = installedClis.reduce((best, c) =>\n caps[c.name].contextWindow > caps[best.name].contextWindow ? c : best\n );\n const bestSpeed = installedClis.reduce((best, c) =>\n caps[c.name].speed > caps[best.name].speed ? c : best\n );\n\n const contextTokensK = (caps[bestContext.name].contextWindow / 1000).toFixed(0);\n\n writeLine(\n `${formatStatus(true)} Complex reasoning: ${colors.bold}${capitalize(bestReasoning.name)}${colors.reset}`\n );\n writeLine(\n `${formatStatus(true)} Large context: ${colors.bold}${capitalize(bestContext.name)}${colors.reset} (${contextTokensK}K tokens)`\n );\n writeLine(\n `${formatStatus(true)} Fast execution: ${colors.bold}${capitalize(bestSpeed.name)}${colors.reset}`\n );\n}\n\n/**\n * Prints Node.js version check result.\n */\nfunction printNodeVersionCheck(check: NodeVersionCheck): void {\n const versionText = check.supported\n ? `${colors.green}${check.version}${colors.reset}`\n : `${colors.yellow}${check.version}${colors.reset}`;\n writeLine(`${formatStatus(check.supported, !check.supported)} Node.js version: ${versionText}`);\n if (!check.supported) {\n writeLine(\n ` ${colors.dim}Warning: Node.js ${String(REQUIRED_NODE_MAJOR)}.x LTS required${colors.reset}`\n );\n }\n}\n\n/**\n * Prints API key configuration check results.\n */\nfunction printApiKeysCheck(keys: ApiKeyCheck[]): void {\n const configuredCount = keys.filter((k) => k.configured).length;\n const configuredNames = keys.filter((k) => k.configured).map((k) => k.name);\n const hasAny = configuredCount > 0;\n\n writeLine(\n `${formatStatus(hasAny, !hasAny)} API keys configured: ${String(configuredCount)} of ${String(keys.length)}`\n );\n if (hasAny) {\n writeLine(` ${colors.dim}Keys: ${configuredNames.join(', ')}${colors.reset}`);\n } else {\n writeLine(\n ` ${colors.dim}Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY${colors.reset}`\n );\n }\n}\n\n/**\n * Prints configuration file check result.\n */\nfunction printConfigFileCheck(check: ConfigFileCheck): void {\n if (check.found && check.path !== null) {\n writeLine(`${formatStatus(true)} Configuration loaded: ${check.path}`);\n } else {\n writeLine(`${formatStatus(false, true)} Configuration file: Not found`);\n writeLine(` ${colors.dim}Run: nexus-agents config init${colors.reset}`);\n }\n}\n\n/**\n * Prints model registry advisory (#890).\n */\nfunction printRegistryAdvisory(advisory: RegistryAdvisory): void {\n const allAvailable = advisory.unavailableModels === 0;\n const countText = `${String(advisory.availableModels)} of ${String(advisory.totalModels)}`;\n writeLine(`${formatStatus(allAvailable, !allAvailable)} Models available: ${countText}`);\n if (advisory.unavailableModels > 0) {\n const missing = advisory.models.filter((m) => !m.available);\n for (const m of missing) {\n writeLine(` ${colors.dim}${m.displayName} — ${m.reason}${colors.reset}`);\n }\n }\n}\n\n/**\n * Prints learning persistence health check (#1017).\n */\nfunction printLearningPersistence(check: LearningPersistenceCheck): void {\n if (!check.enabled) {\n writeLine(`${formatStatus(true)} Learning persistence: ${colors.dim}Disabled${colors.reset}`);\n writeLine(` ${colors.dim}Set NEXUS_PERSIST_LEARNING=true to enable${colors.reset}`);\n return;\n }\n\n const healthy = check.dirExists && check.dirWritable && check.error === null;\n writeLine(`${formatStatus(healthy, !healthy)} Learning persistence: Enabled`);\n\n if (check.error !== null) {\n writeLine(` ${colors.red}Error: ${check.error}${colors.reset}`);\n return;\n }\n\n const dirStatus = check.dirExists\n ? check.dirWritable\n ? `${colors.green}writable${colors.reset}`\n : `${colors.red}not writable${colors.reset}`\n : `${colors.yellow}not created yet${colors.reset}`;\n writeLine(` Data directory: ${dirStatus}`);\n writeLine(` Outcomes: ${String(check.outcomeCount)} recorded`);\n writeLine(` Distilled rules: ${String(check.ruleCount)} active`);\n if (check.rulesLastSaved !== null) {\n writeLine(` Rules last saved: ${check.rulesLastSaved}`);\n }\n}\n\n/**\n * Prints SQLite (better-sqlite3) availability check (#1249).\n */\nfunction printSqliteCheck(check: SqliteCheck): void {\n if (check.available) {\n writeLine(\n `${formatStatus(true)} SQLite (better-sqlite3): ${colors.green}Available${colors.reset}`\n );\n } else {\n writeLine(\n `${formatStatus(false, true)} SQLite (better-sqlite3): ${colors.yellow}Not available${colors.reset}`\n );\n writeLine(\n ` ${colors.dim}Memory backends (agentic, adaptive, typed) require it${colors.reset}`\n );\n writeLine(` ${colors.dim}Fix: npm install -g better-sqlite3${colors.reset}`);\n }\n}\n\n/**\n * Prints data directory health check (#1249).\n */\nfunction printDataDirectory(check: DataDirectoryCheck): void {\n if (check.rootExists) {\n const existCount = check.subdirectories.filter((d) => d.exists).length;\n const totalCount = check.subdirectories.length;\n const allExist = existCount === totalCount;\n writeLine(\n `${formatStatus(allExist, !allExist)} Data directory: ${check.rootPath} (${String(existCount)}/${String(totalCount)} subdirs)`\n );\n if (!allExist) {\n const missing = check.subdirectories.filter((d) => !d.exists);\n for (const dir of missing) {\n writeLine(` ${colors.dim}Missing: ${dir.name}/${colors.reset}`);\n }\n writeLine(` ${colors.dim}Fix: nexus-agents setup${colors.reset}`);\n }\n } else {\n writeLine(\n `${formatStatus(false, true)} Data directory: ${colors.yellow}Not created${colors.reset}`\n );\n writeLine(` ${colors.dim}Run: nexus-agents setup${colors.reset}`);\n }\n}\n\n/** Prints the summary line with issue count. */\nfunction printDoctorSummary(result: DoctorResult): void {\n const unhealthyCount = result.clis.filter((c) => !c.installed || !c.authenticated).length;\n const nodeIssue = result.nodeVersion.supported ? 0 : 1;\n const totalIssues = unhealthyCount + nodeIssue + (result.mcpServerReady ? 0 : 1);\n const summary = result.allHealthy\n ? `${colors.green}${colors.bold}Status: Ready${colors.reset}`\n : `${colors.yellow}${colors.bold}Summary: ${String(totalIssues)} issue(s) found${colors.reset}`;\n writeLine(summary);\n writeLine('');\n}\n\n/**\n * Prints the doctor results to stdout.\n */\nexport function printDoctorResults(result: DoctorResult): void {\n writeLine('');\n writeLine(`${colors.bold}Nexus Agents Doctor${colors.reset}`);\n writeLine('===================');\n writeLine('');\n\n writeLine(`${colors.cyan}Checking environment...${colors.reset}`);\n writeLine('');\n printNodeVersionCheck(result.nodeVersion);\n printApiKeysCheck(result.apiKeys);\n printConfigFileCheck(result.configFile);\n writeLine('');\n\n writeLine(`${colors.cyan}Checking CLI installations...${colors.reset}`);\n writeLine('');\n for (const cli of result.clis) {\n printCliResult(cli);\n }\n\n writeLine(`${colors.cyan}Checking MCP configuration...${colors.reset}`);\n writeLine('');\n writeLine(\n `${formatStatus(result.mcpServerReady)} MCP Server mode: ${result.mcpServerReady ? 'Ready' : 'Not ready'}`\n );\n writeLine(\n `${formatStatus(result.mcpClientReady)} MCP Client mode: ${result.mcpClientReady ? 'Ready (Codex mcp-server)' : 'Not ready (Codex not installed)'}`\n );\n writeLine('');\n\n writeLine(`${colors.cyan}Checking capabilities...${colors.reset}`);\n writeLine('');\n printCapabilities(result.clis);\n writeLine('');\n\n writeLine(`${colors.cyan}Checking model registry...${colors.reset}`);\n writeLine('');\n printRegistryAdvisory(result.registryAdvisory);\n writeLine('');\n\n writeLine(`${colors.cyan}Checking learning subsystem...${colors.reset}`);\n writeLine('');\n printLearningPersistence(result.learningPersistence);\n writeLine('');\n\n writeLine(`${colors.cyan}Checking data storage...${colors.reset}`);\n writeLine('');\n printSqliteCheck(result.sqliteCheck);\n printDataDirectory(result.dataDirectory);\n writeLine('');\n\n printDoctorSummary(result);\n}\n","/**\n * OpenCode MCP auto-configuration for setup command.\n *\n * Detects OpenCode CLI and generates opencode.json/.jsonc with nexus-agents MCP server.\n * Supports JSONC (JSON with Comments) via `jsonc-parser` for comment-preserving writes.\n *\n * @module cli/setup-opencode\n * (Source: Issue #1253 - OpenCode MCP auto-configuration, #1255 - JSONC support)\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { execFileSync } from 'node:child_process';\nimport { join, resolve } from 'node:path';\nimport { homedir, platform } from 'node:os';\nimport { parse as jsoncParse, modify, applyEdits } from 'jsonc-parser';\nimport { getErrorMessage } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\n\nconst logger = createLogger({ component: 'setup-opencode' });\n\n/** OpenCode detection result. */\nexport interface OpenCodeCliInfo {\n readonly installed: boolean;\n readonly version: string | undefined;\n}\n\n/** OpenCode MCP configuration result. */\nexport interface OpenCodeConfigResult {\n readonly success: boolean;\n readonly alreadyConfigured: boolean;\n readonly message: string;\n readonly configPath: string;\n}\n\n/** Resolved config file info. */\nexport interface ResolvedConfig {\n readonly path: string;\n readonly isJsonc: boolean;\n readonly exists: boolean;\n}\n\n/**\n * Detects OpenCode CLI installation.\n */\nexport function detectOpenCodeCli(): OpenCodeCliInfo {\n try {\n const cmd = platform() === 'win32' ? 'where' : 'which';\n execFileSync(cmd, ['opencode'], { timeout: 3000, stdio: 'pipe' });\n } catch {\n return { installed: false, version: undefined };\n }\n\n try {\n const output = execFileSync('opencode', ['--version'], {\n timeout: 5000,\n stdio: 'pipe',\n encoding: 'utf-8',\n });\n const match = /(\\d+\\.\\d+\\.\\d+)/.exec(output);\n return { installed: true, version: match?.[1] };\n } catch {\n return { installed: true, version: undefined };\n }\n}\n\n/**\n * Resolves the OpenCode config directory path.\n * OpenCode uses ~/.config/opencode/ on Linux/macOS.\n */\nfunction getOpenCodeConfigDir(): string {\n return join(homedir(), '.config', 'opencode');\n}\n\n/**\n * Resolves the path for nexus-agents CLI command.\n * Uses `npx nexus-agents` for portability.\n */\nfunction getNexusCommand(): readonly string[] {\n return ['npx', 'nexus-agents', '--mode=server'];\n}\n\nconst NEXUS_MCP_ENTRY = {\n type: 'local',\n command: getNexusCommand(),\n enabled: true,\n};\n\n/**\n * Resolves the OpenCode config file in a directory.\n * Prefers .jsonc over .json (matching OpenCode's own priority).\n */\nexport function resolveOpenCodeConfig(dir: string): ResolvedConfig {\n const jsoncPath = join(dir, 'opencode.jsonc');\n if (existsSync(jsoncPath)) {\n return { path: jsoncPath, isJsonc: true, exists: true };\n }\n const jsonPath = join(dir, 'opencode.json');\n if (existsSync(jsonPath)) {\n return { path: jsonPath, isJsonc: false, exists: true };\n }\n return { path: jsonPath, isJsonc: false, exists: false };\n}\n\n/** Checks if nexus-agents is already configured in an existing config. */\nfunction isAlreadyConfigured(resolved: ResolvedConfig): boolean {\n if (!resolved.exists) return false;\n try {\n const raw = readFileSync(resolved.path, 'utf-8');\n const config = jsoncParse(raw) as Record<string, unknown> | null;\n const mcp = config?.['mcp'] as Record<string, unknown> | undefined;\n return mcp?.['nexus-agents'] !== undefined;\n } catch {\n logger.debug('Failed to parse existing OpenCode config, will overwrite');\n return false;\n }\n}\n\n/** Writes nexus-agents MCP entry using comment-preserving edits for JSONC. */\nfunction writeJsoncConfig(configPath: string, raw: string): void {\n let result = raw;\n result = applyEdits(result, modify(result, ['mcp', 'nexus-agents'], NEXUS_MCP_ENTRY, {}));\n result = applyEdits(result, modify(result, ['$schema'], 'https://opencode.ai/config.json', {}));\n writeFileSync(configPath, result, 'utf-8');\n}\n\n/** Writes nexus-agents MCP entry as plain JSON for new configs. */\nfunction writeJsonConfig(configPath: string): void {\n const config = {\n $schema: 'https://opencode.ai/config.json',\n mcp: { 'nexus-agents': NEXUS_MCP_ENTRY },\n };\n writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\n/** Writes the merged config with nexus-agents MCP entry. */\nfunction writeOpenCodeConfig(configDir: string, resolved: ResolvedConfig): void {\n if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true });\n\n if (resolved.exists) {\n const raw = readFileSync(resolved.path, 'utf-8');\n writeJsoncConfig(resolved.path, raw);\n } else {\n writeJsonConfig(resolved.path);\n }\n}\n\n/** Options for configureOpenCode. */\nexport interface ConfigureOpenCodeOptions {\n readonly force: boolean;\n readonly dryRun: boolean;\n readonly projectRoot?: string;\n}\n\n/** Validates projectRoot to prevent path traversal (CWE-22). */\nfunction validateProjectRoot(projectRoot: string): string {\n const resolved = resolve(projectRoot);\n if (!existsSync(resolved)) {\n throw new Error(`Project root does not exist: ${resolved}`);\n }\n return resolved;\n}\n\n/**\n * Configures OpenCode with nexus-agents MCP server.\n * Supports both global (~/.config/opencode/) and project-local configs.\n */\nexport function configureOpenCode(\n force: boolean,\n dryRun: boolean,\n options?: ConfigureOpenCodeOptions\n): OpenCodeConfigResult {\n try {\n return configureOpenCodeInner(force, dryRun, options);\n } catch (error: unknown) {\n const fallbackPath = join(getOpenCodeConfigDir(), 'opencode.json');\n return {\n success: false,\n alreadyConfigured: false,\n message: `Failed to configure OpenCode: ${getErrorMessage(error)}`,\n configPath: fallbackPath,\n };\n }\n}\n\nfunction configureOpenCodeInner(\n force: boolean,\n dryRun: boolean,\n options?: ConfigureOpenCodeOptions\n): OpenCodeConfigResult {\n const configDir =\n options?.projectRoot !== undefined\n ? validateProjectRoot(options.projectRoot)\n : getOpenCodeConfigDir();\n const resolved = resolveOpenCodeConfig(configDir);\n\n if (isAlreadyConfigured(resolved) && !force) {\n return {\n success: true,\n alreadyConfigured: true,\n message: 'nexus-agents already configured in OpenCode',\n configPath: resolved.path,\n };\n }\n if (dryRun) {\n return {\n success: true,\n alreadyConfigured: false,\n message: `Would configure nexus-agents MCP in ${resolved.path}`,\n configPath: resolved.path,\n };\n }\n writeOpenCodeConfig(configDir, resolved);\n return {\n success: true,\n alreadyConfigured: false,\n message: 'Configured nexus-agents MCP in OpenCode',\n configPath: resolved.path,\n };\n}\n","/**\n * Gemini CLI MCP auto-configuration for setup command.\n *\n * Detects Gemini CLI and configures ~/.gemini/settings.json with nexus-agents MCP server.\n *\n * @module cli/setup-gemini\n * (Source: Issue #1259 - Gemini CLI MCP auto-configuration)\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { execFileSync } from 'node:child_process';\nimport { join } from 'node:path';\nimport { homedir, platform } from 'node:os';\nimport { getErrorMessage } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\n\nconst logger = createLogger({ component: 'setup-gemini' });\n\n/** Gemini CLI detection result. */\nexport interface GeminiCliInfo {\n readonly installed: boolean;\n readonly version: string | undefined;\n}\n\n/** Gemini MCP configuration result. */\nexport interface GeminiConfigResult {\n readonly success: boolean;\n readonly alreadyConfigured: boolean;\n readonly message: string;\n readonly configPath: string;\n}\n\n/** Gemini MCP server entry format. */\ninterface GeminiMcpEntry {\n readonly command: string;\n readonly args: readonly string[];\n readonly timeout: number;\n}\n\n/**\n * Detects Gemini CLI installation.\n */\nexport function detectGeminiCli(): GeminiCliInfo {\n try {\n const cmd = platform() === 'win32' ? 'where' : 'which';\n execFileSync(cmd, ['gemini'], { timeout: 3000, stdio: 'pipe' });\n } catch {\n return { installed: false, version: undefined };\n }\n\n try {\n const output = execFileSync('gemini', ['--version'], {\n timeout: 5000,\n stdio: 'pipe',\n encoding: 'utf-8',\n });\n const match = /(\\d+\\.\\d+\\.\\d+)/.exec(output);\n return { installed: true, version: match?.[1] };\n } catch {\n return { installed: true, version: undefined };\n }\n}\n\n/** Resolves the Gemini config directory path based on scope. */\nfunction getGeminiConfigDir(scope: 'user' | 'project', projectRoot?: string): string {\n if (scope === 'project' && projectRoot !== undefined) {\n return join(projectRoot, '.gemini');\n }\n return join(homedir(), '.gemini');\n}\n\n/** Returns the nexus-agents MCP entry for Gemini settings.json. */\nfunction getNexusMcpEntry(): GeminiMcpEntry {\n return {\n command: 'npx',\n args: ['nexus-agents', '--mode=server'],\n timeout: 30000,\n };\n}\n\n/** Checks if nexus-agents is already configured in settings.json. */\nfunction isAlreadyConfigured(configPath: string): boolean {\n if (!existsSync(configPath)) return false;\n try {\n const config = JSON.parse(readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n const servers = config['mcpServers'] as Record<string, unknown> | undefined;\n return servers?.['nexus-agents'] !== undefined;\n } catch {\n logger.debug('Failed to parse existing Gemini settings.json, will overwrite');\n return false;\n }\n}\n\n/** Reads existing config or returns empty object. */\nfunction readExistingConfig(configPath: string): Record<string, unknown> {\n if (!existsSync(configPath)) return {};\n try {\n return JSON.parse(readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/** Writes the merged config with nexus-agents MCP entry. */\nfunction writeGeminiConfig(configDir: string, configPath: string): void {\n if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true });\n const config = readExistingConfig(configPath);\n const servers = (config['mcpServers'] ?? {}) as Record<string, unknown>;\n servers['nexus-agents'] = getNexusMcpEntry();\n config['mcpServers'] = servers;\n writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Configures Gemini CLI with nexus-agents MCP server.\n *\n * @param force - Force reconfiguration even if already configured\n * @param dryRun - Preview changes without writing\n * @param scope - 'user' for global (~/.gemini/), 'project' for project-local (.gemini/)\n * @param projectRoot - Project root directory (required for project scope)\n */\nexport function configureGemini(\n force: boolean,\n dryRun: boolean,\n scope: 'user' | 'project' = 'user',\n projectRoot?: string\n): GeminiConfigResult {\n const configDir = getGeminiConfigDir(scope, projectRoot);\n const configPath = join(configDir, 'settings.json');\n\n if (isAlreadyConfigured(configPath) && !force) {\n return {\n success: true,\n alreadyConfigured: true,\n message: 'nexus-agents already configured in Gemini CLI',\n configPath,\n };\n }\n if (dryRun) {\n return {\n success: true,\n alreadyConfigured: false,\n message: `Would configure nexus-agents MCP in ${configPath}`,\n configPath,\n };\n }\n try {\n writeGeminiConfig(configDir, configPath);\n return {\n success: true,\n alreadyConfigured: false,\n message: 'Configured nexus-agents MCP in Gemini CLI',\n configPath,\n };\n } catch (error: unknown) {\n return {\n success: false,\n alreadyConfigured: false,\n message: `Failed to configure Gemini: ${getErrorMessage(error)}`,\n configPath,\n };\n }\n}\n","/**\n * Codex CLI MCP auto-configuration for setup command.\n *\n * Detects Codex CLI and registers nexus-agents MCP server\n * using `codex mcp add` CLI command.\n *\n * @module cli/setup-codex\n * (Source: Issue #1263 - Codex CLI MCP auto-configuration)\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { platform } from 'node:os';\nimport { getErrorMessage } from '../core/index.js';\nimport { createLogger } from '../core/index.js';\n\nconst logger = createLogger({ component: 'setup-codex' });\n\n/** Codex CLI detection result. */\nexport interface CodexCliInfo {\n readonly installed: boolean;\n readonly version: string | undefined;\n}\n\n/** Codex MCP configuration result. */\nexport interface CodexConfigResult {\n readonly success: boolean;\n readonly alreadyConfigured: boolean;\n readonly message: string;\n}\n\n/**\n * Detects Codex CLI installation.\n */\nexport function detectCodexCli(): CodexCliInfo {\n try {\n const cmd = platform() === 'win32' ? 'where' : 'which';\n execFileSync(cmd, ['codex'], { timeout: 3000, stdio: 'pipe' });\n } catch {\n return { installed: false, version: undefined };\n }\n\n try {\n const output = execFileSync('codex', ['--version'], {\n timeout: 5000,\n stdio: 'pipe',\n encoding: 'utf-8',\n });\n const match = /(\\d+\\.\\d+\\.\\d+)/.exec(output);\n return { installed: true, version: match?.[1] };\n } catch {\n return { installed: true, version: undefined };\n }\n}\n\n/**\n * Checks if nexus-agents is already configured in Codex MCP.\n */\nfunction isAlreadyConfigured(): boolean {\n try {\n const output = execFileSync('codex', ['mcp', 'list'], {\n timeout: 5000,\n stdio: 'pipe',\n encoding: 'utf-8',\n });\n return output.includes('nexus-agents');\n } catch {\n return false;\n }\n}\n\n/**\n * Removes existing nexus-agents MCP configuration from Codex.\n */\nfunction removeExisting(): void {\n try {\n execFileSync('codex', ['mcp', 'remove', 'nexus-agents'], {\n timeout: 5000,\n stdio: 'pipe',\n });\n } catch {\n logger.debug('Failed to remove existing Codex MCP config (may not exist)');\n }\n}\n\n/**\n * Adds nexus-agents MCP server to Codex CLI.\n *\n * Uses: codex mcp add nexus-agents -- npx nexus-agents --mode=server\n */\nfunction addMcpServer(): CodexConfigResult {\n try {\n execFileSync(\n 'codex',\n ['mcp', 'add', 'nexus-agents', '--', 'npx', 'nexus-agents', '--mode=server'],\n {\n timeout: 10000,\n stdio: 'pipe',\n }\n );\n return {\n success: true,\n alreadyConfigured: false,\n message: 'Configured nexus-agents MCP in Codex CLI',\n };\n } catch (error: unknown) {\n return {\n success: false,\n alreadyConfigured: false,\n message: `Failed to configure Codex: ${getErrorMessage(error)}`,\n };\n }\n}\n\n/**\n * Configures Codex CLI with nexus-agents MCP server.\n */\nexport function configureCodex(force: boolean, dryRun: boolean): CodexConfigResult {\n if (isAlreadyConfigured() && !force) {\n return {\n success: true,\n alreadyConfigured: true,\n message: 'nexus-agents already configured in Codex CLI',\n };\n }\n\n if (dryRun) {\n return {\n success: true,\n alreadyConfigured: false,\n message: 'Would configure nexus-agents MCP in Codex CLI',\n };\n }\n\n if (force && isAlreadyConfigured()) {\n removeExisting();\n }\n\n return addMcpServer();\n}\n","/**\n * nexus-agents setup interactive wizard\n *\n * Guided setup experience for configuring nexus-agents with Claude CLI.\n * Uses Node.js readline for terminal prompts without external dependencies.\n *\n * @module cli/setup-wizard\n * (Source: Issue #425 - Interactive setup wizard)\n */\n\nimport { createInterface, type Interface } from 'node:readline';\nimport { formatHeader, formatStatus, isInteractive } from './setup-formatting.js';\nimport type { SetupOptions } from './setup-types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Usage mode selection. */\nexport type UsageMode = 'claude-desktop' | 'claude-cli' | 'standalone' | 'all';\n\n/** Wizard answers collected from user. */\nexport interface WizardAnswers {\n usageMode: UsageMode;\n hasApiKeys: boolean;\n configDirectory: string;\n confirmProceed: boolean;\n}\n\n/** Wizard state during execution. */\ninterface WizardState {\n currentStep: number;\n totalSteps: number;\n answers: Partial<WizardAnswers>;\n}\n\n// ============================================================================\n// Readline Helpers\n// ============================================================================\n\n/**\n * Creates a readline interface for prompting.\n */\nfunction createReadline(): Interface {\n return createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n}\n\n/**\n * Prompts for input and returns the answer.\n */\nasync function promptInput(rl: Interface, question: string): Promise<string> {\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n resolve(answer.trim());\n });\n });\n}\n\n/**\n * Prompts for a yes/no confirmation.\n */\nasync function promptConfirm(\n rl: Interface,\n question: string,\n defaultValue = true\n): Promise<boolean> {\n const defaultHint = defaultValue ? '[Y/n]' : '[y/N]';\n const answer = await promptInput(rl, `${question} ${defaultHint}: `);\n\n if (answer === '') return defaultValue;\n return answer.toLowerCase().startsWith('y');\n}\n\n/**\n * Prints options for selection prompt.\n */\nfunction printOptions(\n options: readonly { value: string; label: string }[],\n defaultIndex: number\n): void {\n for (let i = 0; i < options.length; i++) {\n const option = options[i];\n const marker = i === defaultIndex ? '>' : ' ';\n const label = option?.label ?? '';\n writeLine(` ${marker} ${String(i + 1)}. ${label}`);\n }\n}\n\n/**\n * Gets value from options at index with fallback.\n */\nfunction getOptionValue(\n options: readonly { value: string; label: string }[],\n index: number,\n fallbackIndex: number\n): string {\n const option = options[index];\n if (option !== undefined) {\n return option.value;\n }\n const fallback = options[fallbackIndex];\n return fallback?.value ?? '';\n}\n\n/**\n * Prompts for a selection from a list of options.\n */\nasync function promptSelect(\n rl: Interface,\n question: string,\n options: readonly { value: string; label: string }[],\n defaultIndex = 0\n): Promise<string> {\n writeLine('\\n' + question);\n printOptions(options, defaultIndex);\n\n const answer = await promptInput(rl, `\\nChoice [1-${String(options.length)}]: `);\n\n if (answer === '') {\n return getOptionValue(options, defaultIndex, 0);\n }\n\n const index = parseInt(answer, 10) - 1;\n if (index >= 0 && index < options.length) {\n return getOptionValue(options, index, 0);\n }\n\n return getOptionValue(options, defaultIndex, 0);\n}\n\n// ============================================================================\n// Output Helpers\n// ============================================================================\n\n/** Writes a line to stdout. */\nfunction writeLine(text: string): void {\n process.stdout.write(text + '\\n');\n}\n\n/** Writes an empty line. */\nfunction writeEmptyLine(): void {\n process.stdout.write('\\n');\n}\n\n/** Prints the wizard header. */\nfunction printWizardHeader(): void {\n writeEmptyLine();\n writeLine(formatHeader('Nexus Agents Setup Wizard'));\n writeLine('='.repeat(40));\n writeLine('This wizard will help you configure nexus-agents.');\n writeEmptyLine();\n}\n\n/** Prints step progress. */\nfunction printStepProgress(state: WizardState, stepName: string): void {\n writeLine(\n `\\n${formatHeader(`Step ${String(state.currentStep)}/${String(state.totalSteps)}: ${stepName}`)}`\n );\n writeLine('-'.repeat(40));\n}\n\n/** Prints completion message. */\nfunction printCompletion(): void {\n writeEmptyLine();\n writeLine(formatStatus('success') + ' Wizard completed! Running setup...');\n writeEmptyLine();\n}\n\n// ============================================================================\n// Wizard Steps\n// ============================================================================\n\n/** Usage mode options. */\nconst USAGE_MODE_OPTIONS: readonly { value: UsageMode; label: string }[] = [\n { value: 'claude-cli', label: 'Claude CLI (terminal-based development)' },\n { value: 'claude-desktop', label: 'Claude Desktop (GUI application)' },\n { value: 'standalone', label: 'Standalone CLI (without Claude integration)' },\n { value: 'all', label: 'All of the above' },\n];\n\n/**\n * Step 1: Ask how the user plans to use nexus-agents.\n */\nasync function askUsageMode(rl: Interface, state: WizardState): Promise<UsageMode> {\n printStepProgress(state, 'Usage Mode');\n writeLine('How will you use nexus-agents?');\n\n const answer = await promptSelect(rl, '', USAGE_MODE_OPTIONS, 0);\n\n return answer as UsageMode;\n}\n\n/**\n * Step 2: Ask about API key configuration.\n */\nasync function askApiKeys(rl: Interface, state: WizardState): Promise<boolean> {\n printStepProgress(state, 'API Keys');\n writeLine('nexus-agents works best with API keys configured.');\n writeLine('Supported providers: Anthropic (Claude), OpenAI, Google (Gemini)');\n writeEmptyLine();\n\n const hasKeys = await promptConfirm(rl, 'Do you have at least one API key configured?', false);\n\n if (!hasKeys) {\n writeEmptyLine();\n writeLine('No worries! You can configure API keys later:');\n writeLine(' - ANTHROPIC_API_KEY for Claude');\n writeLine(' - OPENAI_API_KEY for OpenAI/Codex');\n writeLine(' - GOOGLE_AI_API_KEY for Gemini');\n writeLine('\\nRun `nexus-agents doctor` to check your configuration.');\n }\n\n return hasKeys;\n}\n\n/**\n * Step 3: Ask about configuration directory.\n */\nasync function askConfigDirectory(rl: Interface, state: WizardState): Promise<string> {\n printStepProgress(state, 'Configuration');\n writeLine('Where should nexus-agents store its configuration?');\n writeEmptyLine();\n\n const defaultDir = process.cwd();\n const answer = await promptInput(rl, `Directory [${defaultDir}]: `);\n\n return answer || defaultDir;\n}\n\n/**\n * Step 4: Confirm and proceed.\n */\nasync function askConfirmation(\n rl: Interface,\n state: WizardState,\n answers: Partial<WizardAnswers>\n): Promise<boolean> {\n printStepProgress(state, 'Confirmation');\n writeLine('Setup will configure the following:');\n writeEmptyLine();\n\n const modeLabel =\n USAGE_MODE_OPTIONS.find((o) => o.value === answers.usageMode)?.label ?? 'Unknown';\n const apiKeyStatus = answers.hasApiKeys === true ? 'Configured' : 'Not yet configured';\n const configDir = answers.configDirectory ?? process.cwd();\n writeLine(` Usage mode: ${modeLabel}`);\n writeLine(` API keys: ${apiKeyStatus}`);\n writeLine(` Config directory: ${configDir}`);\n writeEmptyLine();\n\n const skipMcp = answers.usageMode === 'standalone';\n if (!skipMcp) {\n writeLine('Will configure:');\n writeLine(' - MCP server for Claude integration');\n writeLine(' - Rules file (.claude/rules/nexus-agents.md)');\n writeLine(' - Hooks for session tracking');\n } else {\n writeLine('Will configure:');\n writeLine(' - Rules file (.claude/rules/nexus-agents.md)');\n writeLine(' - (Skipping MCP/hooks - not needed for standalone mode)');\n }\n\n writeEmptyLine();\n return promptConfirm(rl, 'Proceed with setup?', true);\n}\n\n// ============================================================================\n// Wizard Runner\n// ============================================================================\n\n/**\n * Runs the interactive setup wizard.\n *\n * @returns Setup options based on wizard answers, or undefined if cancelled\n */\nexport async function runWizard(): Promise<Partial<SetupOptions> | undefined> {\n // Check if interactive mode is available\n if (!isInteractive()) {\n writeLine('Interactive mode not available (TTY required).');\n writeLine('Use --non-interactive flag for automated setup.');\n return undefined;\n }\n\n const rl = createReadline();\n\n try {\n printWizardHeader();\n\n const state: WizardState = {\n currentStep: 1,\n totalSteps: 4,\n answers: {},\n };\n\n // Step 1: Usage mode\n state.answers.usageMode = await askUsageMode(rl, state);\n state.currentStep++;\n\n // Step 2: API keys\n state.answers.hasApiKeys = await askApiKeys(rl, state);\n state.currentStep++;\n\n // Step 3: Config directory\n state.answers.configDirectory = await askConfigDirectory(rl, state);\n state.currentStep++;\n\n // Step 4: Confirmation\n state.answers.confirmProceed = await askConfirmation(rl, state, state.answers);\n state.currentStep++;\n\n if (!state.answers.confirmProceed) {\n writeEmptyLine();\n writeLine('Setup cancelled.');\n return undefined;\n }\n\n printCompletion();\n\n // Convert wizard answers to setup options\n return convertAnswersToOptions(state.answers as WizardAnswers);\n } finally {\n rl.close();\n }\n}\n\n/**\n * Converts wizard answers to setup options.\n */\nfunction convertAnswersToOptions(answers: WizardAnswers): Partial<SetupOptions> {\n const isStandalone = answers.usageMode === 'standalone';\n\n return {\n // Skip MCP and hooks for standalone mode\n skipMcp: isStandalone,\n skipHooks: isStandalone,\n // Always create rules file\n skipRules: false,\n // Use user scope for Claude CLI/Desktop, project for standalone\n scope: isStandalone ? 'project' : 'user',\n // Non-interactive since we collected all info\n nonInteractive: true,\n // Show verbose output to explain what's happening\n verbose: true,\n };\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { isInteractive };\n"],"mappings":"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","names":["existsSync","execSync","homedir","join","execSync","execSync","readFileSync","join","join","mkdirSync","existsSync","homedir","join","existsSync","readFileSync","homedir","join","formatStatus","REQUIRED_NODE_MAJOR","existsSync","readFileSync","join","homedir","writeLine","runSetup","runConfigInitSync","join","homedir","existsSync","mkdirSync","existsSync","readFileSync","writeFileSync","mkdirSync","execFileSync","join","homedir","execFileSync","join","homedir","existsSync","readFileSync","writeFileSync","mkdirSync","existsSync","readFileSync","writeFileSync","mkdirSync","execFileSync","join","homedir","platform","logger","platform","execFileSync","join","homedir","isAlreadyConfigured","existsSync","readFileSync","mkdirSync","writeFileSync","execFileSync","platform","logger","platform","execFileSync","isAlreadyConfigured","addMcpServer","resolve","writeLine","writeLine","writeEmptyLine","mcpResult","existsSync"]}
|