scai 0.1.96 → 0.1.97
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 +11 -1
- package/dist/context.js +16 -11
- package/dist/index.js +126 -76
- package/package.json +1 -1
package/dist/CHANGELOG.md
CHANGED
|
@@ -131,4 +131,14 @@ Type handling with the module pipeline
|
|
|
131
131
|
|
|
132
132
|
• Add DB-related commands to db subcommand (check, reset, migrate)
|
|
133
133
|
• Update table view limits for files and functions in dbcheck.ts
|
|
134
|
-
• Improved resetDatabase command with confirmation prompt before deleting database
|
|
134
|
+
• Improved resetDatabase command with confirmation prompt before deleting database
|
|
135
|
+
|
|
136
|
+
## 2025-08-23
|
|
137
|
+
|
|
138
|
+
* Improved CLI configuration settings with context-aware actions
|
|
139
|
+
* Improved logging and added active repo change detection
|
|
140
|
+
|
|
141
|
+
## 2025-08-23
|
|
142
|
+
|
|
143
|
+
* Improved CLI configuration settings with context-aware actions
|
|
144
|
+
* Added CLI configuration settings with context-aware actions and improved logging
|
package/dist/context.js
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
import { readConfig, writeConfig } from "./config.js";
|
|
3
3
|
import { normalizePath } from "./utils/normalizePath.js";
|
|
4
4
|
import { getHashedRepoKey } from "./utils/repoKey.js";
|
|
5
|
-
import { getDbForRepo } from "./db/client.js";
|
|
6
|
-
import path from "path";
|
|
5
|
+
import { getDbForRepo, getDbPathForRepo } from "./db/client.js";
|
|
7
6
|
import fs from "fs";
|
|
8
7
|
import chalk from "chalk";
|
|
9
8
|
export async function updateContext() {
|
|
@@ -11,33 +10,38 @@ export async function updateContext() {
|
|
|
11
10
|
const cfg = readConfig();
|
|
12
11
|
// 🔑 Find repoKey by matching indexDir to cwd
|
|
13
12
|
let repoKey = Object.keys(cfg.repos || {}).find((key) => normalizePath(cfg.repos[key]?.indexDir || "") === cwd);
|
|
14
|
-
//
|
|
13
|
+
// Initialize new repo config if not found
|
|
14
|
+
let isNewRepo = false;
|
|
15
15
|
if (!repoKey) {
|
|
16
16
|
repoKey = getHashedRepoKey(cwd);
|
|
17
17
|
if (!cfg.repos[repoKey])
|
|
18
18
|
cfg.repos[repoKey] = {};
|
|
19
19
|
cfg.repos[repoKey].indexDir = cwd;
|
|
20
|
-
|
|
20
|
+
isNewRepo = true;
|
|
21
21
|
}
|
|
22
|
+
// Check if active repo has changed
|
|
23
|
+
const activeRepoChanged = cfg.activeRepo !== repoKey;
|
|
22
24
|
// Always set this as active repo
|
|
23
25
|
cfg.activeRepo = repoKey;
|
|
24
26
|
writeConfig(cfg);
|
|
25
27
|
const repoCfg = cfg.repos[repoKey];
|
|
26
28
|
let ok = true;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
// Only log detailed info if new repo or active repo changed
|
|
30
|
+
if (isNewRepo || activeRepoChanged) {
|
|
31
|
+
console.log(chalk.yellow("\n🔁 Updating context...\n"));
|
|
32
|
+
console.log(`✅ Active repo: ${chalk.green(repoKey)}`);
|
|
33
|
+
console.log(`✅ Index dir: ${chalk.cyan(repoCfg.indexDir || cwd)}`);
|
|
34
|
+
}
|
|
30
35
|
// GitHub token is optional
|
|
31
36
|
const token = repoCfg.githubToken || cfg.githubToken;
|
|
32
37
|
if (!token) {
|
|
33
38
|
console.log(`ℹ️ No GitHub token found. You can set one with the: ${chalk.bold(chalk.bgGreen("scai auth set"))} command`);
|
|
34
39
|
}
|
|
35
|
-
else {
|
|
40
|
+
else if (isNewRepo || activeRepoChanged) {
|
|
36
41
|
console.log(`✅ GitHub token present`);
|
|
37
42
|
}
|
|
38
43
|
// Ensure DB exists
|
|
39
|
-
const
|
|
40
|
-
const dbPath = path.join(scaiRepoRoot, "db.sqlite");
|
|
44
|
+
const dbPath = getDbPathForRepo();
|
|
41
45
|
if (!fs.existsSync(dbPath)) {
|
|
42
46
|
console.log(chalk.yellow(`📦 Initializing DB at ${dbPath}`));
|
|
43
47
|
try {
|
|
@@ -47,9 +51,10 @@ export async function updateContext() {
|
|
|
47
51
|
ok = false; // DB init failed
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
|
-
else {
|
|
54
|
+
else if (isNewRepo || activeRepoChanged) {
|
|
51
55
|
console.log(chalk.green("✅ Database present"));
|
|
52
56
|
}
|
|
57
|
+
// Final context status
|
|
53
58
|
if (ok) {
|
|
54
59
|
console.log(chalk.bold.green("\n✅ Context OK\n"));
|
|
55
60
|
}
|
package/dist/index.js
CHANGED
|
@@ -53,55 +53,70 @@ git
|
|
|
53
53
|
.description('Review an open pull request using AI')
|
|
54
54
|
.option('-a, --all', 'Show all PRs requiring a review (not just for the current user)', false)
|
|
55
55
|
.action(async (cmd) => {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
await withContext(async () => {
|
|
57
|
+
const showAll = cmd.all;
|
|
58
|
+
await reviewPullRequestCmd('main', showAll);
|
|
59
|
+
});
|
|
58
60
|
});
|
|
59
61
|
git
|
|
60
62
|
.command('commit')
|
|
61
63
|
.description('Suggest a commit message from staged changes and optionally commit')
|
|
62
64
|
.option('-l, --changelog', 'Generate and optionally stage a changelog entry')
|
|
63
|
-
.action((options) =>
|
|
65
|
+
.action(async (options) => {
|
|
66
|
+
await withContext(async () => {
|
|
67
|
+
suggestCommitMessage(options);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
64
70
|
git
|
|
65
71
|
.command('check')
|
|
66
72
|
.description('Check Git working directory and branch status')
|
|
67
|
-
.action(() => {
|
|
68
|
-
|
|
73
|
+
.action(async () => {
|
|
74
|
+
await withContext(async () => {
|
|
75
|
+
checkGit();
|
|
76
|
+
});
|
|
69
77
|
});
|
|
70
78
|
// Add auth-related commands
|
|
71
79
|
const auth = cmd.command('auth').description('GitHub authentication commands');
|
|
80
|
+
// ⚡ Auth commands
|
|
72
81
|
auth
|
|
73
82
|
.command('check')
|
|
74
83
|
.description('Check if GitHub authentication is set up and valid')
|
|
75
84
|
.action(async () => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
await withContext(async () => {
|
|
86
|
+
try {
|
|
87
|
+
const token = Config.getGitHubToken();
|
|
88
|
+
if (!token) {
|
|
89
|
+
console.log('❌ GitHub authentication not found. Please set your token.');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const result = await validateGitHubTokenAgainstRepo();
|
|
93
|
+
console.log(result);
|
|
81
94
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
console.error(typeof err === 'string' ? err : err.message);
|
|
87
|
-
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
console.error(typeof err === 'string' ? err : err.message);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
88
99
|
});
|
|
89
100
|
auth
|
|
90
101
|
.command('reset')
|
|
91
102
|
.description('Reset GitHub authentication credentials')
|
|
92
|
-
.action(() => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
.action(async () => {
|
|
104
|
+
await withContext(async () => {
|
|
105
|
+
Config.setGitHubToken('');
|
|
106
|
+
console.log('🔄 GitHub authentication has been reset.');
|
|
107
|
+
const token = Config.getGitHubToken();
|
|
108
|
+
console.log(token ? '❌ Token still exists in the configuration.' : '✅ Token successfully removed.');
|
|
109
|
+
});
|
|
97
110
|
});
|
|
98
111
|
auth
|
|
99
112
|
.command('set')
|
|
100
113
|
.description('Set your GitHub Personal Access Token')
|
|
101
114
|
.action(async () => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
115
|
+
await withContext(async () => {
|
|
116
|
+
const token = await promptForToken();
|
|
117
|
+
Config.setGitHubToken(token.trim());
|
|
118
|
+
console.log('🔑 GitHub token set successfully.');
|
|
119
|
+
});
|
|
105
120
|
});
|
|
106
121
|
// 🛠️ Group: `gen` commands for content generation
|
|
107
122
|
const gen = cmd.command('gen').description('Generate code-related output');
|
|
@@ -109,43 +124,57 @@ gen
|
|
|
109
124
|
.command("comm <targets...>")
|
|
110
125
|
.description("Write comments for the given file(s) or folder(s)")
|
|
111
126
|
.action(async (targets) => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
127
|
+
await withContext(async () => {
|
|
128
|
+
const files = await resolveTargetsToFiles(targets, [".ts", ".js"]);
|
|
129
|
+
for (const file of files) {
|
|
130
|
+
await handleAgentRun(file, [addCommentsModule, preserveCodeModule]);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
116
133
|
});
|
|
117
134
|
gen
|
|
118
135
|
.command('changelog')
|
|
119
136
|
.description('Update or create the CHANGELOG.md based on current Git diff')
|
|
120
137
|
.action(async () => {
|
|
121
|
-
await
|
|
138
|
+
await withContext(async () => {
|
|
139
|
+
await handleStandaloneChangelogUpdate();
|
|
140
|
+
});
|
|
122
141
|
});
|
|
123
142
|
gen
|
|
124
143
|
.command('summ [file]')
|
|
125
144
|
.description('Print a summary of the given file to the terminal')
|
|
126
|
-
.action((file) =>
|
|
145
|
+
.action(async (file) => {
|
|
146
|
+
await withContext(async () => {
|
|
147
|
+
summarizeFile(file);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
127
150
|
gen
|
|
128
151
|
.command('testgen <file>')
|
|
129
152
|
.description('Generate tests for the given file')
|
|
130
153
|
.option('-a, --apply', 'Apply the output to the original file')
|
|
131
|
-
.action((file) => {
|
|
132
|
-
|
|
154
|
+
.action(async (file) => {
|
|
155
|
+
await withContext(async () => {
|
|
156
|
+
handleAgentRun(file, [generateTestsModule]);
|
|
157
|
+
});
|
|
133
158
|
});
|
|
134
159
|
// ⚙️ Group: Configuration settings
|
|
135
160
|
const config = cmd.command('config').description('Manage SCAI configuration');
|
|
136
161
|
config
|
|
137
162
|
.command('set-model <model>')
|
|
138
163
|
.description('Set the model to use')
|
|
139
|
-
.action((model) => {
|
|
140
|
-
|
|
141
|
-
|
|
164
|
+
.action(async (model) => {
|
|
165
|
+
await withContext(async () => {
|
|
166
|
+
Config.setModel(model);
|
|
167
|
+
Config.show();
|
|
168
|
+
});
|
|
142
169
|
});
|
|
143
170
|
config
|
|
144
171
|
.command('set-lang <lang>')
|
|
145
172
|
.description('Set the programming language')
|
|
146
|
-
.action((lang) => {
|
|
147
|
-
|
|
148
|
-
|
|
173
|
+
.action(async (lang) => {
|
|
174
|
+
await withContext(async () => {
|
|
175
|
+
Config.setLanguage(lang);
|
|
176
|
+
Config.show();
|
|
177
|
+
});
|
|
149
178
|
});
|
|
150
179
|
config
|
|
151
180
|
.command("show")
|
|
@@ -165,37 +194,39 @@ const index = cmd.command('index').description('index operations');
|
|
|
165
194
|
index
|
|
166
195
|
.command('start')
|
|
167
196
|
.description('Index supported files in the configured index directory')
|
|
168
|
-
.action(
|
|
197
|
+
.action(async () => await withContext(async () => {
|
|
198
|
+
await runIndexCommand();
|
|
199
|
+
}));
|
|
169
200
|
index
|
|
170
201
|
.command('set [dir]')
|
|
171
202
|
.description('Set and activate index directory')
|
|
172
|
-
.action((dir = process.cwd()) => {
|
|
203
|
+
.action(async (dir = process.cwd()) => await withContext(async () => {
|
|
173
204
|
Config.setIndexDir(dir);
|
|
174
205
|
Config.show();
|
|
175
|
-
});
|
|
206
|
+
}));
|
|
176
207
|
index
|
|
177
208
|
.command('list')
|
|
178
209
|
.description('List all indexed repositories')
|
|
179
|
-
.action(() => {
|
|
180
|
-
Config.printAllRepos();
|
|
181
|
-
});
|
|
210
|
+
.action(async () => await withContext(async () => {
|
|
211
|
+
await Config.printAllRepos();
|
|
212
|
+
}));
|
|
182
213
|
index
|
|
183
214
|
.command('switch')
|
|
184
215
|
.description('Switch active repository (by interactive list only)')
|
|
185
|
-
.action(() => {
|
|
186
|
-
runInteractiveSwitch();
|
|
187
|
-
});
|
|
216
|
+
.action(async () => await withContext(async () => {
|
|
217
|
+
await runInteractiveSwitch();
|
|
218
|
+
}));
|
|
188
219
|
index
|
|
189
220
|
.command('delete')
|
|
190
221
|
.description('Delete a repository from the index (interactive)')
|
|
191
|
-
.action(() => {
|
|
192
|
-
runInteractiveDelete();
|
|
193
|
-
});
|
|
222
|
+
.action(async () => await withContext(async () => {
|
|
223
|
+
await runInteractiveDelete();
|
|
224
|
+
}));
|
|
194
225
|
const db = cmd.command('db').description('Database operations');
|
|
195
226
|
db
|
|
196
227
|
.command('check')
|
|
197
228
|
.description('Run the dbcheck script to check the database status')
|
|
198
|
-
.action(() => {
|
|
229
|
+
.action(async () => await withContext(async () => {
|
|
199
230
|
const __filename = fileURLToPath(import.meta.url);
|
|
200
231
|
const __dirname = dirname(__filename);
|
|
201
232
|
const scriptPath = resolve(__dirname, '..', 'dist/scripts', 'dbcheck.js');
|
|
@@ -206,47 +237,66 @@ db
|
|
|
206
237
|
catch (err) {
|
|
207
238
|
console.error('❌ Error running dbcheck script:', err instanceof Error ? err.message : err);
|
|
208
239
|
}
|
|
209
|
-
});
|
|
240
|
+
}));
|
|
210
241
|
db
|
|
211
242
|
.command('reset')
|
|
212
243
|
.description('Delete and reset the SQLite database')
|
|
213
|
-
.action(() =>
|
|
244
|
+
.action(async () => await withContext(async () => {
|
|
245
|
+
await resetDatabase();
|
|
246
|
+
}));
|
|
214
247
|
db
|
|
215
248
|
.command('migrate')
|
|
216
249
|
.description('Run DB migration scripts')
|
|
217
|
-
.action(
|
|
250
|
+
.action(async () => await withContext(async () => {
|
|
251
|
+
await runMigrateCommand();
|
|
252
|
+
}));
|
|
253
|
+
db
|
|
254
|
+
.command('inspect')
|
|
255
|
+
.argument('<filepath>', 'Path to the file to inspect')
|
|
256
|
+
.description('Inspect a specific file and print its indexed summary and functions')
|
|
257
|
+
.action(async (filepath) => await withContext(async () => {
|
|
258
|
+
await runInspectCommand(filepath);
|
|
259
|
+
}));
|
|
260
|
+
const daemon = cmd
|
|
261
|
+
.command('daemon')
|
|
262
|
+
.description('Background summarizer operations');
|
|
263
|
+
// Start the daemon
|
|
264
|
+
daemon
|
|
265
|
+
.command('start')
|
|
266
|
+
.description('Run background summarization of indexed files')
|
|
267
|
+
.action(async () => {
|
|
268
|
+
await withContext(async () => {
|
|
269
|
+
await startDaemon();
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
// Stop the daemon
|
|
273
|
+
daemon
|
|
274
|
+
.command('stop')
|
|
275
|
+
.description('Stop the background summarizer daemon')
|
|
276
|
+
.action(async () => {
|
|
277
|
+
await withContext(async () => {
|
|
278
|
+
await runStopDaemonCommand();
|
|
279
|
+
});
|
|
280
|
+
});
|
|
218
281
|
cmd
|
|
219
282
|
.command('backup')
|
|
220
283
|
.description('Backup the current .scai folder')
|
|
221
|
-
.action(
|
|
284
|
+
.action(async () => await withContext(async () => {
|
|
285
|
+
await runBackupCommand();
|
|
286
|
+
}));
|
|
222
287
|
cmd
|
|
223
288
|
.command('find <query>')
|
|
224
289
|
.description('Search indexed files by keyword')
|
|
225
|
-
.action(
|
|
290
|
+
.action(async (query) => await withContext(async () => {
|
|
291
|
+
await runFindCommand(query);
|
|
292
|
+
}));
|
|
226
293
|
cmd
|
|
227
294
|
.command('ask [question...]')
|
|
228
295
|
.description('Ask a question based on indexed files')
|
|
229
|
-
.action((questionParts) => {
|
|
296
|
+
.action(async (questionParts) => await withContext(async () => {
|
|
230
297
|
const fullQuery = questionParts?.join(' ');
|
|
231
|
-
runAskCommand(fullQuery);
|
|
232
|
-
});
|
|
233
|
-
cmd
|
|
234
|
-
.command('daemon')
|
|
235
|
-
.description('Run background summarization of indexed files')
|
|
236
|
-
.action(async () => {
|
|
237
|
-
await startDaemon();
|
|
238
|
-
});
|
|
239
|
-
cmd
|
|
240
|
-
.command('stop-daemon')
|
|
241
|
-
.description('Stop the background summarizer daemon')
|
|
242
|
-
.action(runStopDaemonCommand);
|
|
243
|
-
cmd
|
|
244
|
-
.command('inspect')
|
|
245
|
-
.argument('<filepath>', 'Path to the file to inspect')
|
|
246
|
-
.description('Inspect a specific file and print its indexed summary and functions')
|
|
247
|
-
.action(async (filepath) => {
|
|
248
|
-
await runInspectCommand(filepath);
|
|
249
|
-
});
|
|
298
|
+
await runAskCommand(fullQuery);
|
|
299
|
+
}));
|
|
250
300
|
cmd
|
|
251
301
|
.command('pipe')
|
|
252
302
|
.description('Run a module pipeline on a given file')
|