@lisa.ai/agent 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,7 +41,7 @@ const parser_1 = require("../utils/parser");
41
41
  const llm_service_1 = require("../services/llm.service");
42
42
  const git_service_1 = require("../services/git.service");
43
43
  const telemetry_service_1 = require("../services/telemetry.service");
44
- async function healCommand(command, modelProvider, attempt = 1, healedFilePath = null, maxRetries = 3, projectId = 'local', lastFixDetails, apiKey) {
44
+ async function healCommand(command, modelProvider, attempt = 1, healedFilePath = null, maxRetries = 3, projectId = 'local', lastFixDetails, apiKey, skipLedger = [], consecutiveFails = 0) {
45
45
  console.log(`\n[Lisa.ai Executing] ${command} (Attempt ${attempt}/${maxRetries}) Using Model: ${modelProvider}`);
46
46
  try {
47
47
  // Execute command synchronously
@@ -53,14 +53,6 @@ async function healCommand(command, modelProvider, attempt = 1, healedFilePath =
53
53
  console.log(`\n✅ [Lisa.ai Success] Command executed successfully on attempt ${attempt}.`);
54
54
  // If we successfully executed and had previously healed a file, PR it
55
55
  if (healedFilePath) {
56
- await (0, telemetry_service_1.reportTelemetry)({
57
- projectId,
58
- type: 'heal',
59
- filePath: healedFilePath,
60
- modelUsed: modelProvider,
61
- status: 'success',
62
- details: lastFixDetails
63
- });
64
56
  await (0, git_service_1.createPullRequestForHeal)(healedFilePath);
65
57
  }
66
58
  }
@@ -74,9 +66,9 @@ async function healCommand(command, modelProvider, attempt = 1, healedFilePath =
74
66
  process.exit(1);
75
67
  }
76
68
  console.log(`\n[Lisa.ai Auto-Heal] Analyzing errors...`);
77
- const filePath = (0, parser_1.extractFilePath)(errorLog);
69
+ const filePath = (0, parser_1.extractFilePath)(errorLog, skipLedger);
78
70
  if (!filePath) {
79
- console.error(`\n🚨 [Lisa.ai Error] Could not parse a valid failing file path from the logs.`);
71
+ console.error(`\n🚨 [Lisa.ai Error] Could not parse a valid failing file path from the logs (or all were explicitly skipped).`);
80
72
  process.exit(1);
81
73
  }
82
74
  const absolutePath = path.resolve(process.cwd(), filePath);
@@ -87,13 +79,33 @@ async function healCommand(command, modelProvider, attempt = 1, healedFilePath =
87
79
  console.log(`[Lisa.ai Auto-Heal] Identified failing file: ${filePath}`);
88
80
  // Read file contents to send to LLM
89
81
  const fileContent = fs.readFileSync(absolutePath, 'utf-8');
82
+ // Increment consecutive fail tracker if this is the exact same file as last time
83
+ let currentFails = (filePath === healedFilePath) ? consecutiveFails + 1 : 1;
84
+ if (currentFails >= 3) {
85
+ console.warn(`\n[Lisa.ai Auto-Heal] ⚠️ Warning: Agent failed to heal ${filePath} after 3 consecutive attempts. It may be missing dependencies. Marking as Skipped.`);
86
+ skipLedger.push(filePath);
87
+ // Immediately retry the loop but force the parser to skip this broken file
88
+ await healCommand(command, modelProvider, attempt + 1, healedFilePath, maxRetries, projectId, lastFixDetails, apiKey, skipLedger, 0);
89
+ return;
90
+ }
91
+ // Pass previous attempted fix if we are stuck in a loop on the same file
92
+ const previousContext = (currentFails > 1) ? lastFixDetails : undefined;
90
93
  // Call LLM for a fix
91
- const fixedCode = await (0, llm_service_1.askLisaForFix)(filePath, fileContent, errorLog, modelProvider, apiKey);
94
+ const fixedCode = await (0, llm_service_1.askLisaForFix)(filePath, fileContent, errorLog, modelProvider, apiKey, previousContext);
92
95
  // Write the fix to the file
93
96
  fs.writeFileSync(absolutePath, fixedCode, 'utf-8');
94
97
  console.log(`[Lisa.ai Auto-Heal] Applied patch to ${filePath}`);
95
- // Recursive retry, passing the healed file path state
96
98
  const generatedDetails = `### Auto-Heal Analysis Triggered\n**Caught Error:**\n\`\`\`bash\n${errorLog}\n\`\`\`\n\n**Applied Fix (${modelProvider}):**\n\`\`\`typescript\n${fixedCode}\n\`\`\``;
97
- await healCommand(command, modelProvider, attempt + 1, filePath, maxRetries, projectId, generatedDetails, apiKey);
99
+ // Dispatch telemetry instantly so the dashboard updates in real-time exactly when the file is patched
100
+ await (0, telemetry_service_1.reportTelemetry)({
101
+ projectId,
102
+ type: 'heal',
103
+ filePath: filePath,
104
+ modelUsed: modelProvider,
105
+ status: 'success',
106
+ details: generatedDetails
107
+ });
108
+ // Recursive retry, passing the healed file path state and updated limits
109
+ await healCommand(command, modelProvider, attempt + 1, filePath, maxRetries, projectId, generatedDetails, apiKey, skipLedger, currentFails);
98
110
  }
99
111
  }
@@ -62,10 +62,10 @@ function getProvider(provider, apiKey) {
62
62
  throw new Error('No Google API key provided by local ENV or Control Plane');
63
63
  return (0, google_1.createGoogleGenerativeAI)({ apiKey: key })('gemini-1.5-pro-latest');
64
64
  }
65
- async function askLisaForFix(filePath, fileContent, errorLog, modelProvider, apiKey) {
65
+ async function askLisaForFix(filePath, fileContent, errorLog, modelProvider, apiKey, previousFixAttempt) {
66
66
  console.log(`[Lisa.ai Auto-Heal] Requesting fix from ${modelProvider} for ${filePath}...`);
67
67
  const model = getProvider(modelProvider, apiKey);
68
- const prompt = `You are Lisa.ai, an autonomous CI/CD expert platform.
68
+ let prompt = `You are Lisa.ai, an autonomous CI/CD expert platform.
69
69
  A build/compilation error occurred. Your task is to fix the provided file so that the error resolves.
70
70
 
71
71
  --- Error Log ---
@@ -79,6 +79,14 @@ ${fileContent}
79
79
  2. Do not suppress TypeScript errors with @ts-ignore or any type assertions unless absolutely unavoidable.
80
80
  3. Fix the underlying type or logic issue.
81
81
  4. Return the code wrapped in a markdown code block (\`\`\`typescript ... \`\`\`). Do not include any explanation or intro text.`;
82
+ if (previousFixAttempt) {
83
+ console.log(`[Lisa.ai Auto-Heal] Warning! Agent is looping on ${filePath}. Injecting previous failed context...`);
84
+ prompt += `\n\n--- CRITICAL WARNING ---\nYou previously attempted to fix this file but the compiler REJECTED your fix!
85
+ Here is the previous analysis and failed fix you attempted:
86
+ ${previousFixAttempt}
87
+
88
+ DO NOT repeat the identical code changes. Try a completely different programming approach, fix syntax typos, or check for missing imports.`;
89
+ }
82
90
  const { text } = await (0, ai_1.generateText)({
83
91
  model,
84
92
  prompt,
@@ -1,20 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extractFilePath = extractFilePath;
4
- function extractFilePath(errorLog) {
4
+ function extractFilePath(errorLog, skipFiles = []) {
5
5
  // Sanitize invisible ANSI color codes (e.g. \x1b[96m) from CLI output logs
6
6
  const cleanLog = errorLog.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
7
- // Matches typical TS/Angular error patterns:
7
+ // 1. First Pass: Try to match typical TS/Angular error patterns
8
8
  // e.g., "src/app/app.component.ts:12:3 - error TS2322:"
9
- // e.g., "Error: src/app/app.component.ts:12:3"
10
- // Try to match path near an error
11
- const tsErrorRegex = /([a-zA-Z0-9_.\-\/\\]+\.ts)(?:[:(])/;
12
- const match = tsErrorRegex.exec(cleanLog);
13
- if (match && match[1]) {
14
- return match[1];
9
+ const tsErrorRegex = /([a-zA-Z0-9_.\-\/\\]+\.ts)(?:[:(])/g;
10
+ let match;
11
+ // Loop through all matches in the error log
12
+ while ((match = tsErrorRegex.exec(cleanLog)) !== null) {
13
+ const foundPath = match[1];
14
+ // If this path is NOT in our skip ledger, we return it as the target
15
+ if (foundPath && !skipFiles.includes(foundPath)) {
16
+ return foundPath;
17
+ }
15
18
  }
16
- // Fallback: Just try to find anything that looks like a .ts file path
17
- const fallbackRegex = /([a-zA-Z0-9_.\-\/\\]+\.ts)/;
18
- const fallbackMatch = fallbackRegex.exec(cleanLog);
19
- return fallbackMatch ? fallbackMatch[1] : null;
19
+ // 2. Second Pass (Fallback): Find anything that looks like a .ts file
20
+ // Note: We use the 'g' flag so we can iterate through multiple matches if the first is skipped
21
+ const fallbackRegex = /([a-zA-Z0-9_.\-\/\\]+\.ts)/g;
22
+ let fallbackMatch;
23
+ while ((fallbackMatch = fallbackRegex.exec(cleanLog)) !== null) {
24
+ const foundPath = fallbackMatch[1];
25
+ if (foundPath && !skipFiles.includes(foundPath)) {
26
+ return foundPath;
27
+ }
28
+ }
29
+ // Exhausted all options and couldn't find an un-skipped file
30
+ return null;
20
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lisa.ai/agent",
3
- "version": "1.0.8",
3
+ "version": "1.1.0",
4
4
  "description": "Lisa.ai Autonomous CI/CD Worker Agent",
5
5
  "main": "dist/index.js",
6
6
  "bin": {