scai 0.1.20 → 0.1.21
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/README.md +108 -83
- package/dist/commands/IndexCmd.js +26 -4
- package/dist/config.js +68 -0
- package/dist/constants.js +19 -0
- package/dist/db/client.js +2 -4
- package/dist/db/fileIndex.js +1 -1
- package/dist/index.js +71 -39
- package/dist/pipeline/modules/changeLogModule.js +2 -2
- package/dist/pipeline/modules/commentModule.js +3 -3
- package/dist/pipeline/modules/commitSuggesterModule.js +2 -2
- package/dist/pipeline/modules/generateTestsModule.js +3 -3
- package/dist/pipeline/modules/refactorModule.js +3 -3
- package/dist/pipeline/modules/summaryModule.js +2 -3
- package/package.json +1 -1
- package/dist/config/ModelConfig.js +0 -23
- /package/dist/{pipeline/types.js → types.js} +0 -0
package/README.md
CHANGED
|
@@ -1,150 +1,175 @@
|
|
|
1
1
|
# ⚙️ scai — Smart Commit AI ✨
|
|
2
2
|
|
|
3
|
-
> AI-powered CLI
|
|
3
|
+
> AI-powered CLI tool for smart commit messages, code comments, summaries, test generation, and changelogs — all powered by local models.
|
|
4
4
|
|
|
5
|
-
**scai** (Smart Commit AI) is a lightweight, privacy-focused CLI tool that
|
|
5
|
+
**scai** (Smart Commit AI) is a lightweight, privacy-focused CLI tool that helps developers work faster and cleaner:
|
|
6
6
|
|
|
7
7
|
- 💬 Suggest high-quality Git commit messages
|
|
8
8
|
- ✨ Automatically comment your code
|
|
9
9
|
- 🧠 Summarize code files instantly in the terminal
|
|
10
|
+
- 🧪 Generate test files for your code (JavaScript/TypeScript)
|
|
10
11
|
- 📝 Generate changelog entries based on Git diffs
|
|
11
|
-
- 🔒 100% local — no API keys, no cloud, no telemetry
|
|
12
|
+
- 🔒 100% local — no API keys, no cloud, no telemetry
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
15
16
|
## 🚀 Features
|
|
16
17
|
|
|
17
|
-
- ⚡️ Powered by local
|
|
18
|
-
- 🛠️
|
|
19
|
-
- 🔒 No external services
|
|
20
|
-
- ✅ Global options
|
|
18
|
+
- ⚡️ Powered by local AI models (e.g., `llama3`, `codellama`)
|
|
19
|
+
- 🛠️ Built with Node.js and TypeScript
|
|
20
|
+
- 🔒 No external services or APIs required
|
|
21
|
+
- ✅ Global options to select model and programming language
|
|
21
22
|
|
|
22
23
|
---
|
|
23
24
|
|
|
24
25
|
## ❤️ Why Local AI?
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
At scai, we believe your code — and your workflow — should stay **yours**. That's why we prioritize **local models** and **privacy-first** development:
|
|
27
28
|
|
|
28
|
-
✅
|
|
29
|
-
✅
|
|
30
|
-
✅
|
|
31
|
-
|
|
29
|
+
- ✅ **Local models**: scai runs entirely on your machine, with no need for cloud-based processing. We use open-source models like `llama3` and `codellama`, ensuring that your code stays private and secure.
|
|
30
|
+
- ✅ **Privacy by design**: We do not send your code to the cloud, store your data, or require API keys. Your data remains 100% local, ensuring full control over your project.
|
|
31
|
+
- ✅ **EU & Danish friendly**: As a Danish company, we are deeply committed to respecting European privacy regulations (GDPR). This means no data collection, no tracking, and full compliance with the strictest data protection laws.
|
|
32
|
+
|
|
33
|
+
By running everything locally, you can be sure that your sensitive code and workflows stay safe, private, and within your control.
|
|
34
|
+
|
|
35
|
+
---
|
|
32
36
|
|
|
33
37
|
## 📦 Installation
|
|
34
38
|
|
|
35
|
-
1. **Install
|
|
39
|
+
1. **Install Ollama:**
|
|
36
40
|
- On **Windows**: [Download Ollama](https://ollama.com/download)
|
|
37
|
-
- On **macOS**:
|
|
38
|
-
- Via Homebrew:
|
|
39
|
-
```bash
|
|
40
|
-
brew install ollama
|
|
41
|
-
```
|
|
42
|
-
- Or download directly from the website
|
|
41
|
+
- On **macOS**: via Homebrew (`brew install ollama`) or [download from Ollama](https://ollama.com)
|
|
43
42
|
|
|
44
|
-
2. **Install scai globally:**
|
|
43
|
+
2. **Install scai globally:**
|
|
44
|
+
```bash
|
|
45
|
+
npm install -g scai
|
|
46
|
+
```
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
3. **Initialize the tool and models:**
|
|
49
|
+
```bash
|
|
50
|
+
scai init
|
|
51
|
+
```
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
This will download required models and set up scai.
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
scai init
|
|
54
|
-
```
|
|
55
|
+
---
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
- Start the Ollama background server
|
|
58
|
-
- Download required models (`llama3`, etc.)
|
|
57
|
+
## ⚒️ Usage Examples
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
### 🔧 Git Commands
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
- **Check Git status (better than `git status`):**
|
|
62
|
+
```bash
|
|
63
|
+
scai git status
|
|
64
|
+
```
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
git add .
|
|
66
|
-
scai sugg
|
|
67
|
-
```
|
|
66
|
+
This is an enhanced version of `git status`. It does more than just show the status of your working directory:
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
```
|
|
68
|
+
- **Check if your working directory is clean**: It tells you if there are any uncommitted changes.
|
|
69
|
+
- **Check your current branch**: It displays your current branch name.
|
|
70
|
+
- **Check if you're up to date with `origin/main`**: Unlike `git status`, which only shows local status, scai ensures you know if your branch is behind or ahead of the `origin/main` branch. It compares your local commit hash with the remote `origin/main` hash, giving you more comprehensive information.
|
|
73
71
|
|
|
74
|
-
|
|
72
|
+
Example output:
|
|
73
|
+
```
|
|
74
|
+
✅ Git working directory is clean
|
|
75
|
+
✅ Up to date with origin/main
|
|
76
|
+
```
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
If you're behind `origin/main`, it will show:
|
|
79
|
+
```
|
|
80
|
+
🔄 Branch <your-branch-name> is not up to date with origin/main
|
|
81
|
+
```
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
- **Suggest a commit message:**
|
|
84
|
+
```bash
|
|
85
|
+
git add .
|
|
86
|
+
scai git sugg
|
|
87
|
+
```
|
|
81
88
|
|
|
82
|
-
|
|
89
|
+
*Example output:*
|
|
90
|
+
```
|
|
91
|
+
feat(api): add error handling to user service
|
|
92
|
+
```
|
|
83
93
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
To commit automatically with the suggestion:
|
|
95
|
+
```bash
|
|
96
|
+
scai git sugg --commit
|
|
97
|
+
```
|
|
87
98
|
|
|
88
|
-
|
|
89
|
-
- `-a, --apply` — Overwrite the original file with the commented version
|
|
99
|
+
### 🛠️ Generate Code-Related Output (`gen` commands)
|
|
90
100
|
|
|
91
|
-
|
|
101
|
+
- **Comment a code file:**
|
|
102
|
+
```bash
|
|
103
|
+
scai gen comm <file>
|
|
104
|
+
```
|
|
92
105
|
|
|
93
|
-
|
|
106
|
+
Adds clear, helpful comments to the code. Optional flag:
|
|
107
|
+
- `-a, --apply` — Overwrite the original file with the commented version.
|
|
94
108
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
- **Summarize a code file:**
|
|
110
|
+
```bash
|
|
111
|
+
scai gen summ <file>
|
|
112
|
+
```
|
|
98
113
|
|
|
99
|
-
Prints a summary of what the code does directly
|
|
114
|
+
Prints a summary of what the code does directly in the terminal. You can also pipe file content:
|
|
115
|
+
```bash
|
|
116
|
+
cat <file> | scai gen summ
|
|
117
|
+
```
|
|
100
118
|
|
|
101
|
-
|
|
119
|
+
- **Generate tests for a code file:**
|
|
120
|
+
```bash
|
|
121
|
+
scai gen tests <file>
|
|
122
|
+
```
|
|
102
123
|
|
|
103
|
-
|
|
104
|
-
cat <file> | scai summ
|
|
105
|
-
```
|
|
124
|
+
Creates a Jest test file for the specified JavaScript/TypeScript module.
|
|
106
125
|
|
|
107
|
-
|
|
126
|
+
- **Update the changelog:**
|
|
127
|
+
```bash
|
|
128
|
+
scai gen changelog
|
|
129
|
+
```
|
|
108
130
|
|
|
109
|
-
|
|
131
|
+
Analyzes the current Git diff and updates (or creates) a `CHANGELOG.md` file with relevant changes.
|
|
110
132
|
|
|
111
|
-
|
|
112
|
-
scai changelog
|
|
113
|
-
```
|
|
133
|
+
## ⚙️ Configuration
|
|
114
134
|
|
|
115
|
-
|
|
135
|
+
scai stores your configuration locally in the `~/.scai/config.json` file. You can configure the model and programming language settings as follows:
|
|
116
136
|
|
|
117
|
-
|
|
137
|
+
- **Set the model:**
|
|
138
|
+
```bash
|
|
139
|
+
scai set model <model>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
e.g., `scai set model codellama:7b`
|
|
143
|
+
|
|
144
|
+
- **Set the programming language:**
|
|
145
|
+
```bash
|
|
146
|
+
scai set lang <lang>
|
|
147
|
+
```
|
|
118
148
|
|
|
119
|
-
|
|
149
|
+
e.g., `scai set lang rust`
|
|
120
150
|
|
|
121
|
-
|
|
151
|
+
- **Show current configuration:**
|
|
152
|
+
```bash
|
|
153
|
+
scai config
|
|
154
|
+
```
|
|
122
155
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
156
|
+
You can also use global options `--model` and `--lang` with any command to override the settings:
|
|
157
|
+
```bash
|
|
158
|
+
scai --model codellama:34b --lang ts git sugg
|
|
159
|
+
```
|
|
127
160
|
|
|
128
|
-
|
|
129
|
-
scai <file> --modules comment,summary > test.txt
|
|
130
|
-
```
|
|
131
|
-
Or to both stdout and a file with tee fx.
|
|
132
|
-
```bash
|
|
133
|
-
scai <file> --modules comment,summary | tee test.txt
|
|
134
|
-
```
|
|
161
|
+
---
|
|
135
162
|
|
|
136
163
|
## 🔐 License & Fair Use
|
|
137
164
|
|
|
138
165
|
**scai is free to use** for individuals, teams, and companies — including in commercial work.
|
|
139
166
|
|
|
140
167
|
You may:
|
|
141
|
-
|
|
142
168
|
- ✅ Use it internally in your projects
|
|
143
169
|
- ✅ Use it at work or in commercial development
|
|
144
170
|
- ✅ Share and recommend it
|
|
145
171
|
|
|
146
172
|
But you may not:
|
|
147
|
-
|
|
148
173
|
- ❌ Repackage or resell **scai** as a product or SaaS
|
|
149
174
|
- ❌ Claim ownership of the tool
|
|
150
175
|
|
|
@@ -6,15 +6,37 @@ import { shouldIgnoreFile } from '../utils/shouldIgnoreFiles.js';
|
|
|
6
6
|
import { detectFileType } from '../utils/detectFileType.js';
|
|
7
7
|
import { runDaemonScheduler } from './DaemonCmd.js';
|
|
8
8
|
import { IGNORED_FOLDER_GLOBS } from '../config/IgnoredPaths.js';
|
|
9
|
+
import { db } from '../db/client.js';
|
|
9
10
|
const IGNORE = [
|
|
10
11
|
'**/node_modules/**', '**/dist/**', '**/build/**',
|
|
11
12
|
'**/coverage/**', '**/.git/**', '**/*.test.*'
|
|
12
13
|
];
|
|
13
14
|
export async function runIndexCommand(targetDir = process.cwd(), options = {}) {
|
|
14
|
-
|
|
15
|
+
const resolvedDir = path.resolve(targetDir);
|
|
16
|
+
console.log(`📂 Indexing files in: ${resolvedDir}`);
|
|
15
17
|
initSchema();
|
|
18
|
+
// 🧠 Check if another directory has already been indexed
|
|
19
|
+
const indexedPaths = db.prepare(`
|
|
20
|
+
SELECT DISTINCT path FROM files LIMIT 100
|
|
21
|
+
`).all();
|
|
22
|
+
const knownRoot = indexedPaths.length > 0
|
|
23
|
+
? path.dirname(indexedPaths[0].path)
|
|
24
|
+
: null;
|
|
25
|
+
if (knownRoot && !resolvedDir.startsWith(knownRoot) && !options.force) {
|
|
26
|
+
console.warn(`⚠️ You're indexing a different folder than before:
|
|
27
|
+
- Previously: ${knownRoot}
|
|
28
|
+
- Now: ${resolvedDir}
|
|
29
|
+
|
|
30
|
+
This will add more files into the existing index and may reduce accuracy or performance.
|
|
31
|
+
|
|
32
|
+
Use --force to continue, or consider clearing the index:
|
|
33
|
+
scai reset-db
|
|
34
|
+
|
|
35
|
+
Aborting.`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
16
38
|
const files = await fg('**/*.*', {
|
|
17
|
-
cwd:
|
|
39
|
+
cwd: resolvedDir,
|
|
18
40
|
ignore: IGNORED_FOLDER_GLOBS,
|
|
19
41
|
absolute: true,
|
|
20
42
|
});
|
|
@@ -28,7 +50,7 @@ export async function runIndexCommand(targetDir = process.cwd(), options = {}) {
|
|
|
28
50
|
indexFile(file, null, type); // empty summary for now
|
|
29
51
|
const ext = path.extname(file);
|
|
30
52
|
countByExt[ext] = (countByExt[ext] || 0) + 1;
|
|
31
|
-
console.log(`📄 Indexed: ${path.relative(
|
|
53
|
+
console.log(`📄 Indexed: ${path.relative(resolvedDir, file)}`);
|
|
32
54
|
count++;
|
|
33
55
|
}
|
|
34
56
|
catch (err) {
|
|
@@ -39,6 +61,6 @@ export async function runIndexCommand(targetDir = process.cwd(), options = {}) {
|
|
|
39
61
|
console.log(`✅ Done. Indexed ${count} files.`);
|
|
40
62
|
if (options.detached) {
|
|
41
63
|
console.log('🚀 Starting summarizer daemon in background mode...');
|
|
42
|
-
runDaemonScheduler();
|
|
64
|
+
runDaemonScheduler();
|
|
43
65
|
}
|
|
44
66
|
}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { CONFIG_PATH, SCAI_HOME, INDEX_DIR } from './constants.js'; // Correctly import INDEX_DIR from constants
|
|
3
|
+
// Default configuration values
|
|
4
|
+
const defaultConfig = {
|
|
5
|
+
model: 'llama3',
|
|
6
|
+
language: 'ts',
|
|
7
|
+
indexDir: INDEX_DIR, // Default index directory from constants
|
|
8
|
+
};
|
|
9
|
+
// Function to ensure the configuration directory exists
|
|
10
|
+
function ensureConfigDir() {
|
|
11
|
+
if (!fs.existsSync(SCAI_HOME)) {
|
|
12
|
+
fs.mkdirSync(SCAI_HOME, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// Function to read the configuration file
|
|
16
|
+
function readConfig() {
|
|
17
|
+
try {
|
|
18
|
+
const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
19
|
+
return { ...defaultConfig, ...JSON.parse(content) };
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return defaultConfig; // Return default config if read fails
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Function to write the configuration to the config file
|
|
26
|
+
function writeConfig(newConfig) {
|
|
27
|
+
ensureConfigDir();
|
|
28
|
+
const current = readConfig();
|
|
29
|
+
const merged = { ...current, ...newConfig };
|
|
30
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(merged, null, 2));
|
|
31
|
+
}
|
|
32
|
+
export const Config = {
|
|
33
|
+
// Get the current model from the config
|
|
34
|
+
getModel() {
|
|
35
|
+
return readConfig().model;
|
|
36
|
+
},
|
|
37
|
+
// Set a new model in the config
|
|
38
|
+
setModel(model) {
|
|
39
|
+
writeConfig({ model });
|
|
40
|
+
console.log(`📦 Model set to: ${model}`);
|
|
41
|
+
},
|
|
42
|
+
// Get the current language from the config
|
|
43
|
+
getLanguage() {
|
|
44
|
+
return readConfig().language;
|
|
45
|
+
},
|
|
46
|
+
// Set a new language in the config
|
|
47
|
+
setLanguage(language) {
|
|
48
|
+
writeConfig({ language });
|
|
49
|
+
console.log(`🗣️ Language set to: ${language}`);
|
|
50
|
+
},
|
|
51
|
+
// Get the index directory from the config
|
|
52
|
+
getIndexDir() {
|
|
53
|
+
return readConfig().indexDir;
|
|
54
|
+
},
|
|
55
|
+
// Set a new index directory in the config
|
|
56
|
+
setIndexDir(indexDir) {
|
|
57
|
+
writeConfig({ indexDir });
|
|
58
|
+
console.log(`📁 Index directory set to: ${indexDir}`);
|
|
59
|
+
},
|
|
60
|
+
// Show the current configuration
|
|
61
|
+
show() {
|
|
62
|
+
const cfg = readConfig();
|
|
63
|
+
console.log(`🔧 Current configuration:`);
|
|
64
|
+
console.log(` Model : ${cfg.model}`);
|
|
65
|
+
console.log(` Language : ${cfg.language}`);
|
|
66
|
+
console.log(` Index dir : ${cfg.indexDir}`);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
export const SCAI_HOME = path.join(os.homedir(), '.scai');
|
|
5
|
+
export const DB_PATH = path.join(SCAI_HOME, 'db.sqlite');
|
|
6
|
+
export const PID_PATH = path.join(SCAI_HOME, 'daemon.pid');
|
|
7
|
+
export const CONFIG_PATH = path.join(SCAI_HOME, 'config.json');
|
|
8
|
+
// Function to read config and get the indexDir on-demand
|
|
9
|
+
export function getIndexDir() {
|
|
10
|
+
try {
|
|
11
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
|
|
12
|
+
return config.indexDir || path.join(os.homedir(), 'defaultIndex'); // Default if not set
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
return path.join(os.homedir(), 'defaultIndex'); // Fallback if no config file
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// On-demand index directory retrieval
|
|
19
|
+
export const INDEX_DIR = getIndexDir();
|
package/dist/db/client.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
|
-
import path from 'path';
|
|
3
2
|
import fs from 'fs';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
|
|
3
|
+
import { DB_PATH, SCAI_HOME } from '../constants.js';
|
|
4
|
+
fs.mkdirSync(SCAI_HOME, { recursive: true });
|
|
7
5
|
export const db = new Database(DB_PATH);
|
package/dist/db/fileIndex.js
CHANGED
|
@@ -17,7 +17,7 @@ export function indexFile(filePath, summary, type) {
|
|
|
17
17
|
// Step 2: Insert into FTS with the same id
|
|
18
18
|
db.prepare(sqlTemplates.insertIntoFtsTemplate).run({ path: filePath, summary });
|
|
19
19
|
}
|
|
20
|
-
export function queryFiles(query, limit =
|
|
20
|
+
export function queryFiles(query, limit = 10) {
|
|
21
21
|
// Sanitize the query by removing or escaping special characters
|
|
22
22
|
const safeQuery = query
|
|
23
23
|
.trim()
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { Config } from './config.js';
|
|
4
5
|
import { createRequire } from 'module';
|
|
5
6
|
const require = createRequire(import.meta.url);
|
|
6
7
|
const { version } = require('../package.json');
|
|
7
|
-
//
|
|
8
|
+
// 🧠 Commands
|
|
8
9
|
import { checkEnv } from "./commands/EnvCmd.js";
|
|
9
10
|
import { checkGit } from "./commands/GitCmd.js";
|
|
10
11
|
import { suggestCommitMessage } from "./commands/CommitSuggesterCmd.js";
|
|
11
12
|
import { handleRefactor } from "./commands/RefactorCmd.js";
|
|
12
13
|
import { generateTests } from "./commands/TestGenCmd.js";
|
|
13
14
|
import { bootstrap } from './modelSetup.js';
|
|
14
|
-
import { ModelConfig } from './config/ModelConfig.js';
|
|
15
15
|
import { summarizeFile } from "./commands/SummaryCmd.js";
|
|
16
16
|
import { handleChangelogUpdate } from './commands/ChangeLogUpdateCmd.js';
|
|
17
17
|
import { runModulePipelineFromCLI } from './commands/ModulePipelineCmd.js';
|
|
@@ -21,12 +21,12 @@ import { runQueryCommand } from './commands/QueryCmd.js';
|
|
|
21
21
|
import { runDaemonBatch } from './commands/DaemonCmd.js';
|
|
22
22
|
import { runStopDaemonCommand } from "./commands/StopDaemonCmd.js";
|
|
23
23
|
import { runAskCommand } from './commands/AskCmd.js';
|
|
24
|
-
//
|
|
24
|
+
// 🎛️ CLI Setup
|
|
25
25
|
const cmd = new Command('scai')
|
|
26
26
|
.version(version)
|
|
27
27
|
.option('--model <model>', 'Set the model to use (e.g., codellama:34b)')
|
|
28
28
|
.option('--lang <lang>', 'Set the target language (ts, java, rust)');
|
|
29
|
-
//
|
|
29
|
+
// 🚀 Init command
|
|
30
30
|
cmd
|
|
31
31
|
.command('init')
|
|
32
32
|
.description('Initialize the model and download required models')
|
|
@@ -34,77 +34,109 @@ cmd
|
|
|
34
34
|
await bootstrap();
|
|
35
35
|
console.log('✅ Model initialization completed!');
|
|
36
36
|
});
|
|
37
|
-
|
|
37
|
+
// 🔧 Group: Git-related commands
|
|
38
|
+
const git = cmd.command('git').description('Git utilities');
|
|
39
|
+
git
|
|
40
|
+
.command('status')
|
|
41
|
+
.description('Check Git status')
|
|
42
|
+
.action(checkGit);
|
|
43
|
+
git
|
|
38
44
|
.command('sugg')
|
|
39
45
|
.description('Suggest a commit message from staged changes')
|
|
40
46
|
.option('-c, --commit', 'Automatically commit with suggested message')
|
|
41
47
|
.action(suggestCommitMessage);
|
|
42
|
-
|
|
48
|
+
// 🛠️ Group: `gen` commands for content generation
|
|
49
|
+
const gen = cmd.command('gen').description('Generate code-related output');
|
|
50
|
+
gen
|
|
43
51
|
.command('comm <file>')
|
|
44
52
|
.description('Write comments for the given file')
|
|
45
53
|
.option('-a, --apply', 'Apply the refactored version to the original file')
|
|
46
54
|
.action((file, options) => handleRefactor(file, options));
|
|
47
|
-
|
|
55
|
+
gen
|
|
48
56
|
.command('changelog')
|
|
49
57
|
.description('Update or create the CHANGELOG.md based on current Git diff')
|
|
50
58
|
.action(async () => {
|
|
51
59
|
await handleChangelogUpdate();
|
|
52
60
|
});
|
|
53
|
-
|
|
61
|
+
gen
|
|
54
62
|
.command('summ [file]')
|
|
55
63
|
.description('Print a summary of the given file to the terminal')
|
|
56
64
|
.action((file) => summarizeFile(file));
|
|
65
|
+
gen
|
|
66
|
+
.command('tests <file>')
|
|
67
|
+
.description('Generate a Jest test file for the specified JS/TS module')
|
|
68
|
+
.action((file) => generateTests(file));
|
|
69
|
+
// 🔍 Indexing
|
|
57
70
|
cmd
|
|
58
|
-
.command('
|
|
59
|
-
.description('
|
|
60
|
-
.
|
|
71
|
+
.command('index [targetDir]')
|
|
72
|
+
.description('Index supported files in the given directory (or current folder if none)')
|
|
73
|
+
.option('-d, --detached', 'Run summarizer daemon after indexing')
|
|
74
|
+
.option('--force', 'Force indexing even if another folder has already been indexed')
|
|
75
|
+
.action((targetDir, options) => {
|
|
76
|
+
const resolvedDir = targetDir ? path.resolve(targetDir) : process.cwd();
|
|
77
|
+
runIndexCommand(resolvedDir, { detached: options.detached, force: options.force });
|
|
78
|
+
});
|
|
79
|
+
// ⚙️ Group: Configuration settings
|
|
80
|
+
const set = cmd.command('set').description('Set configuration values');
|
|
81
|
+
set
|
|
82
|
+
.command('model <model>')
|
|
83
|
+
.description('Set the model to use')
|
|
84
|
+
.action((model) => {
|
|
85
|
+
Config.setModel(model);
|
|
86
|
+
Config.show();
|
|
87
|
+
});
|
|
88
|
+
set
|
|
89
|
+
.command('lang <lang>')
|
|
90
|
+
.description('Set the programming language')
|
|
91
|
+
.action((lang) => {
|
|
92
|
+
Config.setLanguage(lang);
|
|
93
|
+
Config.show();
|
|
94
|
+
});
|
|
95
|
+
set
|
|
96
|
+
.command('index-dir <dir>')
|
|
97
|
+
.description('Set the path to the indexed directory')
|
|
98
|
+
.action((dir) => {
|
|
99
|
+
Config.setIndexDir(path.resolve(dir));
|
|
100
|
+
Config.show();
|
|
101
|
+
});
|
|
102
|
+
// 🧪 Diagnostics and info
|
|
61
103
|
cmd
|
|
62
104
|
.command('env')
|
|
63
105
|
.description('Check environment variables')
|
|
64
106
|
.action(checkEnv);
|
|
65
|
-
cmd
|
|
66
|
-
.command('gen-tests <file>')
|
|
67
|
-
.description('Generate a Jest test file for the specified JS/TS module')
|
|
68
|
-
.action((file) => generateTests(file));
|
|
69
107
|
cmd
|
|
70
108
|
.command('config')
|
|
71
109
|
.description('Show the currently active model and language settings')
|
|
72
110
|
.action(() => {
|
|
73
|
-
|
|
74
|
-
});
|
|
75
|
-
cmd
|
|
76
|
-
.command('daemon')
|
|
77
|
-
.description('Run background summarization of indexed files')
|
|
78
|
-
.action(runDaemonBatch);
|
|
79
|
-
cmd
|
|
80
|
-
.command('stop-daemon')
|
|
81
|
-
.description('Stop the background summarizer daemon')
|
|
82
|
-
.action(runStopDaemonCommand);
|
|
83
|
-
cmd
|
|
84
|
-
.command('index [targetDir]')
|
|
85
|
-
.description('Index supported files in the given directory (or current folder if none)')
|
|
86
|
-
.option('-d, --detached', 'Run summarizer daemon after indexing')
|
|
87
|
-
.action((targetDir, options) => {
|
|
88
|
-
runIndexCommand(targetDir, { detached: options.detached });
|
|
111
|
+
Config.show();
|
|
89
112
|
});
|
|
113
|
+
// 🧠 Query and assistant
|
|
90
114
|
cmd
|
|
91
115
|
.command('query <query>')
|
|
92
116
|
.description('Search indexed files by keyword')
|
|
93
117
|
.action(runQueryCommand);
|
|
94
|
-
// Command structure using Commander
|
|
95
118
|
cmd
|
|
96
119
|
.command('ask')
|
|
97
120
|
.description('Ask a question using file summaries and a local model')
|
|
98
121
|
.argument('<question...>', 'The question to ask')
|
|
99
122
|
.action((question) => {
|
|
100
123
|
const q = question.join(' ');
|
|
101
|
-
runAskCommand(q);
|
|
124
|
+
runAskCommand(q);
|
|
102
125
|
});
|
|
126
|
+
// 🛠️ Background tasks and maintenance
|
|
127
|
+
cmd
|
|
128
|
+
.command('daemon')
|
|
129
|
+
.description('Run background summarization of indexed files')
|
|
130
|
+
.action(runDaemonBatch);
|
|
131
|
+
cmd
|
|
132
|
+
.command('stop-daemon')
|
|
133
|
+
.description('Stop the background summarizer daemon')
|
|
134
|
+
.action(runStopDaemonCommand);
|
|
103
135
|
cmd
|
|
104
136
|
.command('reset-db')
|
|
105
137
|
.description('Delete and reset the SQLite database')
|
|
106
138
|
.action(() => resetDatabase());
|
|
107
|
-
//
|
|
139
|
+
// 🧬 Fallback: Pipeline mode
|
|
108
140
|
cmd
|
|
109
141
|
.arguments('<file>')
|
|
110
142
|
.option('-m, --modules <modules>', 'Comma-separated list of modules to run (e.g., comments,cleanup,summary)')
|
|
@@ -115,11 +147,11 @@ cmd
|
|
|
115
147
|
}
|
|
116
148
|
runModulePipelineFromCLI(file, options);
|
|
117
149
|
});
|
|
118
|
-
// ✅
|
|
150
|
+
// ✅ Parse CLI args
|
|
119
151
|
cmd.parse(process.argv);
|
|
120
|
-
//
|
|
152
|
+
// 🔁 Apply global options post-parse
|
|
121
153
|
const opts = cmd.opts();
|
|
122
154
|
if (opts.model)
|
|
123
|
-
|
|
155
|
+
Config.setModel(opts.model);
|
|
124
156
|
if (opts.lang)
|
|
125
|
-
|
|
157
|
+
Config.setLanguage(opts.lang);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Config } from '../../config.js';
|
|
2
2
|
import { generate } from '../../lib/generate.js';
|
|
3
3
|
export const changelogModule = {
|
|
4
4
|
name: 'changelogModule',
|
|
5
5
|
description: 'Generates changelog entry based on Git diff',
|
|
6
6
|
async run(input) {
|
|
7
|
-
const model =
|
|
7
|
+
const model = Config.getModel();
|
|
8
8
|
const prompt = `
|
|
9
9
|
You're an experienced changelog writer. Based on this Git diff, write a markdown bullet-point entry suitable for CHANGELOG.md:
|
|
10
10
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Config } from '../../config.js';
|
|
2
2
|
import { generate } from '../../lib/generate.js';
|
|
3
3
|
export const addCommentsModule = {
|
|
4
4
|
name: 'addComments',
|
|
5
5
|
description: 'Adds meaningful // comments to each block of code',
|
|
6
6
|
async run(input) {
|
|
7
|
-
const model =
|
|
8
|
-
const lang =
|
|
7
|
+
const model = Config.getModel();
|
|
8
|
+
const lang = Config.getLanguage();
|
|
9
9
|
const prompt = `
|
|
10
10
|
You are a senior ${lang.toUpperCase()} engineer reviewing source code.
|
|
11
11
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { generate } from '../../lib/generate.js';
|
|
2
|
-
import {
|
|
2
|
+
import { Config } from '../../config.js';
|
|
3
3
|
export const commitSuggesterModule = {
|
|
4
4
|
name: 'commitSuggester',
|
|
5
5
|
description: 'Suggests conventional commit messages from Git diff',
|
|
6
6
|
async run({ content }) {
|
|
7
|
-
const model =
|
|
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
10
|
Use this format ONLY:
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// src/pipeline/modules/generateTestsModule.ts
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import {
|
|
4
|
+
import { Config } from '../../config.js';
|
|
5
5
|
import { generate } from '../../lib/generate.js';
|
|
6
6
|
export const generateTestsModule = {
|
|
7
7
|
name: 'generateTests',
|
|
8
8
|
description: 'Generate a Jest test file for the class/module',
|
|
9
9
|
async run({ content, filepath }) {
|
|
10
|
-
const model =
|
|
11
|
-
const lang =
|
|
10
|
+
const model = Config.getModel();
|
|
11
|
+
const lang = Config.getLanguage();
|
|
12
12
|
if (!filepath)
|
|
13
13
|
throw new Error('Missing filepath in pipeline context');
|
|
14
14
|
const prompt = `
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Config } from '../../config.js';
|
|
2
2
|
import { generate } from '../../lib/generate.js';
|
|
3
3
|
export const refactorModule = {
|
|
4
4
|
name: 'refactor',
|
|
5
5
|
description: 'Break code into small, clean functions',
|
|
6
6
|
async run(input) {
|
|
7
|
-
const model =
|
|
8
|
-
const lang =
|
|
7
|
+
const model = Config.getModel();
|
|
8
|
+
const lang = Config.getLanguage();
|
|
9
9
|
const prompt = `
|
|
10
10
|
You are a senior ${lang.toUpperCase()} engineer.
|
|
11
11
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Config } from '../../config.js';
|
|
2
2
|
import { generate } from '../../lib/generate.js';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
export const summaryModule = {
|
|
5
5
|
name: 'summary',
|
|
6
6
|
description: 'Generates a general summary of any file content.',
|
|
7
7
|
run: async ({ content, filepath }) => {
|
|
8
|
-
const model =
|
|
8
|
+
const model = Config.getModel();
|
|
9
9
|
const ext = filepath ? path.extname(filepath).toLowerCase() : '';
|
|
10
10
|
const filename = filepath ? path.basename(filepath) : '';
|
|
11
11
|
// More neutral prompt for general-purpose content
|
|
@@ -36,7 +36,6 @@ ${content}
|
|
|
36
36
|
}
|
|
37
37
|
else {
|
|
38
38
|
console.warn('⚠️ No summary generated.');
|
|
39
|
-
response.summary = '⚠️ No summary generated.';
|
|
40
39
|
}
|
|
41
40
|
return response;
|
|
42
41
|
}
|
package/package.json
CHANGED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export class ModelConfig {
|
|
2
|
-
static setModel(model) {
|
|
3
|
-
this.model = model;
|
|
4
|
-
console.log(`📦 Model set to: ${model}`);
|
|
5
|
-
}
|
|
6
|
-
static getModel() {
|
|
7
|
-
return this.model;
|
|
8
|
-
}
|
|
9
|
-
static setLanguage(lang) {
|
|
10
|
-
this.language = lang;
|
|
11
|
-
console.log(`🗣️ Language set to: ${lang}`);
|
|
12
|
-
}
|
|
13
|
-
static getLanguage() {
|
|
14
|
-
return this.language;
|
|
15
|
-
}
|
|
16
|
-
static logCurrentConfig() {
|
|
17
|
-
console.log(`🔧 Current configuration:`);
|
|
18
|
-
console.log(` Model : ${this.model}`);
|
|
19
|
-
console.log(` Language: ${this.language}`);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
ModelConfig.model = 'llama3';
|
|
23
|
-
ModelConfig.language = 'ts';
|
|
File without changes
|