@lisa.ai/agent 2.2.2 → 2.3.1
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/index.js +141 -109
- package/package.json +6 -4
- package/dist/commands/coverage.js +0 -258
- package/dist/commands/heal.js +0 -277
- package/dist/services/config.service.js +0 -69
- package/dist/services/discovery.service.js +0 -180
- package/dist/services/generator.service.js +0 -84
- package/dist/services/git.service.js +0 -78
- package/dist/services/installer.service.js +0 -60
- package/dist/services/llm.service.js +0 -197
- package/dist/services/telemetry.service.js +0 -60
- package/dist/utils/coverage.parser.js +0 -59
- package/dist/utils/parser.js +0 -174
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.parseCoverageSummary = parseCoverageSummary;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
function parseCoverageSummary(coverageFilePath) {
|
|
40
|
-
const absolutePath = path.resolve(process.cwd(), coverageFilePath);
|
|
41
|
-
if (!fs.existsSync(absolutePath)) {
|
|
42
|
-
throw new Error(`[Lisa.ai Coverage Error] Coverage file not found at ${absolutePath}`);
|
|
43
|
-
}
|
|
44
|
-
const rawData = fs.readFileSync(absolutePath, 'utf-8');
|
|
45
|
-
const summary = JSON.parse(rawData);
|
|
46
|
-
const uncoveredFiles = [];
|
|
47
|
-
for (const [file, metrics] of Object.entries(summary)) {
|
|
48
|
-
if (file === 'total')
|
|
49
|
-
continue;
|
|
50
|
-
// Check if any metric is below 100%
|
|
51
|
-
if (metrics.lines.pct < 100 ||
|
|
52
|
-
metrics.statements.pct < 100 ||
|
|
53
|
-
metrics.functions.pct < 100 ||
|
|
54
|
-
metrics.branches.pct < 100) {
|
|
55
|
-
uncoveredFiles.push(file);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return uncoveredFiles;
|
|
59
|
-
}
|
package/dist/utils/parser.js
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.extractFilePath = extractFilePath;
|
|
37
|
-
const path = __importStar(require("path"));
|
|
38
|
-
const fs = __importStar(require("fs"));
|
|
39
|
-
function extractFilePath(errorLog, skipFiles = [], searchDir = process.cwd()) {
|
|
40
|
-
// Sanitize invisible ANSI color codes (e.g. \x1b[96m) from CLI output logs
|
|
41
|
-
const cleanLog = errorLog.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
|
|
42
|
-
// Normalize skip files for reliable absolute path comparison
|
|
43
|
-
const normalizedSkips = skipFiles.map(p => path.resolve(p));
|
|
44
|
-
// 1. First Pass: Try to match typical JS/TS/Vue error patterns with line numbers
|
|
45
|
-
// e.g., "src/components/Button.tsx:12:3 - error"
|
|
46
|
-
// Supporting Windows absolute paths (e.g. C:\...)
|
|
47
|
-
const exactErrorRegex = /([a-zA-Z]:[a-zA-Z0-9_.\-\/\\]+\.(?:ts|tsx|js|jsx|vue)|[a-zA-Z0-9_.\-\/\\]+\.(?:ts|tsx|js|jsx|vue))(?:\s*[:(])/g;
|
|
48
|
-
let match;
|
|
49
|
-
while ((match = exactErrorRegex.exec(cleanLog)) !== null) {
|
|
50
|
-
const foundPath = match[1];
|
|
51
|
-
if (foundPath) {
|
|
52
|
-
// Bug 4 fix: skip paths that live inside node_modules or build output directories.
|
|
53
|
-
// Without this check a non-scoped package path (e.g. node_modules/jest-config/build/index.js)
|
|
54
|
-
// satisfies the regex AND exists on disk, so Lisa would attempt to "heal" a library file.
|
|
55
|
-
if (/[/\\](node_modules|dist|build)[/\\]/.test(foundPath))
|
|
56
|
-
continue;
|
|
57
|
-
const absoluteFoundPath = path.isAbsolute(foundPath) ? foundPath : path.resolve(searchDir, foundPath);
|
|
58
|
-
if (!normalizedSkips.includes(absoluteFoundPath) && fs.existsSync(absoluteFoundPath)) {
|
|
59
|
-
return foundPath;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// 1.5 Special Pass for Jest Headers (FAIL src/path/to/test.js)
|
|
64
|
-
const jestFailRegex = /FAIL\s+([a-zA-Z0-9_.\-\/\\]+\.(?:ts|tsx|js|jsx|vue))/gi;
|
|
65
|
-
let jestMatch;
|
|
66
|
-
while ((jestMatch = jestFailRegex.exec(cleanLog)) !== null) {
|
|
67
|
-
const foundPath = jestMatch[1];
|
|
68
|
-
const absoluteFoundPath = path.isAbsolute(foundPath) ? foundPath : path.resolve(searchDir, foundPath);
|
|
69
|
-
if (!normalizedSkips.includes(absoluteFoundPath) && fs.existsSync(absoluteFoundPath)) {
|
|
70
|
-
return foundPath;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// 2. Second Pass (Fallback): Find anything that looks like a source file
|
|
74
|
-
// Loosened regex: Doesn't require trailing colon/paren
|
|
75
|
-
const fallbackRegex = /([a-zA-Z]:[a-zA-Z0-9_.\-\/\\]+\.(?:ts|tsx|js|jsx|vue)|[a-zA-Z0-9_.\-\/\\]+\.(?:ts|tsx|js|jsx|vue))/g;
|
|
76
|
-
let fallbackMatch;
|
|
77
|
-
while ((fallbackMatch = fallbackRegex.exec(cleanLog)) !== null) {
|
|
78
|
-
const foundPath = fallbackMatch[1];
|
|
79
|
-
if (foundPath) {
|
|
80
|
-
// Bug 4 fix: same node_modules/dist guard as pass 1.
|
|
81
|
-
if (/[/\\](node_modules|dist|build)[/\\]/.test(foundPath))
|
|
82
|
-
continue;
|
|
83
|
-
const absoluteFoundPath = path.isAbsolute(foundPath) ? foundPath : path.resolve(searchDir, foundPath);
|
|
84
|
-
if (!normalizedSkips.includes(absoluteFoundPath) && fs.existsSync(absoluteFoundPath)) {
|
|
85
|
-
return foundPath;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
// 3. Third Pass (Abstract Testing Fallback): Match exported PascalCase symbols
|
|
90
|
-
// Framework-agnostic. Often testing tools say "Unexpected 'MyButton'" or "Chrome 120 MyService FAILED"
|
|
91
|
-
const symbolRegex = /\b([A-Z][a-zA-Z0-9]{3,})\b/g;
|
|
92
|
-
let symbolMatch;
|
|
93
|
-
const searchedSymbols = new Set();
|
|
94
|
-
// Filter out common JS/Browser built-ins and framework generics that are not user files
|
|
95
|
-
const ignoreList = ['Error', 'TypeError', 'SyntaxError', 'ReferenceError', 'RangeError', 'NullInjectorError', 'Object', 'Boolean', 'String', 'Number', 'Array', 'Chrome', 'Windows', 'Linux', 'Macintosh', 'UserContext', 'TestBed', 'Module', 'Unexpected', 'Expected', 'ChromeHeadless', 'Users', 'AppData', 'Local', 'Temp', 'Process', 'Component', 'Validation', 'Directory', 'Configuration', 'Documentation'];
|
|
96
|
-
while ((symbolMatch = symbolRegex.exec(cleanLog)) !== null) {
|
|
97
|
-
const symbolName = symbolMatch[1];
|
|
98
|
-
if (symbolName && !ignoreList.includes(symbolName) && !searchedSymbols.has(symbolName)) {
|
|
99
|
-
searchedSymbols.add(symbolName);
|
|
100
|
-
console.log(`[Lisa.ai Parser] Discovered abstract symbol failure: ${symbolName}. Scanning project tree...`);
|
|
101
|
-
// SEARCH ENTIRE ROOT instead of just 'src/' to support diverse project structures
|
|
102
|
-
const matchedFile = findFileBySymbolName(symbolName, searchDir, normalizedSkips);
|
|
103
|
-
if (matchedFile) {
|
|
104
|
-
// Return path relative to project root
|
|
105
|
-
return path.relative(searchDir, matchedFile);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
// Exhausted all options and couldn't find an un-skipped file
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Recursively walks a directory looking for a source file that strictly exports the target symbol.
|
|
114
|
-
* Designed to bypass test runners omitting absolute script paths in test exceptions.
|
|
115
|
-
* We pass normalizedSkips to ensure we do not return a file that the Agent has explicitly blacklisted.
|
|
116
|
-
*/
|
|
117
|
-
function findFileBySymbolName(symbolName, dir, skipLedgerAbs) {
|
|
118
|
-
if (!fs.existsSync(dir))
|
|
119
|
-
return null;
|
|
120
|
-
const files = fs.readdirSync(dir);
|
|
121
|
-
for (const file of files) {
|
|
122
|
-
const fullPath = path.join(dir, file);
|
|
123
|
-
if (file === 'node_modules' || file === 'dist' || file === 'build' || file === '.git' || file === '.angular')
|
|
124
|
-
continue;
|
|
125
|
-
let stat;
|
|
126
|
-
try {
|
|
127
|
-
stat = fs.statSync(fullPath);
|
|
128
|
-
}
|
|
129
|
-
catch (e) {
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (stat.isDirectory()) {
|
|
133
|
-
const found = findFileBySymbolName(symbolName, fullPath, skipLedgerAbs);
|
|
134
|
-
if (found)
|
|
135
|
-
return found;
|
|
136
|
-
}
|
|
137
|
-
else if (file.match(/\.(ts|tsx|js|jsx|vue)$/)) {
|
|
138
|
-
// We ONLY care if the file natively exports/declares the symbol.
|
|
139
|
-
// We MUST NOT match files that merely `import` the symbol.
|
|
140
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
141
|
-
if (content.includes(`class ${symbolName}`) ||
|
|
142
|
-
content.includes(`function ${symbolName}`) ||
|
|
143
|
-
content.includes(`const ${symbolName}`) ||
|
|
144
|
-
content.includes(`let ${symbolName}`) ||
|
|
145
|
-
content.includes(`exports.${symbolName}`) ||
|
|
146
|
-
content.includes(`module.exports.${symbolName}`)) {
|
|
147
|
-
let targetPath = fullPath;
|
|
148
|
-
// Find standard test extensions dynamically based on ecosystem
|
|
149
|
-
const ext = path.extname(fullPath);
|
|
150
|
-
const base = fullPath.slice(0, -ext.length);
|
|
151
|
-
// Check if a spec/test file already exists for this source code natively
|
|
152
|
-
if (!file.includes('.spec.') && !file.includes('.test.')) {
|
|
153
|
-
const possibleSpecs = [
|
|
154
|
-
`${base}.spec${ext}`,
|
|
155
|
-
`${base}.test${ext}`,
|
|
156
|
-
`${base}.spec.js`,
|
|
157
|
-
`${base}.test.js`
|
|
158
|
-
];
|
|
159
|
-
for (const p of possibleSpecs) {
|
|
160
|
-
if (fs.existsSync(p)) {
|
|
161
|
-
targetPath = p;
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// If the decided file is NOT in the skip ledger, return it.
|
|
167
|
-
if (!skipLedgerAbs.includes(path.resolve(targetPath))) {
|
|
168
|
-
return targetPath;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return null;
|
|
174
|
-
}
|