@lisa.ai/agent 1.1.7 → 1.1.10

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.
@@ -44,11 +44,38 @@ const telemetry_service_1 = require("../services/telemetry.service");
44
44
  async function coverageCommand(command, modelProvider, attempt = 1, maxRetries = 3, projectId = 'local', apiKey) {
45
45
  console.log(`\n[Lisa.ai Coverage] ${command} (Attempt ${attempt}/${maxRetries}) Using Model: ${modelProvider}`);
46
46
  let executionPassed = true;
47
+ const runSilentlyAndIntercept = (cmd, printProgress = false) => {
48
+ return new Promise((resolve, reject) => {
49
+ const parts = cmd.split(' ');
50
+ const childTarget = process.platform === 'win32' ? `${parts[0]}.cmd` : parts[0];
51
+ const childArgs = parts.slice(1);
52
+ const child = (0, child_process_1.spawn)(parts[0], childArgs, { shell: true, stdio: ['ignore', 'pipe', 'pipe'] });
53
+ child.stdout?.on('data', (data) => {
54
+ const text = data.toString();
55
+ if (printProgress) {
56
+ const lines = text.split('\n');
57
+ for (const line of lines) {
58
+ if (line.includes('Executed')) {
59
+ process.stdout.write(line + '\n');
60
+ }
61
+ }
62
+ }
63
+ });
64
+ child.on('close', (code) => {
65
+ if (code === 0) {
66
+ resolve();
67
+ }
68
+ else {
69
+ reject(new Error(`Test process exited with code ${code}`));
70
+ }
71
+ });
72
+ });
73
+ };
47
74
  try {
48
75
  // 1. Run the test command which should ideally produce coverage-summary.json
49
- // Use 'inherit' so that long-running test commands (like Angular/Karma) print their progress
50
- // in real-time directly to the user's terminal instead of appearing frozen.
51
- (0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: 'inherit' });
76
+ // Use the native interceptor to stream the live Karma/Jest progress bar without error spam
77
+ console.log(`[Lisa.ai Coverage] Booting testing framework in the background. This may take a moment...`);
78
+ await runSilentlyAndIntercept(command, true);
52
79
  console.log(`\n✅ [Lisa.ai Coverage] Tests passed successfully on attempt ${attempt}.`);
53
80
  }
