scai 0.1.85 → 0.1.86

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/CHANGELOG.md CHANGED
@@ -99,4 +99,12 @@ Type handling with the module pipeline
99
99
  • Update .gitignore to ignore Node and build artifacts, editor/IDE files, and project-specific ignores.
100
100
  • Added scripts for building cli, server, and dashboard
101
101
  • Restructure the workspace into 3 modules, cli, dashboard, server
102
- • Improved `askChangelogApproval` to support editing and skipping of changelog entries
102
+ • Improved `askChangelogApproval` to support editing and skipping of changelog entries
103
+
104
+ ## 2025-08-12
105
+
106
+ * Added support for backing up SCAI folder with timestamped directory.
107
+ * Split file processing into logical chunks with logging.
108
+ * Improved commit suggestion generation logic.
109
+ * Removed unnecessary files and updated index.ts to use handleAgentRun instead.
110
+ * Fetch download statistics from NPM API.
@@ -0,0 +1,46 @@
1
+ import fs from 'fs/promises';
2
+ import chalk from 'chalk';
3
+ import { runModulePipeline } from './pipeline/runModulePipeline.js';
4
+ import { normalizePath } from './utils/normalizePath.js';
5
+ import { readConfig } from './config.js';
6
+ import { countTokens, splitCodeIntoChunks } from './utils/splitCodeIntoChunk.js';
7
+ export async function handleAgentRun(filepath, modules) {
8
+ try {
9
+ filepath = normalizePath(filepath);
10
+ const content = await fs.readFile(filepath, 'utf-8');
11
+ const totalTokens = countTokens(content);
12
+ console.log(chalk.blue(`🧮 Total tokens in file:`), chalk.yellow(totalTokens.toString()));
13
+ const config = readConfig();
14
+ const maxTokens = 1500;
15
+ const chunks = splitCodeIntoChunks(content, maxTokens);
16
+ console.log(chalk.magenta(`📦 Split into ${chunks.length} chunks`));
17
+ const processedChunks = [];
18
+ for (const [i, chunk] of chunks.entries()) {
19
+ const chunkTokens = countTokens(chunk);
20
+ if (i === 0) {
21
+ console.log(chalk.cyan(`🔍 Processing ${chunks.length} chunks of file:`), chalk.white(filepath));
22
+ }
23
+ console.log(chalk.gray(` - Chunk ${i + 1} tokens:`), chalk.yellow(chunkTokens.toString()));
24
+ const chunkInput = {
25
+ content: chunk,
26
+ filepath,
27
+ chunkIndex: i,
28
+ chunkCount: chunks.length,
29
+ };
30
+ const response = await runModulePipeline(modules, chunkInput);
31
+ if (!response.content.trim()) {
32
+ throw new Error(`⚠️ Model returned empty result on chunk ${i + 1}`);
33
+ }
34
+ processedChunks.push(response.content);
35
+ console.log(chalk.green(`✅ Finished chunk ${i + 1}/${chunks.length}`));
36
+ }
37
+ // Join all chunk outputs into one string
38
+ const finalOutput = processedChunks.join('\n\n');
39
+ // Overwrite original file here:
40
+ await fs.writeFile(filepath, finalOutput, 'utf-8');
41
+ console.log(chalk.green(`✅ Original file overwritten: ${filepath}`));
42
+ }
43
+ catch (err) {
44
+ console.error(chalk.red('❌ Error in agent run:'), err instanceof Error ? err.message : err);
45
+ }
46
+ }
package/dist/db/backup.js CHANGED
@@ -1,28 +1,40 @@
1
- import fsp from 'fs/promises';
1
+ // src/db/backup.ts
2
+ import fs from 'fs';
2
3
  import path from 'path';
