@triedotdev/mcp 1.0.123 → 1.0.124
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/dist/{chunk-QIS2VDJL.js → chunk-7J4ZOOAD.js} +50 -13
- package/dist/{chunk-QIS2VDJL.js.map → chunk-7J4ZOOAD.js.map} +1 -1
- package/dist/{chunk-F4ZIAHTZ.js → chunk-A4EDTN6R.js} +2 -2
- package/dist/{chunk-B46FDUKR.js → chunk-D2CGMX7K.js} +4 -4
- package/dist/{chunk-CKT2A33R.js → chunk-W2DEBKZ2.js} +2 -2
- package/dist/{chunk-WRGSH5RT.js → chunk-WMI44VIC.js} +2 -2
- package/dist/{chunk-WRGSH5RT.js.map → chunk-WMI44VIC.js.map} +1 -1
- package/dist/cli/main.js +2 -2
- package/dist/cli/yolo-daemon.js +5 -5
- package/dist/{client-PMKE26IV.js → client-EWP4SIG3.js} +2 -2
- package/dist/{goal-validator-XYA364W3.js → goal-validator-CKFKJ46J.js} +2 -2
- package/dist/{guardian-agent-PTC6G37Q.js → guardian-agent-5QVLDPKB.js} +5 -5
- package/dist/{hypothesis-WWDONGPU.js → hypothesis-HFYZNIMZ.js} +2 -2
- package/dist/index.js +147 -27
- package/dist/index.js.map +1 -1
- package/dist/ui/chat.html +821 -0
- package/dist/ui/goals.html +724 -0
- package/dist/ui/hypotheses.html +768 -0
- package/dist/ui/ledger.html +711 -0
- package/dist/ui/nudges.html +752 -0
- package/package.json +1 -1
- package/dist/ui/memory-viewer.html +0 -773
- package/dist/ui/pr-review.html +0 -742
- package/dist/ui/scan-dashboard.html +0 -741
- package/dist/ui/visual-qa.html +0 -762
- /package/dist/{chunk-F4ZIAHTZ.js.map → chunk-A4EDTN6R.js.map} +0 -0
- /package/dist/{chunk-B46FDUKR.js.map → chunk-D2CGMX7K.js.map} +0 -0
- /package/dist/{chunk-CKT2A33R.js.map → chunk-W2DEBKZ2.js.map} +0 -0
- /package/dist/{client-PMKE26IV.js.map → client-EWP4SIG3.js.map} +0 -0
- /package/dist/{goal-validator-XYA364W3.js.map → goal-validator-CKFKJ46J.js.map} +0 -0
- /package/dist/{guardian-agent-PTC6G37Q.js.map → guardian-agent-5QVLDPKB.js.map} +0 -0
- /package/dist/{hypothesis-WWDONGPU.js.map → hypothesis-HFYZNIMZ.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
tryGetClient
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WMI44VIC.js";
|
|
4
4
|
import {
|
|
5
5
|
searchIssues
|
|
6
6
|
} from "./chunk-K5EXATBF.js";
|
|
@@ -801,4 +801,4 @@ export {
|
|
|
801
801
|
getStorage,
|
|
802
802
|
GotchaPredictor
|
|
803
803
|
};
|
|
804
|
-
//# sourceMappingURL=chunk-
|
|
804
|
+
//# sourceMappingURL=chunk-A4EDTN6R.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-TRIJC5MW.js";
|
|
4
4
|
import {
|
|
5
5
|
getHypothesisEngine
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-W2DEBKZ2.js";
|
|
7
7
|
import {
|
|
8
8
|
getInsightStore
|
|
9
9
|
} from "./chunk-4YJ6KLGI.js";
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
GotchaPredictor,
|
|
12
12
|
findCrossProjectPatterns,
|
|
13
13
|
recordToGlobalMemory
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-A4EDTN6R.js";
|
|
15
15
|
import {
|
|
16
16
|
isAIAvailable,
|
|
17
17
|
runAIAnalysis
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-WMI44VIC.js";
|
|
19
19
|
import {
|
|
20
20
|
autoResolveIssues,
|
|
21
21
|
getHistoricalInsights,
|
|
@@ -2143,4 +2143,4 @@ export {
|
|
|
2143
2143
|
GuardianAgent,
|
|
2144
2144
|
getGuardian
|
|
2145
2145
|
};
|
|
2146
|
-
//# sourceMappingURL=chunk-
|
|
2146
|
+
//# sourceMappingURL=chunk-D2CGMX7K.js.map
|
|
@@ -133,7 +133,7 @@ var HypothesisEngine = class {
|
|
|
133
133
|
* This enables fully agentic hypothesis creation based on actual codebase observations
|
|
134
134
|
*/
|
|
135
135
|
async generateHypothesesWithAI(context) {
|
|
136
|
-
const { isAIAvailable, runAIAnalysis } = await import("./client-
|
|
136
|
+
const { isAIAvailable, runAIAnalysis } = await import("./client-EWP4SIG3.js");
|
|
137
137
|
if (!isAIAvailable()) {
|
|
138
138
|
return [];
|
|
139
139
|
}
|
|
@@ -718,4 +718,4 @@ export {
|
|
|
718
718
|
clearHypothesisEngines,
|
|
719
719
|
gatherEvidenceForHypothesis
|
|
720
720
|
};
|
|
721
|
-
//# sourceMappingURL=chunk-
|
|
721
|
+
//# sourceMappingURL=chunk-W2DEBKZ2.js.map
|
|
@@ -292,7 +292,7 @@ async function runAIWithTools(request) {
|
|
|
292
292
|
const toolResults = [];
|
|
293
293
|
for (const block of toolUseBlocks) {
|
|
294
294
|
const input = block.input ?? {};
|
|
295
|
-
allToolCalls.push({ name: block.name, input });
|
|
295
|
+
allToolCalls.push({ id: block.id, name: block.name, input });
|
|
296
296
|
let resultText;
|
|
297
297
|
let isError = false;
|
|
298
298
|
try {
|
|
@@ -337,4 +337,4 @@ export {
|
|
|
337
337
|
getAIStatusMessage,
|
|
338
338
|
runAIWithTools
|
|
339
339
|
};
|
|
340
|
-
//# sourceMappingURL=chunk-
|
|
340
|
+
//# sourceMappingURL=chunk-WMI44VIC.js.map
|
|
@@ -1 +1 @@
|
|
|
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}\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 model: 'claude-sonnet-4-20250514',\n max_tokens: request.maxTokens || 4096,\n temperature: request.temperature ?? 0.3,\n system: request.systemPrompt,\n messages: [\n {\n role: 'user',\n content: request.userPrompt\n }\n ]\n });\n \n // Extract text content\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 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 maxTokens: 4096,\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}\n\nexport interface AIToolCallResult {\n success: boolean;\n content: string;\n error?: string;\n toolCalls?: AIToolCallRecord[];\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>) => Promise<string>;\n maxTokens?: number;\n maxToolRounds?: number;\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\n try {\n for (let round = 0; round < maxRounds; round++) {\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n max_tokens: request.maxTokens || 4096,\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 const result: AIToolCallResult = {\n success: true,\n content: textBlocks.map(b => b.text).join('\\n'),\n };\n if (allToolCalls.length > 0) result.toolCalls = allToolCalls;\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 allToolCalls.push({ name: block.name, input });\n let resultText: string;\n let isError = false;\n try {\n resultText = await request.executeTool(block.name, input);\n } catch (err) {\n resultText = `Tool error: ${err instanceof Error ? err.message : String(err)}`;\n isError = true;\n }\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 const text = textBlocks.map(b => b.text).join('\\n');\n const result: AIToolCallResult = { success: true, content: text || 'Done.' };\n if (allToolCalls.length > 0) result.toolCalls = allToolCalls;\n return result;\n }\n }\n\n const result: AIToolCallResult = { success: true, content: 'Reached maximum tool rounds.' };\n if (allToolCalls.length > 0) result.toolCalls = allToolCalls;\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"]}
|
|
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}\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 model: 'claude-sonnet-4-20250514',\n max_tokens: request.maxTokens || 4096,\n temperature: request.temperature ?? 0.3,\n system: request.systemPrompt,\n messages: [\n {\n role: 'user',\n content: request.userPrompt\n }\n ]\n });\n \n // Extract text content\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 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 maxTokens: 4096,\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}\n\nexport interface AIToolCallResult {\n success: boolean;\n content: string;\n error?: string;\n toolCalls?: AIToolCallRecord[];\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>) => Promise<string>;\n maxTokens?: number;\n maxToolRounds?: number;\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\n try {\n for (let round = 0; round < maxRounds; round++) {\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n max_tokens: request.maxTokens || 4096,\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 const result: AIToolCallResult = {\n success: true,\n content: textBlocks.map(b => b.text).join('\\n'),\n };\n if (allToolCalls.length > 0) result.toolCalls = allToolCalls;\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 allToolCalls.push({ id: block.id, name: block.name, input });\n let resultText: string;\n let isError = false;\n try {\n resultText = await request.executeTool(block.name, input);\n } catch (err) {\n resultText = `Tool error: ${err instanceof Error ? err.message : String(err)}`;\n isError = true;\n }\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 const text = textBlocks.map(b => b.text).join('\\n');\n const result: AIToolCallResult = { success: true, content: text || 'Done.' };\n if (allToolCalls.length > 0) result.toolCalls = allToolCalls;\n return result;\n }\n }\n\n const result: AIToolCallResult = { success: true, content: 'Reached maximum tool rounds.' };\n if (allToolCalls.length > 0) result.toolCalls = allToolCalls;\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"]}
|
package/dist/cli/main.js
CHANGED
|
@@ -43,8 +43,8 @@ import {
|
|
|
43
43
|
listTrackedProjects,
|
|
44
44
|
searchGlobalPatterns,
|
|
45
45
|
updateGlobalMemoryMd
|
|
46
|
-
} from "../chunk-
|
|
47
|
-
import "../chunk-
|
|
46
|
+
} from "../chunk-A4EDTN6R.js";
|
|
47
|
+
import "../chunk-WMI44VIC.js";
|
|
48
48
|
import {
|
|
49
49
|
getDailyLogs,
|
|
50
50
|
getMemoryStats,
|
package/dist/cli/yolo-daemon.js
CHANGED
|
@@ -3,18 +3,18 @@ import {
|
|
|
3
3
|
InteractiveDashboard,
|
|
4
4
|
StreamingManager,
|
|
5
5
|
TrieScanTool
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-7J4ZOOAD.js";
|
|
7
|
+
import "../chunk-D2CGMX7K.js";
|
|
8
8
|
import "../chunk-DFPVUMVE.js";
|
|
9
9
|
import "../chunk-TRIJC5MW.js";
|
|
10
|
-
import "../chunk-
|
|
10
|
+
import "../chunk-W2DEBKZ2.js";
|
|
11
11
|
import "../chunk-4YJ6KLGI.js";
|
|
12
12
|
import {
|
|
13
13
|
isTrieInitialized
|
|
14
14
|
} from "../chunk-6LD7OPJL.js";
|
|
15
15
|
import "../chunk-ZV2K6M7T.js";
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
16
|
+
import "../chunk-A4EDTN6R.js";
|
|
17
|
+
import "../chunk-WMI44VIC.js";
|
|
18
18
|
import "../chunk-K5EXATBF.js";
|
|
19
19
|
import "../chunk-UHMMANC2.js";
|
|
20
20
|
import "../chunk-WS6OA7H6.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
saveKeyToKeychain,
|
|
10
10
|
setAPIKey,
|
|
11
11
|
tryGetClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-WMI44VIC.js";
|
|
13
13
|
import "./chunk-45Y5TLQZ.js";
|
|
14
14
|
import "./chunk-APMV77PU.js";
|
|
15
15
|
import "./chunk-DGUM43GV.js";
|
|
@@ -25,4 +25,4 @@ export {
|
|
|
25
25
|
setAPIKey,
|
|
26
26
|
tryGetClient
|
|
27
27
|
};
|
|
28
|
-
//# sourceMappingURL=client-
|
|
28
|
+
//# sourceMappingURL=client-EWP4SIG3.js.map
|
|
@@ -56,7 +56,7 @@ async function recordGoalViolationFixed(goal, file, projectPath) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
async function checkFilesForGoalViolations(goals, projectPath, filesToCheck) {
|
|
59
|
-
const { isAIAvailable, runAIAnalysis } = await import("./client-
|
|
59
|
+
const { isAIAvailable, runAIAnalysis } = await import("./client-EWP4SIG3.js");
|
|
60
60
|
if (!isAIAvailable()) {
|
|
61
61
|
throw new Error("AI not available - ANTHROPIC_API_KEY not set");
|
|
62
62
|
}
|
|
@@ -185,4 +185,4 @@ export {
|
|
|
185
185
|
recordGoalViolationCaught,
|
|
186
186
|
recordGoalViolationFixed
|
|
187
187
|
};
|
|
188
|
-
//# sourceMappingURL=goal-validator-
|
|
188
|
+
//# sourceMappingURL=goal-validator-CKFKJ46J.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GuardianAgent,
|
|
3
3
|
getGuardian
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-D2CGMX7K.js";
|
|
5
5
|
import "./chunk-TRIJC5MW.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-W2DEBKZ2.js";
|
|
7
7
|
import "./chunk-4YJ6KLGI.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-A4EDTN6R.js";
|
|
9
|
+
import "./chunk-WMI44VIC.js";
|
|
10
10
|
import "./chunk-K5EXATBF.js";
|
|
11
11
|
import "./chunk-UHMMANC2.js";
|
|
12
12
|
import "./chunk-WS6OA7H6.js";
|
|
@@ -23,4 +23,4 @@ export {
|
|
|
23
23
|
GuardianAgent,
|
|
24
24
|
getGuardian
|
|
25
25
|
};
|
|
26
|
-
//# sourceMappingURL=guardian-agent-
|
|
26
|
+
//# sourceMappingURL=guardian-agent-5QVLDPKB.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
clearHypothesisEngines,
|
|
4
4
|
gatherEvidenceForHypothesis,
|
|
5
5
|
getHypothesisEngine
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-W2DEBKZ2.js";
|
|
7
7
|
import "./chunk-4YJ6KLGI.js";
|
|
8
8
|
import "./chunk-K5EXATBF.js";
|
|
9
9
|
import "./chunk-UHMMANC2.js";
|
|
@@ -19,4 +19,4 @@ export {
|
|
|
19
19
|
gatherEvidenceForHypothesis,
|
|
20
20
|
getHypothesisEngine
|
|
21
21
|
};
|
|
22
|
-
//# sourceMappingURL=hypothesis-
|
|
22
|
+
//# sourceMappingURL=hypothesis-HFYZNIMZ.js.map
|
package/dist/index.js
CHANGED
|
@@ -38,11 +38,11 @@ import {
|
|
|
38
38
|
getPrompt,
|
|
39
39
|
getSystemPrompt,
|
|
40
40
|
handleCheckpointTool
|
|
41
|
-
} from "./chunk-
|
|
42
|
-
import "./chunk-
|
|
41
|
+
} from "./chunk-7J4ZOOAD.js";
|
|
42
|
+
import "./chunk-D2CGMX7K.js";
|
|
43
43
|
import "./chunk-DFPVUMVE.js";
|
|
44
44
|
import "./chunk-TRIJC5MW.js";
|
|
45
|
-
import "./chunk-
|
|
45
|
+
import "./chunk-W2DEBKZ2.js";
|
|
46
46
|
import "./chunk-4YJ6KLGI.js";
|
|
47
47
|
import {
|
|
48
48
|
exportToJson,
|
|
@@ -59,11 +59,11 @@ import {
|
|
|
59
59
|
getGlobalMemoryStats,
|
|
60
60
|
listTrackedProjects,
|
|
61
61
|
searchGlobalPatterns
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-A4EDTN6R.js";
|
|
63
63
|
import {
|
|
64
64
|
isAIAvailable,
|
|
65
65
|
runAIAnalysis
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-WMI44VIC.js";
|
|
67
67
|
import {
|
|
68
68
|
findSimilarIssues,
|
|
69
69
|
getMemoryStats,
|
|
@@ -1251,7 +1251,10 @@ var TrieWatchTool = class _TrieWatchTool {
|
|
|
1251
1251
|
debounceMs
|
|
1252
1252
|
});
|
|
1253
1253
|
}
|
|
1254
|
-
|
|
1254
|
+
setTimeout(() => {
|
|
1255
|
+
void this.initialGoalComplianceScan();
|
|
1256
|
+
void this.initialHypothesisGeneration();
|
|
1257
|
+
}, 1e3);
|
|
1255
1258
|
return {
|
|
1256
1259
|
content: [{
|
|
1257
1260
|
type: "text",
|
|
@@ -1426,7 +1429,7 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1426
1429
|
async checkAndGenerateHypotheses(projectPath) {
|
|
1427
1430
|
if (!isAIAvailable()) return;
|
|
1428
1431
|
try {
|
|
1429
|
-
const { getHypothesisEngine } = await import("./hypothesis-
|
|
1432
|
+
const { getHypothesisEngine } = await import("./hypothesis-HFYZNIMZ.js");
|
|
1430
1433
|
const { getOutputManager: getOutputManager2 } = await import("./output-manager-BOTMXSND.js");
|
|
1431
1434
|
const hypothesisEngine = getHypothesisEngine(projectPath);
|
|
1432
1435
|
const recentIssues = Array.from(this.state.issueCache.values()).flat();
|
|
@@ -1635,10 +1638,16 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1635
1638
|
this.state.lastAutoScan = now;
|
|
1636
1639
|
try {
|
|
1637
1640
|
const graph = new ContextGraph(projectPath);
|
|
1638
|
-
const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-
|
|
1641
|
+
const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-CKFKJ46J.js");
|
|
1639
1642
|
const { appendIssuesToLedger } = await import("./ledger-JMPGJGLB.js");
|
|
1643
|
+
console.debug("[AI Watcher] Loading active goals...");
|
|
1640
1644
|
const activeGoals = await getActiveGoals(projectPath);
|
|
1641
1645
|
const hasGoals = activeGoals.length > 0;
|
|
1646
|
+
console.debug("[AI Watcher] Goals loaded:", {
|
|
1647
|
+
totalGoals: activeGoals.length,
|
|
1648
|
+
hasGoals,
|
|
1649
|
+
goals: activeGoals.map((g) => ({ id: g.id, description: g.description, status: g.status }))
|
|
1650
|
+
});
|
|
1642
1651
|
if (this.isQuiet() && !hasGoals) return;
|
|
1643
1652
|
const scored = [];
|
|
1644
1653
|
for (const file of files) {
|
|
@@ -1683,6 +1692,13 @@ ${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
|
|
|
1683
1692
|
Goal violations are HIGH PRIORITY. If a file violates any goal, you MUST report it.
|
|
1684
1693
|
`;
|
|
1685
1694
|
}
|
|
1695
|
+
console.debug("[AI Watcher] Sending files to AI analysis:", {
|
|
1696
|
+
fileCount: valid.length,
|
|
1697
|
+
hasGoals,
|
|
1698
|
+
goalsIncluded: hasGoals,
|
|
1699
|
+
filePaths: valid.map((f) => f.path),
|
|
1700
|
+
goalsSection: goalsSection.slice(0, 200) + (goalsSection.length > 200 ? "..." : "")
|
|
1701
|
+
});
|
|
1686
1702
|
const result = await runAIAnalysis({
|
|
1687
1703
|
systemPrompt: `You are a code quality watcher. You review code for two things:
|
|
1688
1704
|
|
|
@@ -1711,13 +1727,29 @@ ${filesBlock}`,
|
|
|
1711
1727
|
if (result.tokensUsed) {
|
|
1712
1728
|
this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
|
|
1713
1729
|
}
|
|
1714
|
-
|
|
1730
|
+
console.debug("[AI Watcher] AI analysis result:", {
|
|
1731
|
+
success: result.success,
|
|
1732
|
+
contentLength: result.content ? result.content.length : 0,
|
|
1733
|
+
tokensUsed: result.tokensUsed,
|
|
1734
|
+
contentPreview: result.content ? result.content.slice(0, 500) : "null"
|
|
1735
|
+
});
|
|
1736
|
+
if (!result.success || !result.content.trim()) {
|
|
1737
|
+
console.debug("[AI Watcher] AI analysis failed or returned empty content");
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1715
1740
|
let issues = [];
|
|
1716
1741
|
try {
|
|
1717
1742
|
const cleaned = result.content.replace(/```json?\n?|\n?```/g, "").trim();
|
|
1743
|
+
console.debug("[AI Watcher] Parsing AI response:", { cleanedContent: cleaned.slice(0, 300) });
|
|
1718
1744
|
issues = JSON.parse(cleaned);
|
|
1719
1745
|
if (!Array.isArray(issues)) issues = [];
|
|
1720
|
-
|
|
1746
|
+
console.debug("[AI Watcher] Parsed issues:", {
|
|
1747
|
+
totalIssues: issues.length,
|
|
1748
|
+
goalViolations: issues.filter((i) => i.isGoalViolation).length,
|
|
1749
|
+
issueTypes: issues.map((i) => ({ file: i.file, isGoalViolation: i.isGoalViolation, goalIndex: i.goalIndex }))
|
|
1750
|
+
});
|
|
1751
|
+
} catch (error) {
|
|
1752
|
+
console.debug("[AI Watcher] Failed to parse AI response:", error);
|
|
1721
1753
|
return;
|
|
1722
1754
|
}
|
|
1723
1755
|
const issuedFiles = new Set(issues.map((i) => i.file));
|
|
@@ -1733,6 +1765,14 @@ ${filesBlock}`,
|
|
|
1733
1765
|
const goal = activeGoals[issue.goalIndex];
|
|
1734
1766
|
const confidence = Math.min(100, Math.max(0, issue.confidence ?? 80));
|
|
1735
1767
|
const fixId = `fix-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1768
|
+
console.debug("[AI Watcher] Goal violation detected:", {
|
|
1769
|
+
goalDescription: goal.description,
|
|
1770
|
+
file: issue.file,
|
|
1771
|
+
violation: issue.description,
|
|
1772
|
+
confidence,
|
|
1773
|
+
goalIndex: issue.goalIndex,
|
|
1774
|
+
totalActiveGoals: activeGoals.length
|
|
1775
|
+
});
|
|
1736
1776
|
const ledgerIssue = {
|
|
1737
1777
|
id: fixId,
|
|
1738
1778
|
hash: "",
|
|
@@ -1752,6 +1792,11 @@ ${filesBlock}`,
|
|
|
1752
1792
|
await recordGoalViolationCaught(goal, issue.file, projectPath);
|
|
1753
1793
|
const confidenceStr = `${confidence}%`;
|
|
1754
1794
|
const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description} [${confidenceStr} confidence]`;
|
|
1795
|
+
console.debug("[AI Watcher] Sending nudge:", {
|
|
1796
|
+
message: nudgeMsg,
|
|
1797
|
+
file: issue.file,
|
|
1798
|
+
severity: "warning"
|
|
1799
|
+
});
|
|
1755
1800
|
getOutputManager().nudge(nudgeMsg, "warning", issue.file);
|
|
1756
1801
|
this.state.nudges.push({
|
|
1757
1802
|
file: basename2(issue.file),
|
|
@@ -1828,6 +1873,56 @@ ${filesBlock}`,
|
|
|
1828
1873
|
this.state.autoScanInProgress = false;
|
|
1829
1874
|
}
|
|
1830
1875
|
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Initial hypothesis generation when watch starts.
|
|
1878
|
+
*
|
|
1879
|
+
* This generates hypotheses from existing patterns and issues to give
|
|
1880
|
+
* users immediate insights about their codebase.
|
|
1881
|
+
*/
|
|
1882
|
+
async initialHypothesisGeneration() {
|
|
1883
|
+
if (!isAIAvailable()) {
|
|
1884
|
+
console.debug("[Initial Hypothesis] AI not available, skipping initial hypothesis generation");
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
1888
|
+
console.debug("[Initial Hypothesis] Starting initial hypothesis generation", { projectPath });
|
|
1889
|
+
try {
|
|
1890
|
+
const { getHypothesisEngine } = await import("./hypothesis-HFYZNIMZ.js");
|
|
1891
|
+
const hypothesisEngine = getHypothesisEngine(projectPath);
|
|
1892
|
+
console.debug("[Initial Hypothesis] Running AI-powered hypothesis generation...");
|
|
1893
|
+
const generated = await hypothesisEngine.generateHypothesesWithAI({
|
|
1894
|
+
recentIssues: [],
|
|
1895
|
+
// No recent issues yet on startup
|
|
1896
|
+
patterns: [],
|
|
1897
|
+
observations: ["Initial watch session started", "Analyzing codebase for potential patterns"]
|
|
1898
|
+
});
|
|
1899
|
+
console.debug("[Initial Hypothesis] Generated hypotheses on startup:", {
|
|
1900
|
+
count: generated.length,
|
|
1901
|
+
hypotheses: generated.map((h) => ({ statement: h.statement, confidence: h.confidence }))
|
|
1902
|
+
});
|
|
1903
|
+
if (generated.length > 0) {
|
|
1904
|
+
const { getOutputManager: getOutputManager2 } = await import("./output-manager-BOTMXSND.js");
|
|
1905
|
+
const outputManager = getOutputManager2();
|
|
1906
|
+
for (const hypothesis of generated.slice(0, 2)) {
|
|
1907
|
+
const message = `[Initial Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
|
|
1908
|
+
outputManager.nudge(message, "info", void 0, 1e4);
|
|
1909
|
+
if (!isInteractiveMode()) {
|
|
1910
|
+
console.error(` [?] ${message}`);
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
if (this.streamingManager) {
|
|
1914
|
+
this.streamingManager.reportSignalExtraction({
|
|
1915
|
+
decisions: 0,
|
|
1916
|
+
facts: 0,
|
|
1917
|
+
blockers: 0,
|
|
1918
|
+
questions: generated.length
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
} catch (error) {
|
|
1923
|
+
console.debug("[Initial Hypothesis] Failed to generate initial hypotheses:", error);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1831
1926
|
/**
|
|
1832
1927
|
* Initial goal compliance scan when watch starts.
|
|
1833
1928
|
*
|
|
@@ -1843,12 +1938,23 @@ ${filesBlock}`,
|
|
|
1843
1938
|
* 5. Nudge the user about any violations found
|
|
1844
1939
|
*/
|
|
1845
1940
|
async initialGoalComplianceScan() {
|
|
1846
|
-
if (!isAIAvailable())
|
|
1941
|
+
if (!isAIAvailable()) {
|
|
1942
|
+
console.debug("[Initial Scan] AI not available, skipping initial goal compliance scan");
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1847
1945
|
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
1946
|
+
console.debug("[Initial Scan] Starting initial goal compliance scan", { projectPath });
|
|
1848
1947
|
try {
|
|
1849
|
-
const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-
|
|
1948
|
+
const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-CKFKJ46J.js");
|
|
1850
1949
|
const activeGoals = await getActiveGoals(projectPath);
|
|
1851
|
-
|
|
1950
|
+
console.debug("[Initial Scan] Loaded goals for initial scan:", {
|
|
1951
|
+
goalCount: activeGoals.length,
|
|
1952
|
+
goals: activeGoals.map((g) => ({ id: g.id, description: g.description }))
|
|
1953
|
+
});
|
|
1954
|
+
if (activeGoals.length === 0) {
|
|
1955
|
+
console.debug("[Initial Scan] No active goals found, skipping initial scan");
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1852
1958
|
if (!isInteractiveMode()) {
|
|
1853
1959
|
console.error("[*] Checking recent files against active goals...");
|
|
1854
1960
|
}
|
|
@@ -1866,7 +1972,17 @@ ${filesBlock}`,
|
|
|
1866
1972
|
const ext = extname3(file).toLowerCase();
|
|
1867
1973
|
return WATCH_EXTENSIONS.has(ext) && existsSync3(file);
|
|
1868
1974
|
});
|
|
1869
|
-
|
|
1975
|
+
console.debug("[Initial Scan] Files discovered for initial scan:", {
|
|
1976
|
+
totalRecentFiles: recentFiles.size,
|
|
1977
|
+
filteredFiles: filesToCheck.length,
|
|
1978
|
+
filePaths: filesToCheck.slice(0, 5).map((f) => f.replace(projectPath + "/", "")),
|
|
1979
|
+
// Show first 5
|
|
1980
|
+
watchedExtensions: Array.from(WATCH_EXTENSIONS)
|
|
1981
|
+
});
|
|
1982
|
+
if (filesToCheck.length === 0) {
|
|
1983
|
+
console.debug("[Initial Scan] No recent files found for initial scan");
|
|
1984
|
+
return;
|
|
1985
|
+
}
|
|
1870
1986
|
const maxInitialFiles = 10;
|
|
1871
1987
|
const filesToScan = filesToCheck.slice(0, maxInitialFiles);
|
|
1872
1988
|
if (!isInteractiveMode()) {
|
|
@@ -2047,7 +2163,7 @@ Use \`trie_watch start\` to begin autonomous scanning.`
|
|
|
2047
2163
|
).join("\n");
|
|
2048
2164
|
let agencyStatus = "";
|
|
2049
2165
|
try {
|
|
2050
|
-
const { getGuardian } = await import("./guardian-agent-
|
|
2166
|
+
const { getGuardian } = await import("./guardian-agent-5QVLDPKB.js");
|
|
2051
2167
|
const trieAgent = getGuardian(this.watchedDirectory || getWorkingDirectory(void 0, true));
|
|
2052
2168
|
await trieAgent.initialize();
|
|
2053
2169
|
const status = await trieAgent.getAgencyStatus();
|
|
@@ -3845,21 +3961,25 @@ async function listInstalledSkills() {
|
|
|
3845
3961
|
|
|
3846
3962
|
// src/server/resource-manager.ts
|
|
3847
3963
|
var UI_APPS = {
|
|
3848
|
-
"
|
|
3849
|
-
name: "
|
|
3850
|
-
description: "
|
|
3964
|
+
"ledger": {
|
|
3965
|
+
name: "Decision Ledger",
|
|
3966
|
+
description: "Track decisions, blockers, facts, and questions across your project"
|
|
3967
|
+
},
|
|
3968
|
+
"goals": {
|
|
3969
|
+
name: "Goals & Progress",
|
|
3970
|
+
description: "Monitor code quality goals and track progress with visual indicators"
|
|
3851
3971
|
},
|
|
3852
|
-
"
|
|
3853
|
-
name: "
|
|
3854
|
-
description: "
|
|
3972
|
+
"hypotheses": {
|
|
3973
|
+
name: "Hypotheses",
|
|
3974
|
+
description: "Test and validate development theories with evidence-based reasoning"
|
|
3855
3975
|
},
|
|
3856
|
-
"
|
|
3857
|
-
name: "
|
|
3858
|
-
description: "
|
|
3976
|
+
"nudges": {
|
|
3977
|
+
name: "Nudges & Insights",
|
|
3978
|
+
description: "AI-powered code quality insights, warnings, and suggestions"
|
|
3859
3979
|
},
|
|
3860
|
-
"
|
|
3861
|
-
name: "
|
|
3862
|
-
description: "
|
|
3980
|
+
"chat": {
|
|
3981
|
+
name: "AI Chat",
|
|
3982
|
+
description: "Interactive chat with Trie assistant for code analysis and guidance"
|
|
3863
3983
|
}
|
|
3864
3984
|
};
|
|
3865
3985
|
var ResourceManager = class {
|