54
81
  catch (error) {
@@ -43,9 +43,10 @@ const git_service_1 = require("../services/git.service");
43
43
  const telemetry_service_1 = require("../services/telemetry.service");
44
44
  function isolateTestCommand(globalCommand, targetFile) {
45
45
  const cmd = globalCommand.toLowerCase();
46
- // Angular/Karma
46
+ const parsed = path.parse(targetFile);
47
+ // Karma requires generic glob matching, it frequently fails on direct absolute OS paths from node
47
48
  if (cmd.includes('ng test') || cmd.includes('karma')) {
48
- return `${globalCommand} --include ${targetFile}`;
49
+ return `${globalCommand} --include **/${parsed.base}`;
49
50
  }
50
51
  // Jest/Vitest/Playwright
51
52
  if (cmd.includes('jest') || cmd.includes('vitest') || cmd.includes('playwright')) {
@@ -59,9 +60,46 @@ function isolateTestCommand(globalCommand, targetFile) {
59
60
  }
60
61
  async function healCommand(command, modelProvider, attempt = 1, healedFilePath = null, maxRetries = 3, projectId = 'local', lastFixDetails, apiKey, skipLedger = [], consecutiveFails = 0, failTracker = {}) {
61
62
  console.log(`\n[Lisa.ai Executing] ${command} (Global Engine) Using Model: ${modelProvider}`);
63
+ const runSilentlyAndIntercept = (cmd, printProgress = false) => {
64
+ return new Promise((resolve, reject) => {
65
+ // Split command correctly for cross-platform spawn
66
+ const parts = cmd.split(' ');
67
+ const childTarget = process.platform === 'win32' ? `${parts[0]}.cmd` : parts[0];
68
+ const childArgs = parts.slice(1);
69
+ // If the command doesn't have .cmd but we are on Windows and it fails, wrap it in a shell
70
+ const child = (0, child_process_1.spawn)(parts[0], childArgs, { shell: true, stdio: ['ignore', 'pipe', 'pipe'] });
71
+ let stdoutData = '';
72
+ let stderrData = '';
73
+ child.stdout?.on('data', (data) => {
74
+ const text = data.toString();
75
+ stdoutData += text;
76
+ // [Lisa.ai Stream Interceptor]
77
+ // The user explicitly requested to see the progress bar, but not the gigantic error dumps.
78
+ // We filter the stdout to only print lines containing "Executed" (Karma/Jasmine standard).
79
+ if (printProgress) {
80
+ const lines = text.split('\n');
81
+ for (const line of lines) {
82
+ if (line.includes('Executed')) {
83
+ process.stdout.write(line + '\n');
84
+ }
85
+ }
86
+ }
87
+ });
88
+ child.stderr?.on('data', (data) => {
89
+ stderrData += data.toString();
90
+ });
91
+ child.on('close', (code) => {
92
+ if (code === 0) {
93
+ resolve({ stdout: stdoutData, stderr: stderrData });
94
+ }
95
+ else {
96
+ reject({ message: `Process exited with code ${code}`, stdout: stdoutData, stderr: stderrData });
97
+ }
98
+ });
99
+ });
100
+ };
62
101
  try {
63
- const output = (0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: 'pipe' });
64
- console.log(output);
102
+ await runSilentlyAndIntercept(command, true); // True = stream progress globally
65
103
  console.log(`\n✅ [Lisa.ai Success] Global Command executed successfully.`);
66
104
  if (healedFilePath) {
67
105
  await (0, git_service_1.createPullRequestForHeal)(healedFilePath);
@@ -71,7 +109,7 @@ async function healCommand(command, modelProvider, attempt = 1, healedFilePath =
71
109
  catch (error) {
72
110
  console.log(`\n❌ [Lisa.ai Failure] Global Command failed.`);
73
111
  const errorLog = (error.stderr || '') + '\n' + (error.stdout || '') + '\n' + (error.message || '');
74
- console.error(errorLog);
112
+ // console.error(errorLog); // Suppressed to keep "Pure Magic" CLI clean. Error is parsed abstractly.
75
113
  console.log(`\n[Lisa.ai Auto-Heal] Analyzing errors...`);
76
114
  const filePath = (0, parser_1.extractFilePath)(errorLog, skipLedger, process.cwd());
77
115
  if (!filePath) {
@@ -112,7 +150,7 @@ async function healCommand(command, modelProvider, attempt = 1, healedFilePath =
112
150
  try {
113
151
  // Verify the isolated file silently without exploding the Global terminal with 400 other spec errors
114
152
  console.log(`[Lisa.ai Micro-Heal] Verifying fix with isolated command: ${isolatedCommand}`);
115
- (0, child_process_1.execSync)(isolatedCommand, { encoding: 'utf-8', stdio: 'pipe' });
153
+ await runSilentlyAndIntercept(isolatedCommand, false); // False = completely invisible isolated healing
116
154
  console.log(`✅ [Lisa.ai Micro-Heal] Isolated verification passed for ${filePath}!`);
117
155
  isFixed = true;
118
156
  }
package/dist/index.js CHANGED
@@ -5,6 +5,13 @@ const commander_1 = require("commander");
5
5
  const config_service_1 = require("./services/config.service");
6
6
  const heal_1 = require("./commands/heal");
7
7
  const coverage_1 = require("./commands/coverage");
8
+ function printBanner() {
9
+ const pkg = require('../package.json');
10
+ console.log(`\n======================================================`);
11
+ console.log(`✨ Lisa.ai Agent v${pkg.version} Running... `);
12
+ console.log(` Where pure magic happens! 🪄`);
13
+ console.log(`======================================================\n`);
14
+ }
8
15
  const program = new commander_1.Command();
9
16
  program
10
17
  .name('lisa-agent')
@@ -17,6 +24,7 @@ program
17
24
  .option('-m, --model <provider>', 'LLM provider to use (gemini, claude, openai)', 'gemini')
18
25
  .option('-p, --project-id <id>', 'Control Plane Project ID to fetch dynamic config')
19
26
  .action(async (options) => {
27
+ printBanner();
20
28
  let maxRetries = 3;
21
29
  let model = options.model;
22
30
  let apiKey = undefined;
@@ -44,6 +52,7 @@ program
44
52
  .option('-m, --model <provider>', 'LLM provider to use (gemini, claude, openai)', 'gemini')
45
53
  .option('-p, --project-id <id>', 'Control Plane Project ID to fetch dynamic config')
46
54
  .action(async (options) => {
55
+ printBanner();
47
56
  let maxRetries = 3;
48
57
  let model = options.model;
49
58
  let apiKey = undefined;
@@ -47,8 +47,11 @@ function extractFilePath(errorLog, skipFiles = [], searchDir = process.cwd()) {
47
47
  let match;
48
48
  while ((match = exactErrorRegex.exec(cleanLog)) !== null) {
49
49
  const foundPath = match[1];
50
- if (foundPath && !normalizedSkips.includes(path.resolve(foundPath))) {
51
- return foundPath;
50
+ if (foundPath) {
51
+ const absoluteFoundPath = path.resolve(searchDir, foundPath);
52
+ if (!normalizedSkips.includes(absoluteFoundPath) && fs.existsSync(absoluteFoundPath)) {
53
+ return foundPath;
54
+ }
52
55
  }
53
56
  }
54
57
  // 2. Second Pass (Fallback): Find anything that looks like a source file
@@ -56,8 +59,11 @@ function extractFilePath(errorLog, skipFiles = [], searchDir = process.cwd()) {
56
59
  let fallbackMatch;
57
60
  while ((fallbackMatch = fallbackRegex.exec(cleanLog)) !== null) {
58
61
  const foundPath = fallbackMatch[1];
59
- if (foundPath && !normalizedSkips.includes(path.resolve(foundPath))) {
60
- return foundPath;
62
+ if (foundPath) {
63
+ const absoluteFoundPath = path.resolve(searchDir, foundPath);
64
+ if (!normalizedSkips.includes(absoluteFoundPath) && fs.existsSync(absoluteFoundPath)) {
65
+ return foundPath;
66
+ }
61
67
  }
62
68
  }
63
69
  // 3. Third Pass (Abstract Testing Fallback): Match exported PascalCase symbols
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lisa.ai/agent",
3
- "version": "1.1.7",
3
+ "version": "1.1.10",
4
4
  "description": "Lisa.ai Autonomous CI/CD Worker Agent",
5
5
  "main": "dist/index.js",
6
6
  "bin": {