3
- import { SCAI_HOME } from '../constants.js';
4
- function getBackupDir() {
5
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
6
- return path.join(SCAI_HOME, `backup-${timestamp}`);
7
- }
4
+ import os from 'os';
8
5
  export async function backupScaiFolder() {
9
- const backupDir = getBackupDir();
10
6
  try {
11
- await fsp.mkdir(backupDir, { recursive: true });
12
- const files = await fsp.readdir(SCAI_HOME);
13
- for (const file of files) {
14
- const srcPath = path.join(SCAI_HOME, file);
15
- const destPath = path.join(backupDir, file);
16
- const stat = await fsp.stat(srcPath);
17
- if (stat.isFile()) {
18
- await fsp.copyFile(srcPath, destPath);
19
- }
7
+ const homeDir = os.homedir();
8
+ const scaiDir = path.join(homeDir, '.scai');
9
+ // Ensure the .scai folder exists
10
+ if (!fs.existsSync(scaiDir)) {
11
+ console.error(`⚠️ No .scai folder found at ${scaiDir}`);
12
+ return false;
20
13
  }
21
- console.log(`📦 Backed up .scai folder to: ${backupDir}`);
22
- return backupDir;
14
+ // Backup path: ~/.scai_backup_<timestamp>
15
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
16
+ const backupDir = path.join(homeDir, `.scai_backup_${timestamp}`);
17
+ // Recursive copy
18
+ copyRecursiveSync(scaiDir, backupDir);
19
+ return true;
23
20
  }
24
21
  catch (err) {
25
- console.warn('⚠️ Failed to back up .scai folder:', err instanceof Error ? err.message : err);
26
- return null;
22
+ console.error(`⚠️ Failed to back up .scai folder:`, err);
23
+ return false;
24
+ }
25
+ }
26
+ function copyRecursiveSync(src, dest) {
27
+ const stats = fs.statSync(src);
28
+ if (stats.isDirectory()) {
29
+ fs.mkdirSync(dest, { recursive: true });
30
+ const entries = fs.readdirSync(src);
31
+ for (const entry of entries) {
32
+ const srcPath = path.join(src, entry);
33
+ const destPath = path.join(dest, entry);
34
+ copyRecursiveSync(srcPath, destPath);
35
+ }
36
+ }
37
+ else {
38
+ fs.copyFileSync(src, dest);
27
39
  }
28
40
  }
package/dist/index.js CHANGED
@@ -5,8 +5,6 @@ const { version } = require('../package.json');
5
5
  import { Command } from "commander";
6
6
  import { Config } from './config.js';
7
7
  import { suggestCommitMessage } from "./commands/CommitSuggesterCmd.js";
8
- import { handleRefactor } from "./commands/RefactorCmd.js";
9
- import { generateTests } from "./commands/TestGenCmd.js";
10
8
  import { bootstrap } from './modelSetup.js';
11
9
  import { summarizeFile } from "./commands/SummaryCmd.js";
12
10
  import { handleStandaloneChangelogUpdate } from './commands/ChangeLogUpdateCmd.js';
@@ -28,6 +26,10 @@ import { runInteractiveSwitch } from "./commands/SwitchCmd.js";
28
26
  import { execSync } from "child_process";
29
27
  import { fileURLToPath } from "url";
30
28
  import { dirname, resolve } from "path";
29
+ import { handleAgentRun } from './agentManager.js';
30
+ import { addCommentsModule } from './pipeline/modules/commentModule.js';
31
+ import { generateTestsModule } from './pipeline/modules/generateTestsModule.js';
32
+ import { cleanupModule } from './pipeline/modules/cleanupModule.js';
31
33
  // 🎛️ CLI Setup
32
34
  const cmd = new Command('scai')
33
35
  .version(version)
@@ -103,8 +105,9 @@ const gen = cmd.command('gen').description('Generate code-related output');
103
105
  gen
104
106
  .command('comm <file>')
105
107
  .description('Write comments for the given file')
106
- .option('-a, --apply', 'Apply the refactored version to the original file')
107
- .action((file, options) => handleRefactor(file, options));
108
+ .action((file) => {
109
+ handleAgentRun(file, [addCommentsModule, cleanupModule]);
110
+ });
108
111
  gen
109
112
  .command('changelog')
110
113
  .description('Update or create the CHANGELOG.md based on current Git diff')
@@ -116,9 +119,12 @@ gen
116
119
  .description('Print a summary of the given file to the terminal')
117
120
  .action((file) => summarizeFile(file));
118
121
  gen
119
- .command('tests <file>')
120
- .description('Generate a Jest test file for the specified JS/TS module')
121
- .action((file) => generateTests(file));
122
+ .command('testgen <file>')
123
+ .description('Generate tests for the given file')
124
+ .option('-a, --apply', 'Apply the output to the original file')
125
+ .action((file) => {
126
+ handleAgentRun(file, [generateTestsModule]);
127
+ });
122
128
  // ⚙️ Group: Configuration settings
123
129
  const config = cmd.command('config').description('Manage SCAI configuration');
124
130
  config
@@ -1,42 +1,90 @@
1
- function isNaturalLanguageNoise(line) {
2
- const trimmed = line.trim().toLowerCase();
3
- return (trimmed.startsWith('i ') ||
4
- trimmed.startsWith('here') ||
5
- trimmed.startsWith('this') ||
6
- trimmed.startsWith('the following') ||
7
- trimmed.startsWith('below') ||
8
- trimmed.startsWith('in this') ||
9
- trimmed.startsWith('we have') ||
10
- trimmed.includes('the code above') ||
11
- trimmed.includes('ensures that') ||
12
- trimmed.includes('it handles') ||
13
- trimmed.includes('used to'));
1
+ import chalk from 'chalk';
2
+ function isTopOrBottomNoise(line) {
3
+ const trimmed = line.trim();
4
+ if (/^```(?:\w+)?$/.test(trimmed))
5
+ return true;
6
+ if (/^<!--.*-->$/.test(trimmed))
7
+ return true;
8
+ const lower = trimmed.toLowerCase();
9
+ if (!trimmed.startsWith('//') && !trimmed.startsWith('/*')) {
10
+ return [
11
+ /^i\s/i,
12
+ /^here/,
13
+ /^this/,
14
+ /^the following/,
15
+ /^below/,
16
+ /^in this/,
17
+ /^we have/,
18
+ /the code above/,
19
+ /ensures that/,
20
+ /it handles/,
21
+ /used to/,
22
+ /note that/,
23
+ /example/,
24
+ /summary/,
25
+ /added comments/,
26
+ ].some(pattern => pattern.test(lower));
27
+ }
28
+ return false;
14
29
  }
15
30
  export const cleanupModule = {
16
31
  name: 'cleanup',
17
- description: 'Remove markdown fences and natural language noise from top/bottom of code',
18
- async run({ content }) {
19
- let lines = content.trim().split('\n');
20
- // ───── Clean top ─────
21
- while (lines.length) {
22
- const line = lines[0].trim();
23
- if (line === '' || line.startsWith('```') || isNaturalLanguageNoise(line)) {
24
- lines.shift();
25
- }
26
- else {
27
- break;
28
- }
32
+ description: 'Remove markdown fences and fluff from top/bottom of each chunk with colored logging',
33
+ async run(input) {
34
+ // Normalize line endings to \n to avoid issues with \r\n
35
+ let content = input.content.replace(/\r\n/g, '\n');
36
+ let lines = content.split('\n');
37
+ // --- CLEAN TOP ---
38
+ // Remove noise lines before the first triple tick or end
39
+ while (lines.length && (lines[0].trim() === '' || isTopOrBottomNoise(lines[0]))) {
40
+ if (/^```(?:\w+)?$/.test(lines[0].trim()))
41
+ break; // Stop if opening fence found
42
+ console.log(chalk.red(`[cleanupModule] Removing noise from top:`), chalk.yellow(`"${lines[0].trim()}"`));
43
+ lines.shift();
29
44
  }
30
- // ───── Clean bottom ─────
31
- while (lines.length) {
32
- const line = lines[lines.length - 1].trim();
33
- if (line === '' || line.startsWith('```') || isNaturalLanguageNoise(line)) {
34
- lines.pop();
45
+ // If opening fence found at top, find matching closing fence
46
+ if (lines.length && /^```(?:\w+)?$/.test(lines[0].trim())) {
47
+ console.log(chalk.red(`[cleanupModule] Found opening fenced block at top.`));
48
+ // Remove opening fence line
49
+ lines.shift();
50
+ // Find closing fence index
51
+ let closingIndex = -1;
52
+ for (let i = 0; i < lines.length; i++) {
53
+ if (/^```(?:\w+)?$/.test(lines[i].trim())) {
54
+ closingIndex = i;
55
+ break;
56
+ }
57
+ }
58
+ if (closingIndex !== -1) {
59
+ console.log(chalk.red(`[cleanupModule] Found closing fenced block at line ${closingIndex + 1}, removing fence lines.`));
60
+ // Remove closing fence line
61
+ lines.splice(closingIndex, 1);
35
62
  }
36
63
  else {
37
- break;
64
+ console.log(chalk.yellow(`[cleanupModule] No closing fenced block found, only removed opening fence.`));
38
65
  }
66
+ // NO removal of noise lines after fenced block here (to keep new comments intact)
67
+ }
68
+ // --- CLEAN BOTTOM ---
69
+ // If closing fence found at bottom, remove only that triple tick line
70
+ if (lines.length && /^```(?:\w+)?$/.test(lines[lines.length - 1].trim())) {
71
+ console.log(chalk.red(`[cleanupModule] Removing closing fenced block line at bottom.`));
72
+ lines.pop();
39
73
  }
74
+ // Remove noise lines after closing fence (now bottom)
75
+ while (lines.length && (lines[lines.length - 1].trim() === '' || isTopOrBottomNoise(lines[lines.length - 1]))) {
76
+ console.log(chalk.red(`[cleanupModule] Removing noise from bottom after fenced block:`), chalk.yellow(`"${lines[lines.length - 1].trim()}"`));
77
+ lines.pop();
78
+ }
79
+ // --- FINAL CLEANUP: REMOVE ANY LINGERING TRIPLE TICK LINES ANYWHERE ---
80
+ lines = lines.filter(line => {
81
+ const trimmed = line.trim();
82
+ if (/^```(?:\w+)?$/.test(trimmed)) {
83
+ console.log(chalk.red(`[cleanupModule] Removing lingering triple tick line:`), chalk.yellow(`"${line}"`));
84
+ return false;
85
+ }
86
+ return true;
87
+ });
40
88
  return { content: lines.join('\n').trim() };
41
89
  }
42
90
  };
