@triedotdev/mcp 1.0.169 → 1.0.170

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.
Files changed (145) hide show
  1. package/README.md +54 -545
  2. package/dist/chunk-2YXOBNKW.js +619 -0
  3. package/dist/chunk-2YXOBNKW.js.map +1 -0
  4. package/dist/chunk-QR64Y5TI.js +363 -0
  5. package/dist/chunk-QR64Y5TI.js.map +1 -0
  6. package/dist/cli/main.d.ts +0 -15
  7. package/dist/cli/main.js +356 -3098
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/index.js +2 -34
  10. package/dist/index.js.map +1 -1
  11. package/dist/server/mcp-server.js +2 -34
  12. package/package.json +8 -31
  13. package/dist/autonomy-config-FSERX3O3.js +0 -30
  14. package/dist/autonomy-config-FSERX3O3.js.map +0 -1
  15. package/dist/chat-store-JNGNTDSN.js +0 -15
  16. package/dist/chat-store-JNGNTDSN.js.map +0 -1
  17. package/dist/chunk-2HF65EHQ.js +0 -311
  18. package/dist/chunk-2HF65EHQ.js.map +0 -1
  19. package/dist/chunk-3XR6WVAW.js +0 -4011
  20. package/dist/chunk-3XR6WVAW.js.map +0 -1
  21. package/dist/chunk-43X6JBEM.js +0 -36
  22. package/dist/chunk-43X6JBEM.js.map +0 -1
  23. package/dist/chunk-6NLHFIYA.js +0 -344
  24. package/dist/chunk-6NLHFIYA.js.map +0 -1
  25. package/dist/chunk-7IO4YUI3.js +0 -1827
  26. package/dist/chunk-7IO4YUI3.js.map +0 -1
  27. package/dist/chunk-AHD2CBQ7.js +0 -846
  28. package/dist/chunk-AHD2CBQ7.js.map +0 -1
  29. package/dist/chunk-BUTOP5EB.js +0 -931
  30. package/dist/chunk-BUTOP5EB.js.map +0 -1
  31. package/dist/chunk-DGUM43GV.js +0 -11
  32. package/dist/chunk-DGUM43GV.js.map +0 -1
  33. package/dist/chunk-EFWVF6TI.js +0 -267
  34. package/dist/chunk-EFWVF6TI.js.map +0 -1
  35. package/dist/chunk-F6WFNUAY.js +0 -216
  36. package/dist/chunk-F6WFNUAY.js.map +0 -1
  37. package/dist/chunk-FBNURWRY.js +0 -662
  38. package/dist/chunk-FBNURWRY.js.map +0 -1
  39. package/dist/chunk-FQ45QP5A.js +0 -361
  40. package/dist/chunk-FQ45QP5A.js.map +0 -1
  41. package/dist/chunk-FVRO5RN3.js +0 -1306
  42. package/dist/chunk-FVRO5RN3.js.map +0 -1
  43. package/dist/chunk-G2TGF6TR.js +0 -573
  44. package/dist/chunk-G2TGF6TR.js.map +0 -1
  45. package/dist/chunk-G3I7SZLW.js +0 -354
  46. package/dist/chunk-G3I7SZLW.js.map +0 -1
  47. package/dist/chunk-GTKYBOXL.js +0 -700
  48. package/dist/chunk-GTKYBOXL.js.map +0 -1
  49. package/dist/chunk-HVCDY3AK.js +0 -850
  50. package/dist/chunk-HVCDY3AK.js.map +0 -1
  51. package/dist/chunk-I2O5OYQT.js +0 -727
  52. package/dist/chunk-I2O5OYQT.js.map +0 -1
  53. package/dist/chunk-JVMBCWKS.js +0 -348
  54. package/dist/chunk-JVMBCWKS.js.map +0 -1
  55. package/dist/chunk-KCUOWRPX.js +0 -816
  56. package/dist/chunk-KCUOWRPX.js.map +0 -1
  57. package/dist/chunk-KDHN2ZQE.js +0 -313
  58. package/dist/chunk-KDHN2ZQE.js.map +0 -1
  59. package/dist/chunk-ME2OERF5.js +0 -345
  60. package/dist/chunk-ME2OERF5.js.map +0 -1
  61. package/dist/chunk-OBQ74FOU.js +0 -27
  62. package/dist/chunk-OBQ74FOU.js.map +0 -1
  63. package/dist/chunk-Q5EKA5YA.js +0 -254
  64. package/dist/chunk-Q5EKA5YA.js.map +0 -1
  65. package/dist/chunk-Q63FFI6D.js +0 -132
  66. package/dist/chunk-Q63FFI6D.js.map +0 -1
  67. package/dist/chunk-SASNMSB5.js +0 -12597
  68. package/dist/chunk-SASNMSB5.js.map +0 -1
  69. package/dist/chunk-T63OHG4Q.js +0 -440
  70. package/dist/chunk-T63OHG4Q.js.map +0 -1
  71. package/dist/chunk-TN5WEKWI.js +0 -173
  72. package/dist/chunk-TN5WEKWI.js.map +0 -1
  73. package/dist/chunk-VUL52BQL.js +0 -402
  74. package/dist/chunk-VUL52BQL.js.map +0 -1
  75. package/dist/chunk-VVITXIHN.js +0 -189
  76. package/dist/chunk-VVITXIHN.js.map +0 -1
  77. package/dist/chunk-WCN7S3EI.js +0 -14
  78. package/dist/chunk-WCN7S3EI.js.map +0 -1
  79. package/dist/chunk-XPZZFPBZ.js +0 -491
  80. package/dist/chunk-XPZZFPBZ.js.map +0 -1
  81. package/dist/chunk-ZJF5FTBX.js +0 -1396
  82. package/dist/chunk-ZJF5FTBX.js.map +0 -1
  83. package/dist/chunk-ZV2K6M7T.js +0 -74
  84. package/dist/chunk-ZV2K6M7T.js.map +0 -1
  85. package/dist/cli/create-agent.d.ts +0 -1
  86. package/dist/cli/create-agent.js +0 -1050
  87. package/dist/cli/create-agent.js.map +0 -1
  88. package/dist/cli/yolo-daemon.d.ts +0 -1
  89. package/dist/cli/yolo-daemon.js +0 -421
  90. package/dist/cli/yolo-daemon.js.map +0 -1
  91. package/dist/client-NJPZE5JT.js +0 -28
  92. package/dist/client-NJPZE5JT.js.map +0 -1
  93. package/dist/codebase-index-VAPF32XX.js +0 -12
  94. package/dist/codebase-index-VAPF32XX.js.map +0 -1
  95. package/dist/fast-analyzer-3GCCZMLK.js +0 -216
  96. package/dist/fast-analyzer-3GCCZMLK.js.map +0 -1
  97. package/dist/git-EO5SRFMN.js +0 -28
  98. package/dist/git-EO5SRFMN.js.map +0 -1
  99. package/dist/github-ingester-ZOKK6GRS.js +0 -11
  100. package/dist/github-ingester-ZOKK6GRS.js.map +0 -1
  101. package/dist/goal-manager-QUKX2W6C.js +0 -25
  102. package/dist/goal-manager-QUKX2W6C.js.map +0 -1
  103. package/dist/goal-validator-2SFSKKVU.js +0 -24
  104. package/dist/goal-validator-2SFSKKVU.js.map +0 -1
  105. package/dist/graph-B3NA4S7I.js +0 -10
  106. package/dist/graph-B3NA4S7I.js.map +0 -1
  107. package/dist/hypothesis-KCPBR652.js +0 -23
  108. package/dist/hypothesis-KCPBR652.js.map +0 -1
  109. package/dist/incident-index-EFNUSGWL.js +0 -11
  110. package/dist/incident-index-EFNUSGWL.js.map +0 -1
  111. package/dist/insight-store-EC4PLSAW.js +0 -22
  112. package/dist/insight-store-EC4PLSAW.js.map +0 -1
  113. package/dist/issue-store-YAXTNRRY.js +0 -36
  114. package/dist/issue-store-YAXTNRRY.js.map +0 -1
  115. package/dist/ledger-TWZTGDFA.js +0 -58
  116. package/dist/ledger-TWZTGDFA.js.map +0 -1
  117. package/dist/linear-ingester-XXPAZZRW.js +0 -11
  118. package/dist/linear-ingester-XXPAZZRW.js.map +0 -1
  119. package/dist/output-manager-RVJ37XKA.js +0 -13
  120. package/dist/output-manager-RVJ37XKA.js.map +0 -1
  121. package/dist/parse-goal-violation-SACGFG3C.js +0 -8
  122. package/dist/parse-goal-violation-SACGFG3C.js.map +0 -1
  123. package/dist/pattern-discovery-F7LU5K6E.js +0 -8
  124. package/dist/pattern-discovery-F7LU5K6E.js.map +0 -1
  125. package/dist/progress-SRQ2V3BP.js +0 -18
  126. package/dist/progress-SRQ2V3BP.js.map +0 -1
  127. package/dist/project-state-AHPA77SM.js +0 -28
  128. package/dist/project-state-AHPA77SM.js.map +0 -1
  129. package/dist/sync-M2FSWPBC.js +0 -12
  130. package/dist/sync-M2FSWPBC.js.map +0 -1
  131. package/dist/terminal-spawn-5YXDMUCF.js +0 -157
  132. package/dist/terminal-spawn-5YXDMUCF.js.map +0 -1
  133. package/dist/tiered-storage-DYNC5CQ6.js +0 -13
  134. package/dist/tiered-storage-DYNC5CQ6.js.map +0 -1
  135. package/dist/trie-agent-I3HAHY2G.js +0 -26
  136. package/dist/trie-agent-I3HAHY2G.js.map +0 -1
  137. package/dist/ui/chat.html +0 -1014
  138. package/dist/ui/goals.html +0 -967
  139. package/dist/ui/hypotheses.html +0 -1011
  140. package/dist/ui/ledger.html +0 -954
  141. package/dist/ui/nudges.html +0 -995
  142. package/dist/vibe-code-signatures-5ZULYP3D.js +0 -987
  143. package/dist/vibe-code-signatures-5ZULYP3D.js.map +0 -1
  144. package/dist/vulnerability-signatures-2URZSXAQ.js +0 -983
  145. package/dist/vulnerability-signatures-2URZSXAQ.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/agent/goal-manager.ts"],"sourcesContent":["/**\n * Goal Manager - Autonomous goal generation and tracking\n * \n * Features:\n * - Auto-generates goals from incident patterns\n * - Tracks goal progress over time\n * - Presents goals to users for acceptance/rejection\n * - Adaptive goal difficulty based on team velocity\n * - Goal achievement celebrations\n */\n\nimport type { Goal } from './project-state.js';\nimport { getProjectState } from './project-state.js';\nimport { getInsightStore, type Insight } from './insight-store.js';\nimport { searchIssues, getMemoryStats } from '../memory/issue-store.js';\nimport { basename } from 'path';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A pattern detected from incident history\n */\nexport interface IncidentPattern {\n type: 'file-cluster' | 'severity-trend' | 'agent-concentration' | 'time-pattern';\n description: string;\n metric: string;\n currentValue: number;\n suggestedTarget: number;\n confidence: number; // 0-1\n evidence: string[];\n category?: 'security' | 'quality' | 'performance' | 'coverage' | 'general';\n}\n\n/**\n * Goal opportunity - a potential goal before user acceptance\n */\nexport interface GoalOpportunity {\n pattern: IncidentPattern;\n goal: Omit<Goal, 'id' | 'createdAt' | 'updatedAt'>;\n reasoning: string;\n}\n\n/**\n * Configuration for goal generation\n */\nexport interface GoalGenerationConfig {\n minConfidence: number; // Minimum confidence to suggest goal (0-1)\n maxActiveGoals: number; // Maximum concurrent active goals\n goalDurationDays: number; // Default goal duration in days\n reductionTargetPercent: number; // Target reduction percentage\n}\n\nconst DEFAULT_CONFIG: GoalGenerationConfig = {\n minConfidence: 0.6,\n maxActiveGoals: 3,\n goalDurationDays: 14,\n reductionTargetPercent: 50,\n};\n\n// ============================================================================\n// GoalManager Class\n// ============================================================================\n\n/**\n * Manages autonomous goal generation and tracking\n */\nexport class GoalManager {\n private projectPath: string;\n private config: GoalGenerationConfig;\n private projectState;\n private insightStore;\n \n constructor(projectPath: string, config: Partial<GoalGenerationConfig> = {}) {\n this.projectPath = projectPath;\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.projectState = getProjectState(projectPath);\n this.insightStore = getInsightStore(projectPath);\n }\n \n /**\n * Analyze incident patterns from memory\n */\n async analyzeIncidentPatterns(): Promise<IncidentPattern[]> {\n const patterns: IncidentPattern[] = [];\n \n try {\n // Get recent issues for analysis\n const stats = await getMemoryStats(this.projectPath);\n const recentIssues = await searchIssues('', {\n workDir: this.projectPath,\n limit: 500,\n includeResolved: true,\n });\n \n if (recentIssues.length < 5) {\n return patterns; // Not enough data for pattern detection\n }\n \n // 1. Analyze file clusters (files with most issues)\n const fileIssueCount = new Map<string, number>();\n for (const { issue } of recentIssues) {\n const file = issue.file;\n fileIssueCount.set(file, (fileIssueCount.get(file) || 0) + 1);\n }\n \n const sortedFiles = [...fileIssueCount.entries()]\n .sort((a, b) => b[1] - a[1]);\n \n // Detect hot directories\n const dirIssueCount = new Map<string, number>();\n for (const [file, count] of sortedFiles) {\n const parts = file.split('/');\n if (parts.length > 1) {\n const dir = parts.slice(0, -1).join('/');\n dirIssueCount.set(dir, (dirIssueCount.get(dir) || 0) + count);\n }\n }\n \n const sortedDirs = [...dirIssueCount.entries()]\n .sort((a, b) => b[1] - a[1]);\n \n if (sortedDirs.length > 0) {\n const topDirEntry = sortedDirs[0];\n if (!topDirEntry) return patterns; // Should not happen but defensive\n const [topDir, topDirCount] = topDirEntry;\n const totalIssues = recentIssues.length;\n const percentage = (topDirCount / totalIssues) * 100;\n \n if (percentage >= 30) {\n patterns.push({\n type: 'file-cluster',\n description: `${basename(topDir)}/ has ${percentage.toFixed(0)}% of issues`,\n metric: `${topDir}_issues`,\n currentValue: topDirCount,\n suggestedTarget: Math.floor(topDirCount * (1 - this.config.reductionTargetPercent / 100)),\n confidence: Math.min(0.9, percentage / 100 + 0.3),\n evidence: [\n `${topDirCount} issues in ${topDir}/`,\n `${percentage.toFixed(0)}% of total issues`,\n `Top files: ${sortedFiles.filter(([f]) => f.startsWith(topDir)).slice(0, 3).map(([f]) => basename(f)).join(', ')}`,\n ],\n category: 'quality',\n });\n }\n }\n \n // 2. Analyze severity trends\n const criticalCount = recentIssues.filter(r => r.issue.severity === 'critical').length;\n const seriousCount = recentIssues.filter(r => r.issue.severity === 'serious').length;\n \n if (criticalCount >= 3) {\n patterns.push({\n type: 'severity-trend',\n description: `${criticalCount} critical issues need attention`,\n metric: 'critical_issues',\n currentValue: criticalCount,\n suggestedTarget: 0,\n confidence: Math.min(0.95, 0.5 + criticalCount * 0.1),\n evidence: [\n `${criticalCount} critical severity issues`,\n `${seriousCount} serious severity issues`,\n 'Critical issues should be zero for production safety',\n ],\n category: 'security',\n });\n }\n \n // 3. Analyze agent concentration (skill-specific issues)\n const agentIssueCount = new Map<string, number>();\n for (const { issue } of recentIssues) {\n agentIssueCount.set(issue.agent, (agentIssueCount.get(issue.agent) || 0) + 1);\n }\n \n const sortedAgents = [...agentIssueCount.entries()]\n .sort((a, b) => b[1] - a[1]);\n \n if (sortedAgents.length > 0) {\n const topAgentEntry = sortedAgents[0];\n if (!topAgentEntry) return patterns; // Should not happen but defensive\n const [topAgent, topAgentCount] = topAgentEntry;\n const percentage = (topAgentCount / recentIssues.length) * 100;\n \n if (percentage >= 40 && topAgentCount >= 5) {\n const category = this.agentToCategory(topAgent);\n patterns.push({\n type: 'agent-concentration',\n description: `${topAgent} skill finds ${percentage.toFixed(0)}% of issues`,\n metric: `${topAgent}_issues`,\n currentValue: topAgentCount,\n suggestedTarget: Math.floor(topAgentCount * 0.5),\n confidence: Math.min(0.85, percentage / 100 + 0.2),\n evidence: [\n `${topAgentCount} issues from ${topAgent}`,\n `${percentage.toFixed(0)}% of all issues`,\n `Suggests focused improvement in ${category} area`,\n ],\n category,\n });\n }\n }\n \n // 4. Detect improvement trends (for streak goals)\n if (stats.improvementTrend === 'improving') {\n patterns.push({\n type: 'time-pattern',\n description: 'Quality is improving - maintain the streak',\n metric: 'clean_scans',\n currentValue: 0,\n suggestedTarget: 5,\n confidence: 0.7,\n evidence: [\n 'Historical trend shows improvement',\n 'Momentum is positive',\n 'Streak goal can maintain motivation',\n ],\n category: 'quality',\n });\n }\n \n } catch (error) {\n console.error('Failed to analyze incident patterns:', error);\n }\n \n return patterns;\n }\n \n /**\n * Convert agent name to category\n */\n private agentToCategory(agent: string): 'security' | 'quality' | 'performance' | 'coverage' | 'general' {\n const categoryMap: Record<string, 'security' | 'quality' | 'performance' | 'coverage' | 'general'> = {\n 'security': 'security',\n 'soc2': 'security',\n 'performance': 'performance',\n 'accessibility': 'quality',\n 'test': 'coverage',\n 'typecheck': 'quality',\n 'bug-finding': 'quality',\n };\n return categoryMap[agent] || 'general';\n }\n \n /**\n * Generate goal opportunities from patterns\n */\n async generateGoalOpportunities(): Promise<GoalOpportunity[]> {\n const patterns = await this.analyzeIncidentPatterns();\n const opportunities: GoalOpportunity[] = [];\n \n // Filter by confidence threshold\n const validPatterns = patterns.filter(p => p.confidence >= this.config.minConfidence);\n \n // Check current active goals\n await this.projectState.load();\n const activeGoals = this.projectState.getActiveGoals();\n \n // Don't suggest too many goals\n const slotsAvailable = this.config.maxActiveGoals - activeGoals.length;\n if (slotsAvailable <= 0) {\n return opportunities;\n }\n \n // Convert patterns to goal opportunities\n for (const pattern of validPatterns.slice(0, slotsAvailable)) {\n const goalType = pattern.type === 'time-pattern' ? 'streak' : 'reduction';\n const deadline = new Date();\n deadline.setDate(deadline.getDate() + this.config.goalDurationDays);\n \n opportunities.push({\n pattern,\n goal: {\n description: this.generateGoalDescription(pattern),\n type: goalType,\n metric: pattern.metric,\n target: pattern.suggestedTarget,\n currentValue: pattern.currentValue,\n startValue: pattern.currentValue,\n status: 'active',\n autoGenerated: true,\n confidence: pattern.confidence,\n deadline: deadline.toISOString(),\n category: pattern.category,\n evidence: pattern.evidence,\n },\n reasoning: this.generateGoalReasoning(pattern),\n });\n }\n \n return opportunities;\n }\n \n /**\n * Generate a human-readable goal description\n */\n private generateGoalDescription(pattern: IncidentPattern): string {\n switch (pattern.type) {\n case 'file-cluster':\n return `Reduce issues in ${pattern.description.split(' ')[0]} by ${this.config.reductionTargetPercent}%`;\n case 'severity-trend':\n return 'Eliminate all critical issues';\n case 'agent-concentration':\n return `Reduce ${pattern.description.split(' ')[0]} issues by 50%`;\n case 'time-pattern':\n return 'Achieve 5 consecutive clean scans';\n default:\n return pattern.description;\n }\n }\n \n /**\n * Generate reasoning for why this goal was suggested\n */\n private generateGoalReasoning(pattern: IncidentPattern): string {\n const evidence = pattern.evidence.join('. ');\n return `Based on analysis: ${evidence}. Confidence: ${(pattern.confidence * 100).toFixed(0)}%`;\n }\n \n /**\n * Auto-generate goals and create them (with auto-generated status)\n * \n * Returns goals that need user acceptance.\n */\n async autoGenerateGoals(): Promise<Goal[]> {\n const opportunities = await this.generateGoalOpportunities();\n const createdGoals: Goal[] = [];\n \n for (const opportunity of opportunities) {\n const goal: Goal = {\n id: `goal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n ...opportunity.goal,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n \n await this.projectState.addGoal(goal);\n createdGoals.push(goal);\n \n // Create insight about the new goal\n if (this.insightStore.canCreateInsight('goal-suggestion')) {\n const insight: Insight = {\n id: `insight-goal-${goal.id}`,\n type: 'suggestion',\n message: `New goal suggested: ${goal.description}`,\n context: opportunity.reasoning,\n suggestedAction: 'Review and accept/reject this goal',\n relatedIssues: [],\n priority: 6,\n timestamp: Date.now(),\n dismissed: false,\n category: 'progress',\n details: {\n examples: opportunity.pattern.evidence,\n },\n };\n await this.insightStore.addInsight(insight);\n await this.insightStore.markInsightCreated('goal-suggestion');\n }\n }\n \n return createdGoals;\n }\n \n /**\n * Update goal progress based on current state\n */\n async updateGoalProgress(): Promise<void> {\n await this.projectState.load();\n const activeGoals = this.projectState.getActiveGoals();\n \n for (const goal of activeGoals) {\n const currentValue = await this.measureGoalMetric(goal);\n \n // Update current value\n await this.projectState.updateGoal(goal.id, { currentValue });\n \n // Only auto-achieve AI-generated goals. User-added goals (e.g. \"Our Chat always collects\n // the right context\") are continuous quality standards—they should never be auto-marked\n // achieved just because a scan found zero violations. The user must manually mark them done.\n // \n // CRITICAL: This check MUST prevent user goals from being auto-achieved.\n if (!goal.autoGenerated) {\n console.debug(`[GoalManager] Skipping auto-achieve for user goal: \"${goal.description.substring(0, 50)}...\" (autoGenerated=${goal.autoGenerated})`);\n continue;\n }\n \n // Double-check: only proceed if this is definitely an AI-generated goal\n if (goal.autoGenerated !== true) {\n console.warn(`[GoalManager] SAFETY: Blocking auto-achieve for ambiguous goal: \"${goal.description.substring(0, 50)}...\" (autoGenerated=${goal.autoGenerated})`);\n continue;\n }\n \n // Check if goal achieved\n if (this.isGoalAchieved(goal, currentValue)) {\n console.debug(`[GoalManager] Auto-achieving AI goal: \"${goal.description.substring(0, 50)}...\"`);\n await this.projectState.updateGoal(goal.id, {\n status: 'achieved',\n achievedAt: new Date().toISOString(),\n achievedBy: 'agent',\n currentValue,\n });\n \n // Resolve any nudges associated with this goal\n try {\n const { getStorage } = await import('../storage/tiered-storage.js');\n const storage = getStorage(this.projectPath);\n await storage.initialize();\n const resolved = await storage.resolveNudgesForGoal(goal.description);\n if (resolved > 0) {\n console.debug(`[GoalManager] Auto-resolved ${resolved} nudge(s) for achieved goal`);\n }\n } catch (e) {\n console.debug('[GoalManager] Failed to resolve nudges for achieved goal:', e);\n }\n \n // Celebrate!\n await this.celebrateGoalAchievement(goal);\n }\n \n // Check if goal failed (past deadline and not achieved)\n if (goal.deadline) {\n const deadline = new Date(goal.deadline);\n if (Date.now() > deadline.getTime() && !this.isGoalAchieved(goal, currentValue)) {\n await this.projectState.updateGoal(goal.id, {\n status: 'failed',\n currentValue,\n });\n }\n }\n }\n }\n \n /**\n * Measure the current value of a goal's metric\n * \n * Supports both structured metrics and semantic/natural language goals.\n * For custom goals, counts goal-violation issues that match this goal's description.\n */\n private async measureGoalMetric(goal: Goal): Promise<number> {\n try {\n const issues = await searchIssues('', {\n workDir: this.projectPath,\n limit: 1000,\n includeResolved: false,\n });\n \n // First, check for goal-violation issues specific to THIS goal\n // These are stored by watch.ts when violations are detected\n const goalViolations = issues.filter(r => \n r.issue.agent === 'goal-violation' &&\n r.issue.issue.includes(`Goal \"${goal.description}\"`)\n );\n \n // If we have goal-specific violations, use that count\n // This takes priority over semantic matching since it's explicit\n if (goalViolations.length > 0) {\n return goalViolations.length;\n }\n \n // Structured metrics (auto-generated goals)\n if (goal.metric.endsWith('_issues')) {\n const prefix = goal.metric.replace('_issues', '');\n \n // Check if it's a directory metric\n if (prefix.includes('/')) {\n return issues.filter(r => r.issue.file.startsWith(prefix)).length;\n }\n \n // Check if it's an agent metric\n return issues.filter(r => r.issue.agent === prefix).length;\n }\n \n if (goal.metric === 'critical_issues') {\n return issues.filter(r => r.issue.severity === 'critical').length;\n }\n \n // Semantic goal tracking - match description to issue types\n const desc = goal.description.toLowerCase();\n \n // Path-aware matching for directory/module-specific goals\n // Matches patterns like \"in the auth module\", \"in src/\", \"in components folder\"\n const dirMatch = goal.description.match(/in\\s+(?:the\\s+)?(\\S+?)(?:\\s+(?:module|folder|directory|dir))?(?:\\s|$)/i);\n if (dirMatch && dirMatch[1]) {\n const dirName = dirMatch[1].toLowerCase().replace(/[/\\\\]$/, ''); // Normalize trailing slashes\n const matchingIssues = issues.filter(r => {\n const filePath = r.issue.file.toLowerCase();\n // Match directory name anywhere in path (e.g., \"auth\" matches \"src/auth/login.ts\")\n return filePath.includes(`/${dirName}/`) || \n filePath.includes(`\\\\${dirName}\\\\`) ||\n filePath.startsWith(`${dirName}/`) ||\n filePath.startsWith(`${dirName}\\\\`);\n });\n if (matchingIssues.length > 0 || desc.includes(dirName)) {\n return matchingIssues.length;\n }\n }\n \n // Dead code / unused code goals\n if (desc.includes('dead code') || desc.includes('unused') || desc.includes('remove unused')) {\n const deadCodeIssues = issues.filter(r => {\n const msg = r.issue.issue.toLowerCase();\n return msg.includes('unused') || msg.includes('dead code') || \n msg.includes('never used') || msg.includes('unreachable') ||\n msg.includes('no-unused') || msg.includes('defined but never');\n });\n return deadCodeIssues.length;\n }\n \n // Security goals\n if (desc.includes('security') || desc.includes('vulnerab') || desc.includes('fix security')) {\n const securityIssues = issues.filter(r => \n r.issue.agent === 'security' ||\n r.issue.severity === 'critical'\n );\n return securityIssues.length;\n }\n \n // Type safety goals\n if (desc.includes('type') || desc.includes('typescript') || desc.includes('any type')) {\n const typeIssues = issues.filter(r => \n r.issue.agent === 'typecheck' ||\n r.issue.issue.toLowerCase().includes('type') ||\n r.issue.issue.toLowerCase().includes('any')\n );\n return typeIssues.length;\n }\n \n // Test coverage goals\n if (desc.includes('test') || desc.includes('coverage')) {\n const testIssues = issues.filter(r => \n r.issue.agent === 'test' ||\n r.issue.issue.toLowerCase().includes('test') ||\n r.issue.issue.toLowerCase().includes('coverage')\n );\n return testIssues.length;\n }\n \n // Performance goals\n if (desc.includes('performance') || desc.includes('slow') || desc.includes('optimize')) {\n const perfIssues = issues.filter(r => \n r.issue.agent === 'performance' ||\n r.issue.issue.toLowerCase().includes('performance') ||\n r.issue.issue.toLowerCase().includes('slow')\n );\n return perfIssues.length;\n }\n \n // Accessibility goals\n if (desc.includes('accessibility') || desc.includes('a11y') || desc.includes('accessible')) {\n const a11yIssues = issues.filter(r => \n r.issue.agent === 'accessibility' ||\n r.issue.issue.toLowerCase().includes('accessibility')\n );\n return a11yIssues.length;\n }\n \n // Bug-related goals\n if (desc.includes('bug') || desc.includes('fix') || desc.includes('error')) {\n const bugIssues = issues.filter(r => \n r.issue.agent === 'bug-finding' ||\n r.issue.severity === 'critical' ||\n r.issue.severity === 'serious'\n );\n return bugIssues.length;\n }\n \n // Quality goals (general)\n if (desc.includes('quality') || desc.includes('clean') || desc.includes('improve')) {\n // Count all issues as baseline for quality\n return issues.length;\n }\n \n // Default: total issues\n return issues.length;\n } catch {\n return goal.currentValue; // Return existing value on error\n }\n }\n \n /**\n * Check if a goal has been achieved\n */\n private isGoalAchieved(goal: Goal, currentValue: number): boolean {\n switch (goal.type) {\n case 'reduction':\n return currentValue <= goal.target;\n case 'score':\n return currentValue >= goal.target;\n case 'streak':\n return currentValue >= goal.target;\n default:\n return currentValue <= goal.target;\n }\n }\n \n /**\n * Create a celebration insight for goal achievement\n */\n private async celebrateGoalAchievement(goal: Goal): Promise<void> {\n // Find resolved issues that match this goal's metric\n const resolvedDetails = await this.getResolvedIssuesForGoal(goal);\n \n // Validate required fields\n if (goal.startValue === undefined || goal.startValue === null) {\n throw new Error(`Goal ${goal.id} missing startValue`);\n }\n if (goal.currentValue === undefined || goal.currentValue === null) {\n throw new Error(`Goal ${goal.id} missing currentValue`);\n }\n if (goal.target === undefined || goal.target === null) {\n throw new Error(`Goal ${goal.id} missing target`);\n }\n \n // Validate resolvedDetails structure\n for (let i = 0; i < resolvedDetails.length; i++) {\n const issue = resolvedDetails[i];\n if (!issue) {\n throw new Error(`Resolved issue at index ${i} is null/undefined`);\n }\n if (!issue.file) {\n throw new Error(`Resolved issue at index ${i} missing file field`);\n }\n if (!issue.issue) {\n throw new Error(`Resolved issue at index ${i} missing issue description`);\n }\n if (!issue.agent) {\n throw new Error(`Resolved issue at index ${i} missing agent field`);\n }\n }\n \n const insight: Insight = {\n id: `insight-achieved-${goal.id}`,\n type: 'celebration',\n message: `Goal achieved: ${goal.description}!`,\n context: `Started at ${goal.startValue}, now at ${goal.currentValue}. Target was ${goal.target}.`,\n relatedIssues: [],\n priority: 8,\n timestamp: Date.now(),\n dismissed: false,\n category: 'progress',\n details: {\n resolvedCount: resolvedDetails.length,\n resolvedIssues: resolvedDetails.slice(0, 20).map(issue => ({\n file: issue.file,\n line: issue.line,\n issue: issue.issue,\n agent: issue.agent,\n resolvedAt: issue.resolvedAt,\n })),\n summary: resolvedDetails.length > 0 \n ? `Resolved ${resolvedDetails.length} issue${resolvedDetails.length > 1 ? 's' : ''} matching this goal`\n : 'Progress tracked via metric reduction',\n },\n };\n \n // Validate insight structure before saving\n if (!insight.details) {\n throw new Error('Failed to create details object for goal achievement insight');\n }\n if (insight.details.resolvedCount === undefined) {\n throw new Error('resolvedCount is undefined in goal achievement insight');\n }\n if (insight.details.resolvedCount > 0 && (!insight.details.resolvedIssues || insight.details.resolvedIssues.length === 0)) {\n throw new Error(`resolvedCount is ${insight.details.resolvedCount} but resolvedIssues array is empty`);\n }\n if (insight.details.resolvedCount !== insight.details.resolvedIssues?.length) {\n throw new Error(`resolvedCount (${insight.details.resolvedCount}) doesn't match resolvedIssues length (${insight.details.resolvedIssues?.length})`);\n }\n \n await this.insightStore.addInsight(insight);\n }\n\n /**\n * Get resolved issues that match a goal's metric pattern\n */\n private async getResolvedIssuesForGoal(goal: Goal): Promise<Array<{ file: string; line: number | undefined; issue: string; agent: string; resolvedAt: string | undefined }>> {\n try {\n // Get all resolved issues\n const allResolved = await searchIssues('', {\n workDir: this.projectPath,\n limit: 1000,\n includeResolved: true,\n });\n \n // Filter to only resolved issues\n const resolved = allResolved\n .map(r => r.issue)\n .filter(issue => issue.resolved === true);\n \n // Filter by goal's metric pattern (same logic as measureGoalMetric)\n const desc = goal.description.toLowerCase();\n const metric = goal.metric.toLowerCase();\n \n let matchingResolved = resolved;\n \n // Match by metric pattern\n if (metric.endsWith('_issues')) {\n const prefix = metric.replace('_issues', '');\n if (prefix.includes('/')) {\n matchingResolved = resolved.filter(i => i.file.startsWith(prefix));\n } else {\n matchingResolved = resolved.filter(i => i.agent === prefix);\n }\n } else if (metric === 'critical_issues') {\n matchingResolved = resolved.filter(i => i.severity === 'critical');\n } else {\n // Semantic matching (same as measureGoalMetric)\n if (desc.includes('dead code') || desc.includes('unused') || desc.includes('remove unused')) {\n matchingResolved = resolved.filter(i => {\n const msg = i.issue.toLowerCase();\n return msg.includes('unused') || msg.includes('dead code') || \n msg.includes('never used') || msg.includes('unreachable') ||\n msg.includes('no-unused') || msg.includes('defined but never');\n });\n } else if (desc.includes('security') || desc.includes('vulnerab') || desc.includes('fix security')) {\n matchingResolved = resolved.filter(i => \n i.agent === 'security' || i.severity === 'critical'\n );\n } else if (desc.includes('type') || desc.includes('typescript') || desc.includes('any type')) {\n matchingResolved = resolved.filter(i => \n i.agent === 'typecheck' ||\n i.issue.toLowerCase().includes('type') ||\n i.issue.toLowerCase().includes('any')\n );\n } else if (desc.includes('test') || desc.includes('coverage')) {\n matchingResolved = resolved.filter(i => \n i.agent === 'test' ||\n i.issue.toLowerCase().includes('test') ||\n i.issue.toLowerCase().includes('coverage')\n );\n } else if (desc.includes('performance') || desc.includes('slow') || desc.includes('optimize')) {\n matchingResolved = resolved.filter(i => \n i.agent === 'performance' ||\n i.issue.toLowerCase().includes('performance') ||\n i.issue.toLowerCase().includes('slow')\n );\n } else if (desc.includes('accessibility') || desc.includes('a11y') || desc.includes('accessible')) {\n matchingResolved = resolved.filter(i => \n i.agent === 'accessibility' ||\n i.issue.toLowerCase().includes('accessibility')\n );\n } else if (desc.includes('bug') || desc.includes('fix') || desc.includes('error')) {\n matchingResolved = resolved.filter(i => \n i.agent === 'bug-finding' ||\n i.severity === 'critical' ||\n i.severity === 'serious'\n );\n }\n }\n \n // Filter by resolvedAt timestamp (only include issues resolved during goal's lifetime)\n const goalCreatedAt = new Date(goal.createdAt).getTime();\n const goalAchievedAt = goal.achievedAt ? new Date(goal.achievedAt).getTime() : Date.now();\n \n return matchingResolved\n .filter(issue => {\n if (!issue.resolvedAt) return false;\n const resolvedAt = new Date(issue.resolvedAt).getTime();\n return resolvedAt >= goalCreatedAt && resolvedAt <= goalAchievedAt;\n })\n .sort((a, b) => {\n // Sort by resolvedAt, most recent first\n const aTime = a.resolvedAt ? new Date(a.resolvedAt).getTime() : 0;\n const bTime = b.resolvedAt ? new Date(b.resolvedAt).getTime() : 0;\n return bTime - aTime;\n });\n } catch {\n return [];\n }\n }\n \n /**\n * Accept an auto-generated goal\n */\n async acceptGoal(goalId: string): Promise<boolean> {\n return this.projectState.respondToGoal(goalId, true);\n }\n \n /**\n * Reject an auto-generated goal\n */\n async rejectGoal(goalId: string): Promise<boolean> {\n return this.projectState.respondToGoal(goalId, false);\n }\n \n /**\n * Get pending auto-generated goals (awaiting acceptance)\n */\n getPendingGoals(): Goal[] {\n return this.projectState.getAutoGeneratedGoals()\n .filter(g => g.status === 'active');\n }\n \n /**\n * Get goal progress summary\n */\n getGoalProgressSummary(): {\n active: number;\n achieved: number;\n failed: number;\n pending: number;\n } {\n const goals = this.projectState.getAllGoals();\n return {\n active: goals.filter(g => g.status === 'active').length,\n achieved: goals.filter(g => g.status === 'achieved').length,\n failed: goals.filter(g => g.status === 'failed').length,\n pending: goals.filter(g => g.autoGenerated && g.status === 'active').length,\n };\n }\n}\n\n// ============================================================================\n// Adaptive Scan Frequency\n// ============================================================================\n\n/**\n * Calculate optimal scan frequency based on current risk level\n */\nexport async function calculateAdaptiveScanFrequency(projectPath: string): Promise<{\n frequencyMs: number;\n reason: string;\n}> {\n const projectState = getProjectState(projectPath);\n await projectState.load();\n \n try {\n const stats = await getMemoryStats(projectPath);\n const issues = await searchIssues('', {\n workDir: projectPath,\n limit: 100,\n includeResolved: false,\n });\n \n const criticalCount = issues.filter(r => r.issue.severity === 'critical').length;\n const seriousCount = issues.filter(r => r.issue.severity === 'serious').length;\n \n // High risk: scan every minute\n if (criticalCount >= 3) {\n return {\n frequencyMs: 60000,\n reason: `${criticalCount} critical issues detected - scanning frequently`,\n };\n }\n \n // Medium-high risk: scan every 2 minutes\n if (criticalCount > 0 || seriousCount >= 5) {\n return {\n frequencyMs: 120000,\n reason: `Critical or many serious issues - elevated scan frequency`,\n };\n }\n \n // Medium risk: scan every 3 minutes\n if (seriousCount > 0) {\n return {\n frequencyMs: 180000,\n reason: `${seriousCount} serious issues - moderate scan frequency`,\n };\n }\n \n // Low risk: scan every 5 minutes (default)\n if (stats.totalIssues > 10) {\n return {\n frequencyMs: 300000,\n reason: 'Some issues present - standard scan frequency',\n };\n }\n \n // Very low risk: scan every 10 minutes\n return {\n frequencyMs: 600000,\n reason: 'Code looks good - relaxed scan frequency',\n };\n \n } catch {\n // Default on error\n return {\n frequencyMs: 300000,\n reason: 'Default scan frequency (5 min)',\n };\n }\n}\n\n/**\n * Apply adaptive scan frequency\n */\nexport async function adaptScanFrequency(projectPath: string): Promise<number> {\n const projectState = getProjectState(projectPath);\n const { frequencyMs } = await calculateAdaptiveScanFrequency(projectPath);\n \n await projectState.setScanFrequency(frequencyMs);\n \n return frequencyMs;\n}\n\n// ============================================================================\n// Singleton Management\n// ============================================================================\n\nconst goalManagers: Map<string, GoalManager> = new Map();\n\n/**\n * Get the GoalManager for a project (singleton per project)\n */\nexport function getGoalManager(projectPath: string): GoalManager {\n let manager = goalManagers.get(projectPath);\n if (!manager) {\n manager = new GoalManager(projectPath);\n goalManagers.set(projectPath, manager);\n }\n return manager;\n}\n\n/**\n * Clear all GoalManager instances (for testing)\n */\nexport function clearGoalManagers(): void {\n goalManagers.clear();\n}\n"],"mappings":";;;;;;;;;;;;AAeA,SAAS,gBAAgB;AAuCzB,IAAM,iBAAuC;AAAA,EAC3C,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,wBAAwB;AAC1B;AASO,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,aAAqB,SAAwC,CAAC,GAAG;AAC3E,SAAK,cAAc;AACnB,SAAK,SAAS,EAAE,GAAG,gBAAgB,GAAG,OAAO;AAC7C,SAAK,eAAe,gBAAgB,WAAW;AAC/C,SAAK,eAAe,gBAAgB,WAAW;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,0BAAsD;AAC1D,UAAM,WAA8B,CAAC;AAErC,QAAI;AAEF,YAAM,QAAQ,MAAM,eAAe,KAAK,WAAW;AACnD,YAAM,eAAe,MAAM,aAAa,IAAI;AAAA,QAC1C,SAAS,KAAK;AAAA,QACd,OAAO;AAAA,QACP,iBAAiB;AAAA,MACnB,CAAC;AAED,UAAI,aAAa,SAAS,GAAG;AAC3B,eAAO;AAAA,MACT;AAGA,YAAM,iBAAiB,oBAAI,IAAoB;AAC/C,iBAAW,EAAE,MAAM,KAAK,cAAc;AACpC,cAAM,OAAO,MAAM;AACnB,uBAAe,IAAI,OAAO,eAAe,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,MAC9D;AAEA,YAAM,cAAc,CAAC,GAAG,eAAe,QAAQ,CAAC,EAC7C,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAG7B,YAAM,gBAAgB,oBAAI,IAAoB;AAC9C,iBAAW,CAAC,MAAM,KAAK,KAAK,aAAa;AACvC,cAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,YAAI,MAAM,SAAS,GAAG;AACpB,gBAAM,MAAM,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AACvC,wBAAc,IAAI,MAAM,cAAc,IAAI,GAAG,KAAK,KAAK,KAAK;AAAA,QAC9D;AAAA,MACF;AAEA,YAAM,aAAa,CAAC,GAAG,cAAc,QAAQ,CAAC,EAC3C,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAE7B,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,cAAc,WAAW,CAAC;AAChC,YAAI,CAAC,YAAa,QAAO;AACzB,cAAM,CAAC,QAAQ,WAAW,IAAI;AAC9B,cAAM,cAAc,aAAa;AACjC,cAAM,aAAc,cAAc,cAAe;AAEjD,YAAI,cAAc,IAAI;AACpB,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,aAAa,GAAG,SAAS,MAAM,CAAC,SAAS,WAAW,QAAQ,CAAC,CAAC;AAAA,YAC9D,QAAQ,GAAG,MAAM;AAAA,YACjB,cAAc;AAAA,YACd,iBAAiB,KAAK,MAAM,eAAe,IAAI,KAAK,OAAO,yBAAyB,IAAI;AAAA,YACxF,YAAY,KAAK,IAAI,KAAK,aAAa,MAAM,GAAG;AAAA,YAChD,UAAU;AAAA,cACR,GAAG,WAAW,cAAc,MAAM;AAAA,cAClC,GAAG,WAAW,QAAQ,CAAC,CAAC;AAAA,cACxB,cAAc,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,YAClH;AAAA,YACA,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAGA,YAAM,gBAAgB,aAAa,OAAO,OAAK,EAAE,MAAM,aAAa,UAAU,EAAE;AAChF,YAAM,eAAe,aAAa,OAAO,OAAK,EAAE,MAAM,aAAa,SAAS,EAAE;AAE9E,UAAI,iBAAiB,GAAG;AACtB,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,aAAa,GAAG,aAAa;AAAA,UAC7B,QAAQ;AAAA,UACR,cAAc;AAAA,UACd,iBAAiB;AAAA,UACjB,YAAY,KAAK,IAAI,MAAM,MAAM,gBAAgB,GAAG;AAAA,UACpD,UAAU;AAAA,YACR,GAAG,aAAa;AAAA,YAChB,GAAG,YAAY;AAAA,YACf;AAAA,UACF;AAAA,UACA,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAGA,YAAM,kBAAkB,oBAAI,IAAoB;AAChD,iBAAW,EAAE,MAAM,KAAK,cAAc;AACpC,wBAAgB,IAAI,MAAM,QAAQ,gBAAgB,IAAI,MAAM,KAAK,KAAK,KAAK,CAAC;AAAA,MAC9E;AAEA,YAAM,eAAe,CAAC,GAAG,gBAAgB,QAAQ,CAAC,EAC/C,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAE7B,UAAI,aAAa,SAAS,GAAG;AAC3B,cAAM,gBAAgB,aAAa,CAAC;AACpC,YAAI,CAAC,cAAe,QAAO;AAC3B,cAAM,CAAC,UAAU,aAAa,IAAI;AAClC,cAAM,aAAc,gBAAgB,aAAa,SAAU;AAE3D,YAAI,cAAc,MAAM,iBAAiB,GAAG;AAC1C,gBAAM,WAAW,KAAK,gBAAgB,QAAQ;AAC9C,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,aAAa,GAAG,QAAQ,gBAAgB,WAAW,QAAQ,CAAC,CAAC;AAAA,YAC7D,QAAQ,GAAG,QAAQ;AAAA,YACnB,cAAc;AAAA,YACd,iBAAiB,KAAK,MAAM,gBAAgB,GAAG;AAAA,YAC/C,YAAY,KAAK,IAAI,MAAM,aAAa,MAAM,GAAG;AAAA,YACjD,UAAU;AAAA,cACR,GAAG,aAAa,gBAAgB,QAAQ;AAAA,cACxC,GAAG,WAAW,QAAQ,CAAC,CAAC;AAAA,cACxB,mCAAmC,QAAQ;AAAA,YAC7C;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,MAAM,qBAAqB,aAAa;AAC1C,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,aAAa;AAAA,UACb,QAAQ;AAAA,UACR,cAAc;AAAA,UACd,iBAAiB;AAAA,UACjB,YAAY;AAAA,UACZ,UAAU;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IAEF,SAAS,OAAO;AACd,cAAQ,MAAM,wCAAwC,KAAK;AAAA,IAC7D;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,OAAgF;AACtG,UAAM,cAA+F;AAAA,MACnG,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,eAAe;AAAA,IACjB;AACA,WAAO,YAAY,KAAK,KAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,4BAAwD;AAC5D,UAAM,WAAW,MAAM,KAAK,wBAAwB;AACpD,UAAM,gBAAmC,CAAC;AAG1C,UAAM,gBAAgB,SAAS,OAAO,OAAK,EAAE,cAAc,KAAK,OAAO,aAAa;AAGpF,UAAM,KAAK,aAAa,KAAK;AAC7B,UAAM,cAAc,KAAK,aAAa,eAAe;AAGrD,UAAM,iBAAiB,KAAK,OAAO,iBAAiB,YAAY;AAChE,QAAI,kBAAkB,GAAG;AACvB,aAAO;AAAA,IACT;AAGA,eAAW,WAAW,cAAc,MAAM,GAAG,cAAc,GAAG;AAC5D,YAAM,WAAW,QAAQ,SAAS,iBAAiB,WAAW;AAC9D,YAAM,WAAW,oBAAI,KAAK;AAC1B,eAAS,QAAQ,SAAS,QAAQ,IAAI,KAAK,OAAO,gBAAgB;AAElE,oBAAc,KAAK;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,UACJ,aAAa,KAAK,wBAAwB,OAAO;AAAA,UACjD,MAAM;AAAA,UACN,QAAQ,QAAQ;AAAA,UAChB,QAAQ,QAAQ;AAAA,UAChB,cAAc,QAAQ;AAAA,UACtB,YAAY,QAAQ;AAAA,UACpB,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,YAAY,QAAQ;AAAA,UACpB,UAAU,SAAS,YAAY;AAAA,UAC/B,UAAU,QAAQ;AAAA,UAClB,UAAU,QAAQ;AAAA,QACpB;AAAA,QACA,WAAW,KAAK,sBAAsB,OAAO;AAAA,MAC/C,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,wBAAwB,SAAkC;AAChE,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,eAAO,oBAAoB,QAAQ,YAAY,MAAM,GAAG,EAAE,CAAC,CAAC,OAAO,KAAK,OAAO,sBAAsB;AAAA,MACvG,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO,UAAU,QAAQ,YAAY,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,MACpD,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO,QAAQ;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,SAAkC;AAC9D,UAAM,WAAW,QAAQ,SAAS,KAAK,IAAI;AAC3C,WAAO,sBAAsB,QAAQ,kBAAkB,QAAQ,aAAa,KAAK,QAAQ,CAAC,CAAC;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBAAqC;AACzC,UAAM,gBAAgB,MAAM,KAAK,0BAA0B;AAC3D,UAAM,eAAuB,CAAC;AAE9B,eAAW,eAAe,eAAe;AACvC,YAAM,OAAa;AAAA,QACjB,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,QAChE,GAAG,YAAY;AAAA,QACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAEA,YAAM,KAAK,aAAa,QAAQ,IAAI;AACpC,mBAAa,KAAK,IAAI;AAGtB,UAAI,KAAK,aAAa,iBAAiB,iBAAiB,GAAG;AACzD,cAAM,UAAmB;AAAA,UACvB,IAAI,gBAAgB,KAAK,EAAE;AAAA,UAC3B,MAAM;AAAA,UACN,SAAS,uBAAuB,KAAK,WAAW;AAAA,UAChD,SAAS,YAAY;AAAA,UACrB,iBAAiB;AAAA,UACjB,eAAe,CAAC;AAAA,UAChB,UAAU;AAAA,UACV,WAAW,KAAK,IAAI;AAAA,UACpB,WAAW;AAAA,UACX,UAAU;AAAA,UACV,SAAS;AAAA,YACP,UAAU,YAAY,QAAQ;AAAA,UAChC;AAAA,QACF;AACA,cAAM,KAAK,aAAa,WAAW,OAAO;AAC1C,cAAM,KAAK,aAAa,mBAAmB,iBAAiB;AAAA,MAC9D;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBAAoC;AACxC,UAAM,KAAK,aAAa,KAAK;AAC7B,UAAM,cAAc,KAAK,aAAa,eAAe;AAErD,eAAW,QAAQ,aAAa;AAC9B,YAAM,eAAe,MAAM,KAAK,kBAAkB,IAAI;AAGtD,YAAM,KAAK,aAAa,WAAW,KAAK,IAAI,EAAE,aAAa,CAAC;AAO5D,UAAI,CAAC,KAAK,eAAe;AACvB,gBAAQ,MAAM,uDAAuD,KAAK,YAAY,UAAU,GAAG,EAAE,CAAC,uBAAuB,KAAK,aAAa,GAAG;AAClJ;AAAA,MACF;AAGA,UAAI,KAAK,kBAAkB,MAAM;AAC/B,gBAAQ,KAAK,oEAAoE,KAAK,YAAY,UAAU,GAAG,EAAE,CAAC,uBAAuB,KAAK,aAAa,GAAG;AAC9J;AAAA,MACF;AAGA,UAAI,KAAK,eAAe,MAAM,YAAY,GAAG;AAC3C,gBAAQ,MAAM,0CAA0C,KAAK,YAAY,UAAU,GAAG,EAAE,CAAC,MAAM;AAC/F,cAAM,KAAK,aAAa,WAAW,KAAK,IAAI;AAAA,UAC1C,QAAQ;AAAA,UACR,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,UACnC,YAAY;AAAA,UACZ;AAAA,QACF,CAAC;AAGD,YAAI;AACF,gBAAM,EAAE,WAAW,IAAI,MAAM,OAAO,8BAA8B;AAClE,gBAAM,UAAU,WAAW,KAAK,WAAW;AAC3C,gBAAM,QAAQ,WAAW;AACzB,gBAAM,WAAW,MAAM,QAAQ,qBAAqB,KAAK,WAAW;AACpE,cAAI,WAAW,GAAG;AAChB,oBAAQ,MAAM,+BAA+B,QAAQ,6BAA6B;AAAA,UACpF;AAAA,QACF,SAAS,GAAG;AACV,kBAAQ,MAAM,6DAA6D,CAAC;AAAA,QAC9E;AAGA,cAAM,KAAK,yBAAyB,IAAI;AAAA,MAC1C;AAGA,UAAI,KAAK,UAAU;AACjB,cAAM,WAAW,IAAI,KAAK,KAAK,QAAQ;AACvC,YAAI,KAAK,IAAI,IAAI,SAAS,QAAQ,KAAK,CAAC,KAAK,eAAe,MAAM,YAAY,GAAG;AAC/E,gBAAM,KAAK,aAAa,WAAW,KAAK,IAAI;AAAA,YAC1C,QAAQ;AAAA,YACR;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,kBAAkB,MAA6B;AAC3D,QAAI;AACF,YAAM,SAAS,MAAM,aAAa,IAAI;AAAA,QACpC,SAAS,KAAK;AAAA,QACd,OAAO;AAAA,QACP,iBAAiB;AAAA,MACnB,CAAC;AAID,YAAM,iBAAiB,OAAO;AAAA,QAAO,OACnC,EAAE,MAAM,UAAU,oBAClB,EAAE,MAAM,MAAM,SAAS,SAAS,KAAK,WAAW,GAAG;AAAA,MACrD;AAIA,UAAI,eAAe,SAAS,GAAG;AAC7B,eAAO,eAAe;AAAA,MACxB;AAGA,UAAI,KAAK,OAAO,SAAS,SAAS,GAAG;AACnC,cAAM,SAAS,KAAK,OAAO,QAAQ,WAAW,EAAE;AAGhD,YAAI,OAAO,SAAS,GAAG,GAAG;AACxB,iBAAO,OAAO,OAAO,OAAK,EAAE,MAAM,KAAK,WAAW,MAAM,CAAC,EAAE;AAAA,QAC7D;AAGA,eAAO,OAAO,OAAO,OAAK,EAAE,MAAM,UAAU,MAAM,EAAE;AAAA,MACtD;AAEA,UAAI,KAAK,WAAW,mBAAmB;AACrC,eAAO,OAAO,OAAO,OAAK,EAAE,MAAM,aAAa,UAAU,EAAE;AAAA,MAC7D;AAGA,YAAM,OAAO,KAAK,YAAY,YAAY;AAI1C,YAAM,WAAW,KAAK,YAAY,MAAM,wEAAwE;AAChH,UAAI,YAAY,SAAS,CAAC,GAAG;AAC3B,cAAM,UAAU,SAAS,CAAC,EAAE,YAAY,EAAE,QAAQ,UAAU,EAAE;AAC9D,cAAM,iBAAiB,OAAO,OAAO,OAAK;AACxC,gBAAM,WAAW,EAAE,MAAM,KAAK,YAAY;AAE1C,iBAAO,SAAS,SAAS,IAAI,OAAO,GAAG,KAChC,SAAS,SAAS,KAAK,OAAO,IAAI,KAClC,SAAS,WAAW,GAAG,OAAO,GAAG,KACjC,SAAS,WAAW,GAAG,OAAO,IAAI;AAAA,QAC3C,CAAC;AACD,YAAI,eAAe,SAAS,KAAK,KAAK,SAAS,OAAO,GAAG;AACvD,iBAAO,eAAe;AAAA,QACxB;AAAA,MACF;AAGA,UAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,eAAe,GAAG;AAC3F,cAAM,iBAAiB,OAAO,OAAO,OAAK;AACxC,gBAAM,MAAM,EAAE,MAAM,MAAM,YAAY;AACtC,iBAAO,IAAI,SAAS,QAAQ,KAAK,IAAI,SAAS,WAAW,KAClD,IAAI,SAAS,YAAY,KAAK,IAAI,SAAS,aAAa,KACxD,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,mBAAmB;AAAA,QACtE,CAAC;AACD,eAAO,eAAe;AAAA,MACxB;AAGA,UAAI,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,cAAc,GAAG;AAC3F,cAAM,iBAAiB,OAAO;AAAA,UAAO,OACnC,EAAE,MAAM,UAAU,cAClB,EAAE,MAAM,aAAa;AAAA,QACvB;AACA,eAAO,eAAe;AAAA,MACxB;AAGA,UAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,UAAU,GAAG;AACrF,cAAM,aAAa,OAAO;AAAA,UAAO,OAC/B,EAAE,MAAM,UAAU,eAClB,EAAE,MAAM,MAAM,YAAY,EAAE,SAAS,MAAM,KAC3C,EAAE,MAAM,MAAM,YAAY,EAAE,SAAS,KAAK;AAAA,QAC5C;AACA,eAAO,WAAW;AAAA,MACpB;AAGA,UAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,UAAU,GAAG;AACtD,cAAM,aAAa,OAAO;AAAA,UAAO,OAC/B,EAAE,MAAM,UAAU,UAClB,EAAE,MAAM,MAAM,YAAY,EAAE,SAAS,MAAM,KAC3C,EAAE,MAAM,MAAM,YAAY,EAAE,SAAS,UAAU;AAAA,QACjD;AACA,eAAO,WAAW;AAAA,MACpB;AAGA,UAAI,KAAK,SAAS,aAAa,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,UAAU,GAAG;AACtF,cAAM,aAAa,OAAO;AAAA,UAAO,OAC/B,EAAE,MAAM,UAAU,iBAClB,EAAE,MAAM,MAAM,YAAY,EAAE,SAAS,aAAa,KAClD,EAAE,MAAM,MAAM,YAAY,EAAE,SAAS,MAAM;AAAA,QAC7C;AACA,eAAO,WAAW;AAAA,MACpB;AAGA,UAAI,KAAK,SAAS,eAAe,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,YAAY,GAAG;AAC1F,cAAM,aAAa,OAAO;AAAA,UAAO,OAC/B,EAAE,MAAM,UAAU,mBAClB,EAAE,MAAM,MAAM,YAAY,EAAE,SAAS,eAAe;AAAA,QACtD;AACA,eAAO,WAAW;AAAA,MACpB;AAGA,UAAI,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,OAAO,GAAG;AAC1E,cAAM,YAAY,OAAO;AAAA,UAAO,OAC9B,EAAE,MAAM,UAAU,iBAClB,EAAE,MAAM,aAAa,cACrB,EAAE,MAAM,aAAa;AAAA,QACvB;AACA,eAAO,UAAU;AAAA,MACnB;AAGA,UAAI,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,SAAS,GAAG;AAElF,eAAO,OAAO;AAAA,MAChB;AAGA,aAAO,OAAO;AAAA,IAChB,QAAQ;AACN,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,MAAY,cAA+B;AAChE,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,eAAO,gBAAgB,KAAK;AAAA,MAC9B,KAAK;AACH,eAAO,gBAAgB,KAAK;AAAA,MAC9B,KAAK;AACH,eAAO,gBAAgB,KAAK;AAAA,MAC9B;AACE,eAAO,gBAAgB,KAAK;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,yBAAyB,MAA2B;AAEhE,UAAM,kBAAkB,MAAM,KAAK,yBAAyB,IAAI;AAGhE,QAAI,KAAK,eAAe,UAAa,KAAK,eAAe,MAAM;AAC7D,YAAM,IAAI,MAAM,QAAQ,KAAK,EAAE,qBAAqB;AAAA,IACtD;AACA,QAAI,KAAK,iBAAiB,UAAa,KAAK,iBAAiB,MAAM;AACjE,YAAM,IAAI,MAAM,QAAQ,KAAK,EAAE,uBAAuB;AAAA,IACxD;AACA,QAAI,KAAK,WAAW,UAAa,KAAK,WAAW,MAAM;AACrD,YAAM,IAAI,MAAM,QAAQ,KAAK,EAAE,iBAAiB;AAAA,IAClD;AAGA,aAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;AAC/C,YAAM,QAAQ,gBAAgB,CAAC;AAC/B,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,2BAA2B,CAAC,oBAAoB;AAAA,MAClE;AACA,UAAI,CAAC,MAAM,MAAM;AACf,cAAM,IAAI,MAAM,2BAA2B,CAAC,qBAAqB;AAAA,MACnE;AACA,UAAI,CAAC,MAAM,OAAO;AAChB,cAAM,IAAI,MAAM,2BAA2B,CAAC,4BAA4B;AAAA,MAC1E;AACA,UAAI,CAAC,MAAM,OAAO;AAChB,cAAM,IAAI,MAAM,2BAA2B,CAAC,sBAAsB;AAAA,MACpE;AAAA,IACF;AAEA,UAAM,UAAmB;AAAA,MACvB,IAAI,oBAAoB,KAAK,EAAE;AAAA,MAC/B,MAAM;AAAA,MACN,SAAS,kBAAkB,KAAK,WAAW;AAAA,MAC3C,SAAS,cAAc,KAAK,UAAU,YAAY,KAAK,YAAY,gBAAgB,KAAK,MAAM;AAAA,MAC9F,eAAe,CAAC;AAAA,MAChB,UAAU;AAAA,MACV,WAAW,KAAK,IAAI;AAAA,MACpB,WAAW;AAAA,MACX,UAAU;AAAA,MACV,SAAS;AAAA,QACP,eAAe,gBAAgB;AAAA,QAC/B,gBAAgB,gBAAgB,MAAM,GAAG,EAAE,EAAE,IAAI,YAAU;AAAA,UACzD,MAAM,MAAM;AAAA,UACZ,MAAM,MAAM;AAAA,UACZ,OAAO,MAAM;AAAA,UACb,OAAO,MAAM;AAAA,UACb,YAAY,MAAM;AAAA,QACpB,EAAE;AAAA,QACF,SAAS,gBAAgB,SAAS,IAC9B,YAAY,gBAAgB,MAAM,SAAS,gBAAgB,SAAS,IAAI,MAAM,EAAE,wBAChF;AAAA,MACN;AAAA,IACF;AAGA,QAAI,CAAC,QAAQ,SAAS;AACpB,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AACA,QAAI,QAAQ,QAAQ,kBAAkB,QAAW;AAC/C,YAAM,IAAI,MAAM,wDAAwD;AAAA,IAC1E;AACA,QAAI,QAAQ,QAAQ,gBAAgB,MAAM,CAAC,QAAQ,QAAQ,kBAAkB,QAAQ,QAAQ,eAAe,WAAW,IAAI;AACzH,YAAM,IAAI,MAAM,oBAAoB,QAAQ,QAAQ,aAAa,oCAAoC;AAAA,IACvG;AACA,QAAI,QAAQ,QAAQ,kBAAkB,QAAQ,QAAQ,gBAAgB,QAAQ;AAC5E,YAAM,IAAI,MAAM,kBAAkB,QAAQ,QAAQ,aAAa,0CAA0C,QAAQ,QAAQ,gBAAgB,MAAM,GAAG;AAAA,IACpJ;AAEA,UAAM,KAAK,aAAa,WAAW,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,yBAAyB,MAAsI;AAC3K,QAAI;AAEF,YAAM,cAAc,MAAM,aAAa,IAAI;AAAA,QACzC,SAAS,KAAK;AAAA,QACd,OAAO;AAAA,QACP,iBAAiB;AAAA,MACnB,CAAC;AAGD,YAAM,WAAW,YACd,IAAI,OAAK,EAAE,KAAK,EAChB,OAAO,WAAS,MAAM,aAAa,IAAI;AAG1C,YAAM,OAAO,KAAK,YAAY,YAAY;AAC1C,YAAM,SAAS,KAAK,OAAO,YAAY;AAEvC,UAAI,mBAAmB;AAGvB,UAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,cAAM,SAAS,OAAO,QAAQ,WAAW,EAAE;AAC3C,YAAI,OAAO,SAAS,GAAG,GAAG;AACxB,6BAAmB,SAAS,OAAO,OAAK,EAAE,KAAK,WAAW,MAAM,CAAC;AAAA,QACnE,OAAO;AACL,6BAAmB,SAAS,OAAO,OAAK,EAAE,UAAU,MAAM;AAAA,QAC5D;AAAA,MACF,WAAW,WAAW,mBAAmB;AACvC,2BAAmB,SAAS,OAAO,OAAK,EAAE,aAAa,UAAU;AAAA,MACnE,OAAO;AAEL,YAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,eAAe,GAAG;AAC3F,6BAAmB,SAAS,OAAO,OAAK;AACtC,kBAAM,MAAM,EAAE,MAAM,YAAY;AAChC,mBAAO,IAAI,SAAS,QAAQ,KAAK,IAAI,SAAS,WAAW,KAClD,IAAI,SAAS,YAAY,KAAK,IAAI,SAAS,aAAa,KACxD,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,mBAAmB;AAAA,UACtE,CAAC;AAAA,QACH,WAAW,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,cAAc,GAAG;AAClG,6BAAmB,SAAS;AAAA,YAAO,OACjC,EAAE,UAAU,cAAc,EAAE,aAAa;AAAA,UAC3C;AAAA,QACF,WAAW,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,UAAU,GAAG;AAC5F,6BAAmB,SAAS;AAAA,YAAO,OACjC,EAAE,UAAU,eACZ,EAAE,MAAM,YAAY,EAAE,SAAS,MAAM,KACrC,EAAE,MAAM,YAAY,EAAE,SAAS,KAAK;AAAA,UACtC;AAAA,QACF,WAAW,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,UAAU,GAAG;AAC7D,6BAAmB,SAAS;AAAA,YAAO,OACjC,EAAE,UAAU,UACZ,EAAE,MAAM,YAAY,EAAE,SAAS,MAAM,KACrC,EAAE,MAAM,YAAY,EAAE,SAAS,UAAU;AAAA,UAC3C;AAAA,QACF,WAAW,KAAK,SAAS,aAAa,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,UAAU,GAAG;AAC7F,6BAAmB,SAAS;AAAA,YAAO,OACjC,EAAE,UAAU,iBACZ,EAAE,MAAM,YAAY,EAAE,SAAS,aAAa,KAC5C,EAAE,MAAM,YAAY,EAAE,SAAS,MAAM;AAAA,UACvC;AAAA,QACF,WAAW,KAAK,SAAS,eAAe,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,YAAY,GAAG;AACjG,6BAAmB,SAAS;AAAA,YAAO,OACjC,EAAE,UAAU,mBACZ,EAAE,MAAM,YAAY,EAAE,SAAS,eAAe;AAAA,UAChD;AAAA,QACF,WAAW,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,OAAO,GAAG;AACjF,6BAAmB,SAAS;AAAA,YAAO,OACjC,EAAE,UAAU,iBACZ,EAAE,aAAa,cACf,EAAE,aAAa;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,gBAAgB,IAAI,KAAK,KAAK,SAAS,EAAE,QAAQ;AACvD,YAAM,iBAAiB,KAAK,aAAa,IAAI,KAAK,KAAK,UAAU,EAAE,QAAQ,IAAI,KAAK,IAAI;AAExF,aAAO,iBACJ,OAAO,WAAS;AACf,YAAI,CAAC,MAAM,WAAY,QAAO;AAC9B,cAAM,aAAa,IAAI,KAAK,MAAM,UAAU,EAAE,QAAQ;AACtD,eAAO,cAAc,iBAAiB,cAAc;AAAA,MACtD,CAAC,EACA,KAAK,CAAC,GAAG,MAAM;AAEd,cAAM,QAAQ,EAAE,aAAa,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI;AAChE,cAAM,QAAQ,EAAE,aAAa,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI;AAChE,eAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACL,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,QAAkC;AACjD,WAAO,KAAK,aAAa,cAAc,QAAQ,IAAI;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,QAAkC;AACjD,WAAO,KAAK,aAAa,cAAc,QAAQ,KAAK;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA0B;AACxB,WAAO,KAAK,aAAa,sBAAsB,EAC5C,OAAO,OAAK,EAAE,WAAW,QAAQ;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,yBAKE;AACA,UAAM,QAAQ,KAAK,aAAa,YAAY;AAC5C,WAAO;AAAA,MACL,QAAQ,MAAM,OAAO,OAAK,EAAE,WAAW,QAAQ,EAAE;AAAA,MACjD,UAAU,MAAM,OAAO,OAAK,EAAE,WAAW,UAAU,EAAE;AAAA,MACrD,QAAQ,MAAM,OAAO,OAAK,EAAE,WAAW,QAAQ,EAAE;AAAA,MACjD,SAAS,MAAM,OAAO,OAAK,EAAE,iBAAiB,EAAE,WAAW,QAAQ,EAAE;AAAA,IACvE;AAAA,EACF;AACF;AASA,eAAsB,+BAA+B,aAGlD;AACD,QAAM,eAAe,gBAAgB,WAAW;AAChD,QAAM,aAAa,KAAK;AAExB,MAAI;AACF,UAAM,QAAQ,MAAM,eAAe,WAAW;AAC9C,UAAM,SAAS,MAAM,aAAa,IAAI;AAAA,MACpC,SAAS;AAAA,MACT,OAAO;AAAA,MACP,iBAAiB;AAAA,IACnB,CAAC;AAED,UAAM,gBAAgB,OAAO,OAAO,OAAK,EAAE,MAAM,aAAa,UAAU,EAAE;AAC1E,UAAM,eAAe,OAAO,OAAO,OAAK,EAAE,MAAM,aAAa,SAAS,EAAE;AAGxE,QAAI,iBAAiB,GAAG;AACtB,aAAO;AAAA,QACL,aAAa;AAAA,QACb,QAAQ,GAAG,aAAa;AAAA,MAC1B;AAAA,IACF;AAGA,QAAI,gBAAgB,KAAK,gBAAgB,GAAG;AAC1C,aAAO;AAAA,QACL,aAAa;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,IACF;AAGA,QAAI,eAAe,GAAG;AACpB,aAAO;AAAA,QACL,aAAa;AAAA,QACb,QAAQ,GAAG,YAAY;AAAA,MACzB;AAAA,IACF;AAGA,QAAI,MAAM,cAAc,IAAI;AAC1B,aAAO;AAAA,QACL,aAAa;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,IACF;AAGA,WAAO;AAAA,MACL,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EAEF,QAAQ;AAEN,WAAO;AAAA,MACL,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAKA,eAAsB,mBAAmB,aAAsC;AAC7E,QAAM,eAAe,gBAAgB,WAAW;AAChD,QAAM,EAAE,YAAY,IAAI,MAAM,+BAA+B,WAAW;AAExE,QAAM,aAAa,iBAAiB,WAAW;AAE/C,SAAO;AACT;AAMA,IAAM,eAAyC,oBAAI,IAAI;AAKhD,SAAS,eAAe,aAAkC;AAC/D,MAAI,UAAU,aAAa,IAAI,WAAW;AAC1C,MAAI,CAAC,SAAS;AACZ,cAAU,IAAI,YAAY,WAAW;AACrC,iBAAa,IAAI,aAAa,OAAO;AAAA,EACvC;AACA,SAAO;AACT;AAKO,SAAS,oBAA0B;AACxC,eAAa,MAAM;AACrB;","names":[]}
@@ -1,361 +0,0 @@
1
- import {
2
- getTrieDirectory,
3
- getWorkingDirectory
4
- } from "./chunk-VVITXIHN.js";
5
-
6
- // src/ai/client.ts
7
- import Anthropic from "@anthropic-ai/sdk";
8
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
9
- import { execSync } from "child_process";
10
- import { join } from "path";
11
- var clientInstance = null;
12
- var apiKeyChecked = false;
13
- var apiKeyAvailable = false;
14
- function isAIAvailable() {
15
- if (!apiKeyChecked) {
16
- checkAPIKey();
17
- }
18
- return apiKeyAvailable;
19
- }
20
- function getKeyFromKeychain() {
21
- if (process.platform !== "darwin") return null;
22
- try {
23
- const result = execSync(
24
- 'security find-generic-password -a "trie" -s "anthropic-api-key" -w 2>/dev/null',
25
- { encoding: "utf-8" }
26
- ).trim();
27
- return result.length > 10 ? result : null;
28
- } catch {
29
- return null;
30
- }
31
- }
32
- function saveKeyToKeychain(key) {
33
- if (process.platform !== "darwin") return false;
34
- try {
35
- try {
36
- execSync('security delete-generic-password -a "trie" -s "anthropic-api-key" 2>/dev/null');
37
- } catch {
38
- }
39
- execSync(`security add-generic-password -a "trie" -s "anthropic-api-key" -w "${key.replace(/"/g, '\\"')}"`);
40
- return true;
41
- } catch {
42
- return false;
43
- }
44
- }
45
- function setAPIKey(key) {
46
- process.env.ANTHROPIC_API_KEY = key;
47
- clientInstance = null;
48
- apiKeyChecked = true;
49
- apiKeyAvailable = true;
50
- if (saveKeyToKeychain(key)) {
51
- return { saved: true, method: "keychain" };
52
- }
53
- try {
54
- const workDir = getWorkingDirectory(void 0, true);
55
- const trieDir = getTrieDirectory(workDir);
56
- const configPath = join(trieDir, "config.json");
57
- let config = {};
58
- if (existsSync(configPath)) {
59
- config = JSON.parse(readFileSync(configPath, "utf-8"));
60
- }
61
- if (!config.apiKeys || typeof config.apiKeys !== "object") config.apiKeys = {};
62
- config.apiKeys.anthropic = key;
63
- mkdirSync(trieDir, { recursive: true });
64
- writeFileSync(configPath, JSON.stringify(config, null, 2));
65
- } catch {
66
- }
67
- return { saved: true, method: "config" };
68
- }
69
- function checkAPIKey() {
70
- apiKeyChecked = true;
71
- const envApiKey = process.env.ANTHROPIC_API_KEY;
72
- if (envApiKey && envApiKey.length > 10) {
73
- apiKeyAvailable = true;
74
- return;
75
- }
76
- const keychainKey = getKeyFromKeychain();
77
- if (keychainKey) {
78
- process.env.ANTHROPIC_API_KEY = keychainKey;
79
- apiKeyAvailable = true;
80
- return;
81
- }
82
- try {
83
- const workDir = getWorkingDirectory(void 0, true);
84
- const configPath = join(getTrieDirectory(workDir), "config.json");
85
- if (existsSync(configPath)) {
86
- const configContent = readFileSync(configPath, "utf-8");
87
- const config = JSON.parse(configContent);
88
- if (config.apiKeys?.anthropic && config.apiKeys.anthropic.length > 10) {
89
- process.env.ANTHROPIC_API_KEY = config.apiKeys.anthropic;
90
- apiKeyAvailable = true;
91
- return;
92
- }
93
- }
94
- } catch {
95
- }
96
- try {
97
- const workDir = getWorkingDirectory(void 0, true);
98
- const envFiles = [".env", ".env.local", ".env.production"];
99
- for (const envFile of envFiles) {
100
- const envPath = join(workDir, envFile);
101
- if (existsSync(envPath)) {
102
- const envContent = readFileSync(envPath, "utf-8");
103
- const lines = envContent.split("\n");
104
- for (const line of lines) {
105
- const match = line.match(/^\s*ANTHROPIC_API_KEY\s*=\s*(.+)$/);
106
- if (match && match[1]) {
107
- const key = match[1].trim().replace(/^["']|["']$/g, "");
108
- if (key.length > 10) {
109
- process.env.ANTHROPIC_API_KEY = key;
110
- apiKeyAvailable = true;
111
- return;
112
- }
113
- }
114
- }
115
- }
116
- }
117
- } catch {
118
- }
119
- apiKeyAvailable = false;
120
- }
121
- function getClient() {
122
- if (!isAIAvailable()) {
123
- throw new Error(
124
- "ANTHROPIC_API_KEY not found. Set it in your environment to enable AI-powered analysis.\nExample: export ANTHROPIC_API_KEY=sk-ant-..."
125
- );
126
- }
127
- if (!clientInstance) {
128
- clientInstance = new Anthropic();
129
- }
130
- return clientInstance;
131
- }
132
- function tryGetClient() {
133
- if (!isAIAvailable()) {
134
- return null;
135
- }
136
- if (!clientInstance) {
137
- clientInstance = new Anthropic();
138
- }
139
- return clientInstance;
140
- }
141
- async function runAIAnalysis(request) {
142
- const client = tryGetClient();
143
- if (!client) {
144
- return {
145
- success: false,
146
- content: "",
147
- error: "AI not available - ANTHROPIC_API_KEY not set"
148
- };
149
- }
150
- try {
151
- const response = await client.messages.create(
152
- {
153
- model: "claude-sonnet-4-20250514",
154
- // Increase default token limit to prevent truncation in Trie Watch
155
- max_tokens: request.maxTokens || 8192,
156
- temperature: request.temperature ?? 0.3,
157
- system: request.systemPrompt,
158
- messages: [
159
- {
160
- role: "user",
161
- content: request.userPrompt
162
- }
163
- ]
164
- },
165
- request.signal ? { signal: request.signal } : void 0
166
- );
167
- const textContent = response.content.filter((block) => block.type === "text").map((block) => block.text).join("\n");
168
- return {
169
- success: true,
170
- content: textContent,
171
- tokensUsed: {
172
- input: response.usage.input_tokens,
173
- output: response.usage.output_tokens
174
- }
175
- };
176
- } catch (error) {
177
- const errorMessage = error instanceof Error ? error.message : String(error);
178
- if (errorMessage.includes("authentication") || errorMessage.includes("API key")) {
179
- return {
180
- success: false,
181
- content: "",
182
- error: "Invalid API key. Check your ANTHROPIC_API_KEY."
183
- };
184
- }
185
- if (errorMessage.includes("rate limit")) {
186
- return {
187
- success: false,
188
- content: "",
189
- error: "Rate limited. Try again in a moment."
190
- };
191
- }
192
- return {
193
- success: false,
194
- content: "",
195
- error: `AI analysis failed: ${errorMessage}`
196
- };
197
- }
198
- }
199
- async function analyzeCodeIssues(request) {
200
- const systemPrompts = {
201
- validate: `You are a senior code reviewer. Analyze the following issues detected by static analysis.
202
- For each issue:
203
- 1. Determine if it's a TRUE POSITIVE (real problem) or FALSE POSITIVE (not actually an issue)
204
- 2. Provide a confidence score (0-100)
205
- 3. Explain your reasoning briefly
206
-
207
- Output format:
208
- ### Issue 1: [file:line]
209
- **Verdict:** TRUE_POSITIVE / FALSE_POSITIVE
210
- **Confidence:** [0-100]
211
- **Reason:** [one line explanation]
212
- **Fix:** [specific fix if true positive]`,
213
- expand: `You are a security expert and senior architect. Given these detected code issues, look deeper:
214
- 1. Are there related problems in the same code that were missed?
215
- 2. What's the root cause of these patterns?
216
- 3. What's the blast radius if these issues cause problems?
217
- 4. What architectural changes would prevent these patterns?
218
-
219
- Be specific. Reference line numbers. Provide code examples.`,
220
- fix: `You are an expert programmer. For each issue, provide a specific fix:
221
- 1. Show the exact code change needed
222
- 2. Explain why this fix works
223
- 3. Note any edge cases to consider
224
-
225
- Use markdown code blocks with the language specified.`,
226
- explain: `You are a patient teacher explaining code issues to a junior developer.
227
- For each issue:
228
- 1. Explain what the problem is in simple terms
229
- 2. Explain why it's a problem (what could go wrong)
230
- 3. Explain the fix and why it works
231
- 4. Provide a learning resource if relevant`
232
- };
233
- const issuesText = request.issues.map((issue, i) => {
234
- let text = `### Issue ${i + 1}: ${issue.file}${issue.line ? ":" + issue.line : ""}
235
- `;
236
- text += `**Problem:** ${issue.issue}
237
- `;
238
- if (issue.code) {
239
- text += `**Code:**
240
- \`\`\`
241
- ${issue.code}
242
- \`\`\`
243
- `;
244
- }
245
- return text;
246
- }).join("\n");
247
- const userPrompt = `${request.context ? `Context: ${request.context}
248
-
249
- ` : ""}${issuesText}`;
250
- return runAIAnalysis({
251
- systemPrompt: systemPrompts[request.analysisType],
252
- userPrompt,
253
- // Increase token limit to prevent response truncation
254
- maxTokens: 8192,
255
- temperature: 0.2
256
- });
257
- }
258
- function getAIStatusMessage() {
259
- if (isAIAvailable()) {
260
- return "[AI] AI-powered analysis enabled";
261
- }
262
- return "[!] AI not available (ANTHROPIC_API_KEY not set) - using pattern-only mode";
263
- }
264
- async function runAIWithTools(request) {
265
- const client = tryGetClient();
266
- if (!client) {
267
- return { success: false, content: "", error: "AI not available - ANTHROPIC_API_KEY not set" };
268
- }
269
- const maxRounds = request.maxToolRounds ?? 5;
270
- const messages = [...request.messages];
271
- const allToolCalls = [];
272
- const allToolResults = [];
273
- const { onProgress } = request;
274
- try {
275
- for (let round = 0; round < maxRounds; round++) {
276
- onProgress?.(round === 0 ? "Analyzing..." : `Processing (round ${round + 1})...`);
277
- const response = await client.messages.create({
278
- model: "claude-sonnet-4-20250514",
279
- // Increase default token limit to prevent truncation in Trie Watch
280
- max_tokens: request.maxTokens || 8192,
281
- temperature: 0.3,
282
- system: request.systemPrompt,
283
- messages,
284
- tools: request.tools
285
- });
286
- const toolUseBlocks = response.content.filter(
287
- (b) => b.type === "tool_use"
288
- );
289
- const textBlocks = response.content.filter(
290
- (b) => b.type === "text"
291
- );
292
- if (toolUseBlocks.length === 0) {
293
- const result2 = {
294
- success: true,
295
- content: textBlocks.map((b) => b.text).join("\n")
296
- };
297
- if (allToolCalls.length > 0) {
298
- result2.toolCalls = allToolCalls;
299
- result2.toolResults = allToolResults;
300
- }
301
- return result2;
302
- }
303
- messages.push({ role: "assistant", content: response.content });
304
- const toolResults = [];
305
- for (const block of toolUseBlocks) {
306
- const input = block.input ?? {};
307
- const toolLabel = block.name.replace(/^trie_/, "").replace(/_/g, " ");
308
- onProgress?.(`Running ${toolLabel}...`);
309
- let resultText;
310
- let isError = false;
311
- try {
312
- resultText = await request.executeTool(block.name, input, onProgress);
313
- } catch (err) {
314
- resultText = `Tool error: ${err instanceof Error ? err.message : String(err)}`;
315
- isError = true;
316
- }
317
- allToolCalls.push({ name: block.name, input, result: resultText });
318
- allToolResults.push(resultText);
319
- toolResults.push({
320
- type: "tool_result",
321
- tool_use_id: block.id,
322
- content: resultText,
323
- is_error: isError
324
- });
325
- }
326
- messages.push({ role: "user", content: toolResults });
327
- if (response.stop_reason === "end_turn") {
328
- const text = textBlocks.map((b) => b.text).join("\n");
329
- const result2 = { success: true, content: text || "Done." };
330
- if (allToolCalls.length > 0) {
331
- result2.toolCalls = allToolCalls;
332
- result2.toolResults = allToolResults;
333
- }
334
- return result2;
335
- }
336
- }
337
- const result = { success: true, content: "Reached maximum tool rounds." };
338
- if (allToolCalls.length > 0) {
339
- result.toolCalls = allToolCalls;
340
- result.toolResults = allToolResults;
341
- }
342
- return result;
343
- } catch (error) {
344
- const errorMessage = error instanceof Error ? error.message : String(error);
345
- return { success: false, content: "", error: `AI tool-use failed: ${errorMessage}` };
346
- }
347
- }
348
-
349
- export {
350
- isAIAvailable,
351
- getKeyFromKeychain,
352
- saveKeyToKeychain,
353
- setAPIKey,
354
- getClient,
355
- tryGetClient,
356
- runAIAnalysis,
357
- analyzeCodeIssues,
358
- getAIStatusMessage,
359
- runAIWithTools
360
- };
361
- //# sourceMappingURL=chunk-FQ45QP5A.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ai/client.ts"],"sourcesContent":["/**\n * Centralized AI Client\n * \n * Handles API key detection, graceful fallbacks, and AI-powered analysis.\n * All agents use this for AI-enhanced analysis.\n * \n * API Key Setup:\n * 1. Set ANTHROPIC_API_KEY in your environment\n * 2. Or add it to your MCP server config (mcp.json)\n * 3. Or create .env file in your project root\n * \n * If no API key is found, agents fall back to pattern-only mode.\n */\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { execSync } from 'node:child_process';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from '../utils/workspace.js';\n\n// Cached client instance\nlet clientInstance: Anthropic | null = null;\nlet apiKeyChecked = false;\nlet apiKeyAvailable = false;\n\n/**\n * Check if AI is available (API key is set)\n */\nexport function isAIAvailable(): boolean {\n if (!apiKeyChecked) {\n checkAPIKey();\n }\n return apiKeyAvailable;\n}\n\n/**\n * Read API key from Apple Keychain (macOS only)\n */\nexport function getKeyFromKeychain(): string | null {\n if (process.platform !== 'darwin') return null;\n try {\n const result = execSync(\n 'security find-generic-password -a \"trie\" -s \"anthropic-api-key\" -w 2>/dev/null',\n { encoding: 'utf-8' }\n ).trim();\n return result.length > 10 ? result : null;\n } catch { return null; }\n}\n\n/**\n * Save API key to Apple Keychain (macOS only)\n */\nexport function saveKeyToKeychain(key: string): boolean {\n if (process.platform !== 'darwin') return false;\n try {\n try { execSync('security delete-generic-password -a \"trie\" -s \"anthropic-api-key\" 2>/dev/null'); } catch { /* not found */ }\n execSync(`security add-generic-password -a \"trie\" -s \"anthropic-api-key\" -w \"${key.replace(/\"/g, '\\\\\"')}\"`);\n return true;\n } catch { return false; }\n}\n\n/**\n * Save API key and refresh the cached state\n */\nexport function setAPIKey(key: string): { saved: boolean; method: 'keychain' | 'config' } {\n process.env.ANTHROPIC_API_KEY = key;\n clientInstance = null;\n apiKeyChecked = true;\n apiKeyAvailable = true;\n\n if (saveKeyToKeychain(key)) {\n return { saved: true, method: 'keychain' };\n }\n\n try {\n const workDir = getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(workDir);\n const configPath = join(trieDir, 'config.json');\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n config = JSON.parse(readFileSync(configPath, 'utf-8'));\n }\n if (!config.apiKeys || typeof config.apiKeys !== 'object') config.apiKeys = {};\n (config.apiKeys as Record<string, string>).anthropic = key;\n mkdirSync(trieDir, { recursive: true });\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n } catch { /* best effort */ }\n\n return { saved: true, method: 'config' };\n}\n\n/**\n * Check for API key in environment, keychain, config, and .env files\n */\nfunction checkAPIKey(): void {\n apiKeyChecked = true;\n \n // 1. Check standard env var first\n const envApiKey = process.env.ANTHROPIC_API_KEY;\n if (envApiKey && envApiKey.length > 10) {\n apiKeyAvailable = true;\n return;\n }\n\n // 2. Check Apple Keychain (macOS)\n const keychainKey = getKeyFromKeychain();\n if (keychainKey) {\n process.env.ANTHROPIC_API_KEY = keychainKey;\n apiKeyAvailable = true;\n return;\n }\n \n // 3. Check config file\n try {\n const workDir = getWorkingDirectory(undefined, true);\n const configPath = join(getTrieDirectory(workDir), 'config.json');\n \n if (existsSync(configPath)) {\n const configContent = readFileSync(configPath, 'utf-8');\n const config = JSON.parse(configContent);\n \n if (config.apiKeys?.anthropic && config.apiKeys.anthropic.length > 10) {\n process.env.ANTHROPIC_API_KEY = config.apiKeys.anthropic;\n apiKeyAvailable = true;\n return;\n }\n }\n } catch {\n // Config file doesn't exist or couldn't be read\n }\n \n // 4. Check .env files\n try {\n const workDir = getWorkingDirectory(undefined, true);\n const envFiles = ['.env', '.env.local', '.env.production'];\n \n for (const envFile of envFiles) {\n const envPath = join(workDir, envFile);\n if (existsSync(envPath)) {\n const envContent = readFileSync(envPath, 'utf-8');\n const lines = envContent.split('\\n');\n \n for (const line of lines) {\n const match = line.match(/^\\s*ANTHROPIC_API_KEY\\s*=\\s*(.+)$/);\n if (match && match[1]) {\n const key = match[1].trim().replace(/^[\"']|[\"']$/g, '');\n if (key.length > 10) {\n process.env.ANTHROPIC_API_KEY = key;\n apiKeyAvailable = true;\n return;\n }\n }\n }\n }\n }\n } catch {\n // .env file doesn't exist or couldn't be read\n }\n \n apiKeyAvailable = false;\n}\n\n/**\n * Get the Anthropic client (lazy initialized)\n * Throws if API key is not available\n */\nexport function getClient(): Anthropic {\n if (!isAIAvailable()) {\n throw new Error(\n 'ANTHROPIC_API_KEY not found. Set it in your environment to enable AI-powered analysis.\\n' +\n 'Example: export ANTHROPIC_API_KEY=sk-ant-...'\n );\n }\n \n if (!clientInstance) {\n clientInstance = new Anthropic();\n }\n \n return clientInstance;\n}\n\n/**\n * Try to get client, return null if not available\n */\nexport function tryGetClient(): Anthropic | null {\n if (!isAIAvailable()) {\n return null;\n }\n \n if (!clientInstance) {\n clientInstance = new Anthropic();\n }\n \n return clientInstance;\n}\n\nexport interface AIAnalysisRequest {\n systemPrompt: string;\n userPrompt: string;\n maxTokens?: number;\n temperature?: number;\n /** Optional AbortSignal to cancel the request */\n signal?: AbortSignal;\n}\n\nexport interface AIAnalysisResult {\n success: boolean;\n content: string;\n error?: string;\n tokensUsed?: {\n input: number;\n output: number;\n };\n}\n\n/**\n * Run AI analysis with the given prompts\n */\nexport async function runAIAnalysis(request: AIAnalysisRequest): Promise<AIAnalysisResult> {\n const client = tryGetClient();\n \n if (!client) {\n return {\n success: false,\n content: '',\n error: 'AI not available - ANTHROPIC_API_KEY not set'\n };\n }\n \n try {\n const response = await client.messages.create(\n {\n model: 'claude-sonnet-4-20250514',\n // Increase default token limit to prevent truncation in Trie Watch\n max_tokens: request.maxTokens || 8192,\n temperature: request.temperature ?? 0.3,\n system: request.systemPrompt,\n messages: [\n {\n role: 'user',\n content: request.userPrompt\n }\n ]\n },\n request.signal ? { signal: request.signal } : undefined\n );\n \n // Extract text content - ensure full text is preserved without truncation\n const textContent = response.content\n .filter((block): block is Anthropic.TextBlock => block.type === 'text')\n .map(block => block.text)\n .join('\\n');\n \n return {\n success: true,\n content: textContent,\n tokensUsed: {\n input: response.usage.input_tokens,\n output: response.usage.output_tokens\n }\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n \n // Check for specific error types\n if (errorMessage.includes('authentication') || errorMessage.includes('API key')) {\n return {\n success: false,\n content: '',\n error: 'Invalid API key. Check your ANTHROPIC_API_KEY.'\n };\n }\n \n if (errorMessage.includes('rate limit')) {\n return {\n success: false,\n content: '',\n error: 'Rate limited. Try again in a moment.'\n };\n }\n \n return {\n success: false,\n content: '',\n error: `AI analysis failed: ${errorMessage}`\n };\n }\n}\n\n/**\n * AI analysis for code issues\n */\nexport interface CodeIssueAnalysisRequest {\n issues: Array<{\n file: string;\n line?: number;\n issue: string;\n code?: string;\n }>;\n analysisType: 'validate' | 'expand' | 'fix' | 'explain';\n context?: string;\n}\n\n/**\n * Run AI analysis on code issues\n * Used by agents to validate, expand, or fix detected issues\n */\nexport async function analyzeCodeIssues(request: CodeIssueAnalysisRequest): Promise<AIAnalysisResult> {\n const systemPrompts: Record<CodeIssueAnalysisRequest['analysisType'], string> = {\n validate: `You are a senior code reviewer. Analyze the following issues detected by static analysis.\nFor each issue:\n1. Determine if it's a TRUE POSITIVE (real problem) or FALSE POSITIVE (not actually an issue)\n2. Provide a confidence score (0-100)\n3. Explain your reasoning briefly\n\nOutput format:\n### Issue 1: [file:line]\n**Verdict:** TRUE_POSITIVE / FALSE_POSITIVE\n**Confidence:** [0-100]\n**Reason:** [one line explanation]\n**Fix:** [specific fix if true positive]`,\n\n expand: `You are a security expert and senior architect. Given these detected code issues, look deeper:\n1. Are there related problems in the same code that were missed?\n2. What's the root cause of these patterns?\n3. What's the blast radius if these issues cause problems?\n4. What architectural changes would prevent these patterns?\n\nBe specific. Reference line numbers. Provide code examples.`,\n\n fix: `You are an expert programmer. For each issue, provide a specific fix:\n1. Show the exact code change needed\n2. Explain why this fix works\n3. Note any edge cases to consider\n\nUse markdown code blocks with the language specified.`,\n\n explain: `You are a patient teacher explaining code issues to a junior developer.\nFor each issue:\n1. Explain what the problem is in simple terms\n2. Explain why it's a problem (what could go wrong)\n3. Explain the fix and why it works\n4. Provide a learning resource if relevant`\n };\n\n const issuesText = request.issues.map((issue, i) => {\n let text = `### Issue ${i + 1}: ${issue.file}${issue.line ? ':' + issue.line : ''}\\n`;\n text += `**Problem:** ${issue.issue}\\n`;\n if (issue.code) {\n // Preserve complete code without truncation for analysis\n text += `**Code:**\\n\\`\\`\\`\\n${issue.code}\\n\\`\\`\\`\\n`;\n }\n return text;\n }).join('\\n');\n\n const userPrompt = `${request.context ? `Context: ${request.context}\\n\\n` : ''}${issuesText}`;\n\n return runAIAnalysis({\n systemPrompt: systemPrompts[request.analysisType],\n userPrompt,\n // Increase token limit to prevent response truncation\n maxTokens: 8192,\n temperature: 0.2\n });\n}\n\n/**\n * Get status message about AI availability\n */\nexport function getAIStatusMessage(): string {\n if (isAIAvailable()) {\n return '[AI] AI-powered analysis enabled';\n }\n return '[!] AI not available (ANTHROPIC_API_KEY not set) - using pattern-only mode';\n}\n\nexport interface AIToolCallRecord {\n name: string;\n input: Record<string, unknown>;\n result?: string;\n}\n\nexport interface AIToolCallResult {\n success: boolean;\n content: string;\n error?: string;\n toolCalls?: AIToolCallRecord[];\n toolResults?: string[];\n}\n\n/**\n * Run AI analysis with tool-use support.\n * Loops until Claude returns a final text response or hits maxToolRounds.\n */\nexport async function runAIWithTools(request: {\n systemPrompt: string;\n messages: Anthropic.MessageParam[];\n tools: Anthropic.Tool[];\n executeTool: (name: string, input: Record<string, unknown>, onProgress?: (msg: string) => void) => Promise<string>;\n maxTokens?: number;\n maxToolRounds?: number;\n onProgress?: (message: string) => void;\n}): Promise<AIToolCallResult> {\n const client = tryGetClient();\n if (!client) {\n return { success: false, content: '', error: 'AI not available - ANTHROPIC_API_KEY not set' };\n }\n\n const maxRounds = request.maxToolRounds ?? 5;\n const messages: Anthropic.MessageParam[] = [...request.messages];\n const allToolCalls: AIToolCallRecord[] = [];\n const allToolResults: string[] = [];\n\n const { onProgress } = request;\n\n try {\n for (let round = 0; round < maxRounds; round++) {\n onProgress?.(round === 0 ? 'Analyzing...' : `Processing (round ${round + 1})...`);\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n // Increase default token limit to prevent truncation in Trie Watch\n max_tokens: request.maxTokens || 8192,\n temperature: 0.3,\n system: request.systemPrompt,\n messages,\n tools: request.tools,\n });\n\n const toolUseBlocks = response.content.filter(\n (b): b is Anthropic.ToolUseBlock => b.type === 'tool_use'\n );\n const textBlocks = response.content.filter(\n (b): b is Anthropic.TextBlock => b.type === 'text'\n );\n\n if (toolUseBlocks.length === 0) {\n // Preserve complete text content without truncation\n const result: AIToolCallResult = {\n success: true,\n content: textBlocks.map(b => b.text).join('\\n'),\n };\n if (allToolCalls.length > 0) {\n result.toolCalls = allToolCalls;\n result.toolResults = allToolResults;\n }\n return result;\n }\n\n // Claude wants to use tools -- execute them\n messages.push({ role: 'assistant', content: response.content });\n\n const toolResults: Anthropic.ToolResultBlockParam[] = [];\n for (const block of toolUseBlocks) {\n const input = (block.input ?? {}) as Record<string, unknown>;\n const toolLabel = block.name.replace(/^trie_/, '').replace(/_/g, ' ');\n onProgress?.(`Running ${toolLabel}...`);\n let resultText: string;\n let isError = false;\n try {\n resultText = await request.executeTool(block.name, input, onProgress);\n } catch (err) {\n resultText = `Tool error: ${err instanceof Error ? err.message : String(err)}`;\n isError = true;\n }\n allToolCalls.push({ name: block.name, input, result: resultText });\n allToolResults.push(resultText);\n toolResults.push({\n type: 'tool_result',\n tool_use_id: block.id,\n content: resultText,\n is_error: isError,\n });\n }\n\n messages.push({ role: 'user', content: toolResults });\n\n if (response.stop_reason === 'end_turn') {\n // Preserve complete text without truncation\n const text = textBlocks.map(b => b.text).join('\\n');\n const result: AIToolCallResult = { success: true, content: text || 'Done.' };\n if (allToolCalls.length > 0) {\n result.toolCalls = allToolCalls;\n result.toolResults = allToolResults;\n }\n return result;\n }\n }\n\n const result: AIToolCallResult = { success: true, content: 'Reached maximum tool rounds.' };\n if (allToolCalls.length > 0) {\n result.toolCalls = allToolCalls;\n result.toolResults = allToolResults;\n }\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { success: false, content: '', error: `AI tool-use failed: ${errorMessage}` };\n }\n}\n"],"mappings":"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","names":["result"]}