@lisa.ai/agent 1.1.12 → 2.0.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,27 @@ const coverage_parser_1 = require("../utils/coverage.parser");
41
41
  const llm_service_1 = require("../services/llm.service");
42
42
  const heal_1 = require("./heal");
43
43
  const telemetry_service_1 = require("../services/telemetry.service");
44
+ const discovery_service_1 = require("../services/discovery.service");
45
+ const installer_service_1 = require("../services/installer.service");
46
+ const generator_service_1 = require("../services/generator.service");
44
47
  async function coverageCommand(command, modelProvider, attempt = 1, maxRetries = 3, projectId = 'local', apiKey) {
48
+ // [Lisa.ai V2 Zero-Config Engine]
49
+ if (!command) {
50
+ console.log(`\n[Lisa.ai Auto-Discovery] No explicit --command provided. Initiating Autonomous Framework Fingerprinting...`);
51
+ let fingerprint = discovery_service_1.AutoDiscoveryService.scanRepository();
52
+ if (fingerprint.testingFramework === 'none') {
53
+ fingerprint = await installer_service_1.AutoInstallerService.installMissingFramework(fingerprint);
54
+ await generator_service_1.AutoGeneratorService.provisionConfigurationFiles(fingerprint, modelProvider, apiKey);
55
+ }
56
+ if (fingerprint.suggestedTestCommand) {
57
+ command = fingerprint.suggestedTestCommand;
58
+ console.log(`[Lisa.ai Auto-Discovery] Bootstrapping execution with natively discovered command: ${command}`);
59
+ }
60
+ else {
61
+ console.error(`\n🚨 [Lisa.ai Fatal Error] Agent could not dynamically extrapolate a testing command for a Generic Node Environment. Please pass --command explicitly.`);
62
+ process.exit(1);
63
+ }
64
+ }
45
65
  console.log(`\n[Lisa.ai Coverage] ${command} (Attempt ${attempt}/${maxRetries}) Using Model: ${modelProvider}`);
46
66
  let executionPassed = true;
47
67
  const runSilentlyAndIntercept = (cmd, printProgress = false) => {
@@ -41,6 +41,9 @@ 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
+ const discovery_service_1 = require("../services/discovery.service");
45
+ const installer_service_1 = require("../services/installer.service");
46
+ const generator_service_1 = require("../services/generator.service");
44
47
  function isolateTestCommand(globalCommand, targetFile) {
45
48
  const cmd = globalCommand.toLowerCase();
46
49
  const parsed = path.parse(targetFile);
@@ -91,6 +94,23 @@ function isolateTestCommand(globalCommand, targetFile) {
91
94
  return globalCommand;
92
95
  }
93
96
  async function healCommand(command, modelProvider, attempt = 1, healedFilePath = null, maxRetries = 3, projectId = 'local', lastFixDetails, apiKey, skipLedger = [], consecutiveFails = 0, failTracker = {}) {
97
+ // [Lisa.ai V2 Zero-Config Engine]
98
+ if (!command) {
99
+ console.log(`\n[Lisa.ai Auto-Discovery] No explicit --command provided. Initiating Autonomous Framework Fingerprinting...`);
100
+ let fingerprint = discovery_service_1.AutoDiscoveryService.scanRepository();
101
+ if (fingerprint.testingFramework === 'none') {
102
+ fingerprint = await installer_service_1.AutoInstallerService.installMissingFramework(fingerprint);
103
+ await generator_service_1.AutoGeneratorService.provisionConfigurationFiles(fingerprint, modelProvider, apiKey);
104
+ }
105
+ if (fingerprint.suggestedTestCommand) {
106
+ command = fingerprint.suggestedTestCommand;
107
+ console.log(`[Lisa.ai Auto-Discovery] Bootstrapping execution with natively discovered command: ${command}`);
108
+ }
109
+ else {
110
+ console.error(`\n🚨 [Lisa.ai Fatal Error] Agent could not dynamically extrapolate a testing command for a Generic Node Environment. Please pass --command explicitly.`);
111
+ process.exit(1);
112
+ }
113
+ }
94
114
  console.log(`\n[Lisa.ai Executing] ${command} (Global Engine) Using Model: ${modelProvider}`);
95
115
  const runSilentlyAndIntercept = (cmd, printProgress = false) => {
96
116
  return new Promise((resolve, reject) => {
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ program
20
20
  program
21
21
  .command('heal')
22
22
  .description('Run a command and autonomously heal errors')
23
- .requiredOption('-c, --command <type>', 'Command to execute (e.g. "ng build")')
23
+ .option('-c, --command <type>', 'Command to execute (Optional for Auto-Discovery)')
24
24
  .option('-m, --model <provider>', 'LLM provider to use (gemini, claude, openai)', 'gemini')
25
25
  .option('-p, --project-id <id>', 'Control Plane Project ID to fetch dynamic config')
26
26
  .action(async (options) => {
@@ -48,7 +48,7 @@ program
48
48
  program
49
49
  .command('coverage')
50
50
  .description('Run test command dynamically generating missing specs for 100% coverage')
51
- .requiredOption('-c, --command <type>', 'Test command to execute (e.g. "npm run test")')
51
+ .option('-c, --command <type>', 'Test command to execute (Optional for Auto-Discovery)')
52
52
  .option('-m, --model <provider>', 'LLM provider to use (gemini, claude, openai)', 'gemini')
53
53
  .option('-p, --project-id <id>', 'Control Plane Project ID to fetch dynamic config')
54
54
  .action(async (options) => {
@@ -0,0 +1,93 @@
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.AutoDiscoveryService = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ class AutoDiscoveryService {
40
+ /**
41
+ * Statically analyzes the repository's package.json to generate an architectural fingerprint.
42
+ */
43
+ static scanRepository(projectPath = process.cwd()) {
44
+ const pkgPath = path.resolve(projectPath, 'package.json');
45
+ const result = {
46
+ type: 'unknown',
47
+ testingFramework: 'none'
48
+ };
49
+ if (!fs.existsSync(pkgPath)) {
50
+ console.warn(`[Lisa.ai AutoDiscovery] No package.json found at ${pkgPath}. Defaulting to Generic Node.`);
51
+ result.type = 'node';
52
+ return result;
53
+ }
54
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
55
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
56
+ const scripts = pkg.scripts || {};
57
+ // 1. Detect Core Framework
58
+ if (deps['@angular/core']) {
59
+ result.type = 'angular';
60
+ }
61
+ else if (deps['react']) {
62
+ result.type = 'react';
63
+ }
64
+ else if (deps['vue']) {
65
+ result.type = 'vue';
66
+ }
67
+ else {
68
+ result.type = 'node';
69
+ }
70
+ // 2. Detect Existing Testing Libraries
71
+ if (deps['jest'] || scripts['test']?.includes('jest')) {
72
+ result.testingFramework = 'jest';
73
+ }
74
+ else if (deps['karma'] || scripts['test']?.includes('karma') || scripts['test']?.includes('ng test')) {
75
+ result.testingFramework = 'karma';
76
+ }
77
+ else if (deps['vitest'] || scripts['test']?.includes('vitest')) {
78
+ result.testingFramework = 'vitest';
79
+ }
80
+ // 3. Extrapolate Commands
81
+ if (result.testingFramework !== 'none') {
82
+ if (scripts['test']) {
83
+ result.suggestedTestCommand = 'npm run test';
84
+ }
85
+ else {
86
+ // They have the library but no script; we execute binary directly
87
+ result.suggestedTestCommand = result.testingFramework === 'karma' ? 'npx karma start' : `npx ${result.testingFramework}`;
88
+ }
89
+ }
90
+ return result;
91
+ }
92
+ }
93
+ exports.AutoDiscoveryService = AutoDiscoveryService;
@@ -0,0 +1,84 @@
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.AutoGeneratorService = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const llm_service_1 = require("./llm.service");
40
+ class AutoGeneratorService {
41
+ /**
42
+ * Asks the LLM to write the environment-specific setup files (jest.config.js, setupTests.ts)
43
+ * if the user's framework is missing them.
44
+ */
45
+ static async provisionConfigurationFiles(fingerprint, modelProvider, apiKey, projectPath = process.cwd()) {
46
+ if (fingerprint.testingFramework === 'none')
47
+ return;
48
+ console.log(`\n[Lisa.ai Auto-Generator] šŸŖ„ Analyzing ${fingerprint.type} architecture to generate ${fingerprint.testingFramework} configuration specs...`);
49
+ // Check if config already exists so we don't nuke it maliciously
50
+ const commonConfigs = ['jest.config.js', 'jest.config.ts', 'karma.conf.js', 'vitest.config.ts', 'vitest.config.js'];
51
+ const hasExistingConfig = commonConfigs.some(cfg => fs.existsSync(path.join(projectPath, cfg)));
52
+ if (hasExistingConfig) {
53
+ console.log(`[Lisa.ai Auto-Generator] Setup file detected. Bypassing initialization.`);
54
+ return;
55
+ }
56
+ const prompt = `You are an expert ${fingerprint.type} architect.
57
+ Write a production-ready '${fingerprint.testingFramework}' configuration file for a standard '${fingerprint.type}' application.
58
+ The application resides in the root directory.
59
+
60
+ Requirements:
61
+ 1. Ensure it specifically instruments code coverage.
62
+ 2. Ensure standard transpilation (ts-jest for jest, or standard karma-webpack/karma-typescript implementations).
63
+ 3. Do NOT wrap your response in markdown formatting (no \`\`\`javascript).
64
+ 4. Return ONLY the raw code string block.`;
65
+ try {
66
+ const generatedConfigString = await (0, llm_service_1.askLisaGeneral)(prompt, modelProvider, apiKey);
67
+ let targetFileName = '';
68
+ if (fingerprint.testingFramework === 'jest')
69
+ targetFileName = 'jest.config.js';
70
+ if (fingerprint.testingFramework === 'karma')
71
+ targetFileName = 'karma.conf.js';
72
+ if (fingerprint.testingFramework === 'vitest')
73
+ targetFileName = 'vitest.config.ts';
74
+ const targetFilePath = path.join(projectPath, targetFileName);
75
+ fs.writeFileSync(targetFilePath, generatedConfigString, 'utf-8');
76
+ console.log(`āœ… [Lisa.ai Auto-Generator] Natively wrote ${targetFileName} to repository root.`);
77
+ }
78
+ catch (error) {
79
+ console.error(`\nāŒ [Lisa.ai Auto-Generator] Failed to author configuration file: ${error.message}`);
80
+ process.exit(1);
81
+ }
82
+ }
83
+ }
84
+ exports.AutoGeneratorService = AutoGeneratorService;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AutoInstallerService = void 0;
4
+ const child_process_1 = require("child_process");
5
+ class AutoInstallerService {
6
+ /**
7
+ * Natively executes NPM installation commands if a framework is completely devoid of testing tooling.
8
+ */
9
+ static async installMissingFramework(fingerprint, projectPath = process.cwd()) {
10
+ if (fingerprint.testingFramework !== 'none') {
11
+ return fingerprint; // Already fully equipped
12
+ }
13
+ console.log(`\n[Lisa.ai Auto-Installer] 🚨 No testing framework detected for ${fingerprint.type} architecture.`);
14
+ console.log(`[Lisa.ai Auto-Installer] šŸŖ„ Initiating Zero-Config Installation Protocol...`);
15
+ let installCmd = '';
16
+ let testingTarget = 'none';
17
+ switch (fingerprint.type) {
18
+ case 'angular':
19
+ // Angular historically uses Karma/Jasmine natively, though modern might prefer Jest.
20
+ // We'll provision standard Jasmine/Karma to align with standard Angular builders.
21
+ console.log(`[Lisa.ai Auto-Installer] Provisioning Angular TestBed environment...`);
22
+ installCmd = 'npm install --save-dev karma karma-chrome-launcher karma-coverage karma-jasmine jasmine-core @types/jasmine';
23
+ testingTarget = 'karma';
24
+ fingerprint.suggestedTestCommand = 'npm run test';
25
+ break;
26
+ case 'react':
27
+ case 'node':
28
+ default:
29
+ // Jest is the safest, most ubiquitous generic fallback for React and Node JS.
30
+ console.log(`[Lisa.ai Auto-Installer] Provisioning Universal Jest environment...`);
31
+ installCmd = 'npm install --save-dev jest @types/jest ts-jest';
32
+ testingTarget = 'jest';
33
+ fingerprint.suggestedTestCommand = 'npx jest --coverage';
34
+ break;
35
+ case 'vue':
36
+ // Vitest is the modern standard for Vue 3 / Vite ecosystems
37
+ console.log(`[Lisa.ai Auto-Installer] Provisioning Vue Vitest environment...`);
38
+ installCmd = 'npm install --save-dev vitest @vue/test-utils jsdom';
39
+ testingTarget = 'vitest';
40
+ fingerprint.suggestedTestCommand = 'npx vitest run --coverage';
41
+ break;
42
+ }
43
+ if (installCmd) {
44
+ console.log(`[Lisa.ai Executing] ${installCmd}`);
45
+ const parts = installCmd.split(' ');
46
+ const childTarget = process.platform === 'win32' ? `${parts[0]}.cmd` : parts[0];
47
+ // Execute natively blocking so the repository is fully built before the agent tries to test it
48
+ const result = (0, child_process_1.spawnSync)(childTarget, parts.slice(1), { cwd: projectPath, stdio: 'inherit' });
49
+ if (result.status !== 0) {
50
+ console.error(`\nāŒ [Lisa.ai Auto-Installer] Failed to construct dynamic testing environment.`);
51
+ process.exit(1);
52
+ }
53
+ console.log(`āœ… [Lisa.ai Auto-Installer] Framework successfully injected.`);
54
+ fingerprint.testingFramework = testingTarget;
55
+ return fingerprint;
56
+ }
57
+ return fingerprint;
58
+ }
59
+ }
60
+ exports.AutoInstallerService = AutoInstallerService;
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.askLisaForFix = askLisaForFix;
37
37
  exports.generateTestForFile = generateTestForFile;
38
38
  exports.updateTestForFile = updateTestForFile;
39
+ exports.askLisaGeneral = askLisaGeneral;
39
40
  const ai_1 = require("ai");
40
41
  const openai_1 = require("@ai-sdk/openai");
41
42
  const anthropic_1 = require("@ai-sdk/anthropic");
@@ -142,3 +143,12 @@ ${existingTestContent}
142
143
  const match = text.match(/```(?:typescript|ts|javascript|js)?\n([\s\S]*?)```/);
143
144
  return match ? match[1].trim() : text.trim();
144
145
  }
146
+ async function askLisaGeneral(promptStr, modelProvider, apiKey) {
147
+ const model = getProvider(modelProvider, apiKey);
148
+ const { text } = await (0, ai_1.generateText)({
149
+ model,
150
+ prompt: promptStr,
151
+ });
152
+ const match = text.match(/```(?:typescript|ts|javascript|js)?\n([\s\S]*?)```/);
153
+ return match ? match[1].trim() : text.trim();
154
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lisa.ai/agent",
3
- "version": "1.1.12",
3
+ "version": "2.0.0",
4
4
  "description": "Lisa.ai Autonomous CI/CD Worker Agent",
5
5
  "main": "dist/index.js",
6
6
  "bin": {