@@ -2,7 +2,7 @@ import { Config } from '../../config.js';
2
2
  import { generate } from '../../lib/generate.js';
3
3
  import { detectFileType } from '../../fileRules/detectFileType.js';
4
4
  export const addCommentsModule = {
5
- name: 'addComments',
5
+ name: 'comments',
6
6
  description: 'Adds meaningful comments to any file type (code, config, or data)',
7
7
  async run(input) {
8
8
  const model = Config.getModel();
@@ -37,23 +37,37 @@ export const addCommentsModule = {
37
37
  text: '#',
38
38
  };
39
39
  const commentSyntax = commentMap[fileType] || '//';
40
+ const chunkLabel = (input.chunkIndex && input.chunkCount && input.chunkCount > 1)
41
+ ? `CHUNK ${input.chunkIndex + 1}/${input.chunkCount} of ${input.filepath}`
42
+ : `FULL FILE: ${input.filepath}`;
40
43
  const prompt = `
41
44
  You are a senior engineer reviewing a ${fileType} file.
42
45
 
43
- Your task is to add clear, helpful, and accurate comments using "${commentSyntax}" syntax.
44
- This applies to *every* section where an explanation could help — even for simple code or configuration.
46
+ Please:
47
+
48
+ 1. Add a concise summary comment above each function describing its purpose.
49
+ - Do NOT write trivial summaries like "..." or empty comments.
50
+ - Do NOT overwrite or remove any existing comments.
51
+
52
+ 2. Add clear, helpful inline comments to explain non-obvious logic inside functions.
53
+ - Preserve all existing comments as-is.
54
+
55
+ 3. Use "${commentSyntax}" as the comment syntax appropriate for ${fileType}.
56
+
57
+ 4. Preserve all original formatting, whitespace, and code exactly.
45
58
 
46
59
  Rules:
47
- - Always return the full original file with comments added.
48
- - Preserve all formatting, whitespace, and code exactly.
49
- - Use only "${commentSyntax}" comments that are valid for ${fileType}.
50
- - Do not wrap the output in markdown or code fences.
60
+ - Return the full original chunk of code with added comments only.
61
+ - Do NOT remove, change, or overwrite any existing code or comments.
62
+ - Summaries should be brief but meaningful.
63
+ - Inline comments should clarify complex or tricky parts only.
51
64
 
52
- --- FILE START ---
65
+ --- ${chunkLabel} START ---
53
66
  ${input.content}
54
- --- FILE END ---
67
+ --- ${chunkLabel} END ---
55
68
  `.trim();
56
69
  const response = await generate({ content: prompt }, model);
57
- return { content: response.content === 'NO UPDATE' ? '' : response.content };
70
+ const contentToReturn = (response.content && response.content !== 'NO UPDATE') ? response.content : input.content;
71
+ return { content: contentToReturn };
58
72
  },
59
73
  };
@@ -7,11 +7,17 @@ export const commitSuggesterModule = {
7
7
  const model = Config.getModel();
8
8
  const prompt = `
9
9
  Suggest ALWAYS 3 concise, conventional Git commit messages based on the input code diff.
10
- Use this format ONLY:
11
10
 
12
- 1. feat: ...
13
- 2. fix: ...
14
- 3. refactor: ...
11
+ - Follow the Conventional Commits specification for prefixes (e.g., feat:, fix:, refactor:, docs:, style:, test:, chore:).
12
+ - Choose the most appropriate prefix for each message based on the changes in the diff.
13
+ - Do NOT repeat the same prefix unless it is clearly the most appropriate.
14
+ - Keep each message short, clear, and action-oriented.
15
+
16
+ Format your response exactly as:
17
+
18
+ 1. <type>: <message>
19
+ 2. <type>: <message>
20
+ 3. <type>: <message>
15
21
 
16
22
  Here is the diff:
17
23
  ${content}
@@ -1,10 +1,9 @@
1
- // src/pipeline/modules/generateTestsModule.ts
2
1
  import fs from 'fs/promises';
3
2
  import path from 'path';
4
3
  import { Config } from '../../config.js';
5
4
  import { generate } from '../../lib/generate.js';
6
5
  export const generateTestsModule = {
7
- name: 'generateTests',
6
+ name: 'tests',
8
7
  description: 'Generate a Jest test file for the class/module',
9
8
  async run({ content, filepath }) {
10
9
  const model = Config.getModel();
@@ -8,7 +8,6 @@ export const summaryModule = {
8
8
  const model = Config.getModel();
9
9
  const ext = filepath ? path.extname(filepath).toLowerCase() : '';
10
10
  const filename = filepath ? path.basename(filepath) : '';
11
- // More neutral prompt for general-purpose content
12
11
  const prompt = `
13
12
  You are an assistant specialized in summarizing files.
14
13
 
@@ -16,6 +16,10 @@ const builtInModules = {
16
16
  export function getModuleByName(name) {
17
17
  return builtInModules[name];
18
18
  }
19
+ // Return module metadata for CLI or UI
19
20
  export function listAvailableModules() {
20
- return Object.keys(builtInModules);
21
+ return Object.values(builtInModules).map(({ name, description }) => ({
22
+ name,
23
+ description: description || 'No description available',
24
+ }));
21
25
  }
@@ -1,24 +1,24 @@
1
+ import chalk from 'chalk';
1
2
  export async function runModulePipeline(modules, input) {
2
3
  let current = input;
3
- // Add flag or condition for logging (optional)
4
- const isDebug = false;
5
- if (isDebug) {
6
- console.log('Input: ', input);
7
- }
8
- let response = { content: '' };
4
+ const isDebug = true;
9
5
  for (const mod of modules) {
10
6
  try {
11
- response = await mod.run(current);
12
7
  if (isDebug) {
13
- console.log(`⚙️ Running: ${mod.name}`);
14
- console.log("Current: ", response.content);
8
+ console.log(chalk.green('➡️ Input:', current.content));
9
+ }
10
+ const response = await mod.run(current);
11
+ console.log(`⚙️ Running: ${mod.name}`);
12
+ if (isDebug) {
13
+ console.log(chalk.red('➡️ Output:', response.content));
15
14
  }
15
+ // Feed this output into the next module
16
+ current = response;
16
17
  }
17
18
  catch (error) {
18
19
  console.error(`❌ Error in ${mod.name}:`, error instanceof Error ? error.message : error);
19
20
  throw new Error(`Pipeline failed at module ${mod.name}`);
20
21
  }
21
22
  }
22
- // Return the output, assuming 'code' holds the relevant transformed content
23
- return response; // Ensure the return type matches PromptOutput
23
+ return current;
24
24
  }
@@ -0,0 +1,38 @@
1
+ import { encode } from 'gpt-3-encoder';
2
+ export function splitCodeIntoChunks(text, maxTokens) {
3
+ const lines = text.split('\n');
4
+ const chunks = [];
5
+ let currentChunkLines = [];
6
+ let currentTokens = 0;
7
+ for (const line of lines) {
8
+ const lineTokens = encode(line + '\n').length;
9
+ if (currentTokens + lineTokens > maxTokens) {
10
+ // Try to split at a more natural point
11
+ let splitIndex = currentChunkLines.length;
12
+ for (let i = currentChunkLines.length - 1; i >= 0; i--) {
13
+ const trimmed = currentChunkLines[i].trim();
14
+ if (trimmed === '' ||
15
+ trimmed.startsWith('function ') ||
16
+ trimmed.startsWith('class ') ||
17
+ trimmed.endsWith('}') ||
18
+ trimmed.endsWith(';')) {
19
+ splitIndex = i + 1;
20
+ break;
21
+ }
22
+ }
23
+ chunks.push(currentChunkLines.slice(0, splitIndex).join('\n'));
24
+ // Move leftover lines into the next chunk
25
+ currentChunkLines = currentChunkLines.slice(splitIndex);
26
+ currentTokens = encode(currentChunkLines.join('\n')).length;
27
+ }
28
+ currentChunkLines.push(line);
29
+ currentTokens += lineTokens;
30
+ }
31
+ if (currentChunkLines.length > 0) {
32
+ chunks.push(currentChunkLines.join('\n'));
33
+ }
34
+ return chunks;
35
+ }
36
+ export function countTokens(text) {
37
+ return encode(text).length;
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scai",
3
- "version": "0.1.85",
3
+ "version": "0.1.86",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "scai": "./dist/index.js"
@@ -44,6 +44,7 @@
44
44
  "columnify": "^1.6.0",
45
45
  "commander": "^11.0.0",
46
46
  "fast-glob": "^3.3.3",
47
+ "gpt-3-encoder": "^1.1.4",
47
48
  "proper-lockfile": "^4.1.2",
48
49
  "string-similarity-js": "^2.1.4",
49
50
  "ts-morph": "^26.0.0"
@@ -1,35 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import { runModulePipeline } from '../pipeline/runModulePipeline.js';
4
- import { addCommentsModule } from '../pipeline/modules/commentModule.js';
5
- import { normalizePath } from '../utils/normalizePath.js';
6
- export async function handleRefactor(filepath, options = {}) {
7
- try {
8
- // Normalize and resolve filepath (includes expanding ~ and consistent slashes)
9
- filepath = normalizePath(filepath);
10
- const { dir, name, ext } = path.parse(filepath);
11
- const refactoredPath = path.join(dir, `${name}.refactored${ext}`);
12
- if (options.apply) {
13
- try {
14
- const refactoredCode = await fs.readFile(refactoredPath, 'utf-8');
15
- await fs.writeFile(filepath, refactoredCode, 'utf-8');
16
- await fs.unlink(refactoredPath);
17
- console.log(`♻️ Applied refactor: Overwrote ${filepath} and removed ${refactoredPath}`);
18
- }
19
- catch {
20
- console.error(`❌ No saved refactor found at ${refactoredPath}`);
21
- }
22
- return;
23
- }
24
- const content = await fs.readFile(filepath, 'utf-8');
25
- const response = await runModulePipeline([addCommentsModule], { content });
26
- if (!response.content.trim())
27
- throw new Error('⚠️ Model returned empty result');
28
- await fs.writeFile(refactoredPath, response.content, 'utf-8');
29
- console.log(`✅ Refactored code saved to: ${refactoredPath}`);
30
- console.log(`ℹ️ Run again with '--apply' to overwrite the original.`);
31
- }
32
- catch (err) {
33
- console.error('❌ Error in refactor command:', err instanceof Error ? err.message : err);
34
- }
35
- }
@@ -1,14 +0,0 @@
1
- import fs from 'fs/promises';
2
- import { generateTestsModule } from '../pipeline/modules/generateTestsModule.js';
3
- import { cleanupModule } from '../pipeline/modules/cleanupModule.js';
4
- import { runModulePipeline } from '../pipeline/runModulePipeline.js';
5
- export async function generateTests(filepath) {
6
- try {
7
- const content = await fs.readFile(filepath, 'utf-8');
8
- const result = await runModulePipeline([generateTestsModule, cleanupModule], { content, filepath });
9
- console.log('✅ Test generated and cleaned up.');
10
- }
11
- catch (err) {
12
- console.error('❌ Error generating tests:', err.message);
13
- }
14
- }