@optiqcode/cli 1.5.0 ā 1.7.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.
- package/dist/index.js +184 -88
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { isValidDirectory, getGitIgnorePatterns, shouldIgnoreFile } from './util
|
|
|
12
12
|
const BACKEND_URL = process.env.OPTIQ_BACKEND_URL || 'https://api.optiqcode.com';
|
|
13
13
|
async function showBanner() {
|
|
14
14
|
console.clear();
|
|
15
|
-
console.log(chalk.
|
|
15
|
+
console.log(chalk.cyan.bold(`
|
|
16
16
|
___ _ _
|
|
17
17
|
/ _ \\ _ __ | |_(_) __ _
|
|
18
18
|
| | | | '_ \\| __| |/ _\` |
|
|
@@ -20,28 +20,49 @@ async function showBanner() {
|
|
|
20
20
|
\\___/| .__/ \\__|_|\\__, |
|
|
21
21
|
|_| |_|
|
|
22
22
|
`));
|
|
23
|
-
console.log(chalk.gray('
|
|
23
|
+
console.log(chalk.gray(' AI-powered code indexing & search'));
|
|
24
|
+
console.log(chalk.gray(' v1.6.0\n'));
|
|
25
|
+
}
|
|
26
|
+
function showHelp() {
|
|
27
|
+
console.log(chalk.cyan.bold('Optiq CLI') + chalk.gray(' - AI-powered code indexing\n'));
|
|
28
|
+
console.log(chalk.white('Usage:'));
|
|
29
|
+
console.log(chalk.gray(' optiq [command] [options]\n'));
|
|
30
|
+
console.log(chalk.white('Commands:'));
|
|
31
|
+
console.log(chalk.gray(' login Login with email & OTP'));
|
|
32
|
+
console.log(chalk.gray(' index Index current directory once'));
|
|
33
|
+
console.log(chalk.gray(' watch Watch directory and auto-index changes'));
|
|
34
|
+
console.log(chalk.gray(' logout Clear stored credentials'));
|
|
35
|
+
console.log(chalk.gray(' key Show your API key'));
|
|
36
|
+
console.log(chalk.gray(' help Show this help message\n'));
|
|
37
|
+
console.log(chalk.white('Options:'));
|
|
38
|
+
console.log(chalk.gray(' --path <dir> Specify directory to index (default: current)\n'));
|
|
39
|
+
console.log(chalk.white('Examples:'));
|
|
40
|
+
console.log(chalk.gray(' optiq login'));
|
|
41
|
+
console.log(chalk.gray(' optiq index'));
|
|
42
|
+
console.log(chalk.gray(' optiq watch'));
|
|
43
|
+
console.log(chalk.gray(' optiq index --path /path/to/project\n'));
|
|
44
|
+
console.log(chalk.gray('Get started: https://github.com/optiqcode/optiq'));
|
|
24
45
|
}
|
|
25
46
|
async function login() {
|
|
26
|
-
console.log(chalk.
|
|
47
|
+
console.log(chalk.cyan('š Login\n'));
|
|
27
48
|
const { email } = await prompts({
|
|
28
49
|
type: 'text',
|
|
29
50
|
name: 'email',
|
|
30
51
|
message: 'Email:',
|
|
31
|
-
validate: (value) => value.includes('@') || '
|
|
52
|
+
validate: (value) => value.includes('@') || 'Invalid email',
|
|
32
53
|
});
|
|
33
54
|
if (!email) {
|
|
34
|
-
console.log(chalk.gray('\
|
|
55
|
+
console.log(chalk.gray('\nCancelled'));
|
|
35
56
|
process.exit(0);
|
|
36
57
|
}
|
|
37
|
-
const spinner = ora({ text: 'Sending code...', color: '
|
|
58
|
+
const spinner = ora({ text: 'Sending code...', color: 'cyan' }).start();
|
|
38
59
|
try {
|
|
39
60
|
// Send OTP
|
|
40
61
|
const otpResponse = await axios.post(`${BACKEND_URL}/api/auth/send-otp`, { email }, { timeout: 10000 });
|
|
41
62
|
if (!otpResponse.data.success) {
|
|
42
63
|
throw new Error('Failed to send code');
|
|
43
64
|
}
|
|
44
|
-
spinner.succeed(chalk.
|
|
65
|
+
spinner.succeed(chalk.cyan('Code sent\n'));
|
|
45
66
|
const { code } = await prompts({
|
|
46
67
|
type: 'text',
|
|
47
68
|
name: 'code',
|
|
@@ -52,10 +73,10 @@ async function login() {
|
|
|
52
73
|
},
|
|
53
74
|
});
|
|
54
75
|
if (!code) {
|
|
55
|
-
console.log(chalk.gray('\
|
|
76
|
+
console.log(chalk.gray('\nCancelled'));
|
|
56
77
|
return false;
|
|
57
78
|
}
|
|
58
|
-
const verifySpinner = ora({ text: 'Verifying...', color: '
|
|
79
|
+
const verifySpinner = ora({ text: 'Verifying...', color: 'cyan' }).start();
|
|
59
80
|
// Verify OTP
|
|
60
81
|
const verifyResponse = await axios.post(`${BACKEND_URL}/api/auth/verify-otp`, { email, code }, { timeout: 10000 });
|
|
61
82
|
if (verifyResponse.data.success) {
|
|
@@ -82,29 +103,95 @@ async function login() {
|
|
|
82
103
|
token: token,
|
|
83
104
|
apiKey: validateResponse.data.context_engine_api_key || '',
|
|
84
105
|
});
|
|
85
|
-
verifySpinner.succeed(chalk.
|
|
106
|
+
verifySpinner.succeed(chalk.cyan(`Logged in as ${email}\n`));
|
|
86
107
|
return true;
|
|
87
108
|
}
|
|
88
109
|
else {
|
|
89
|
-
verifySpinner.fail(chalk.
|
|
110
|
+
verifySpinner.fail(chalk.red('Invalid code'));
|
|
90
111
|
return false;
|
|
91
112
|
}
|
|
92
113
|
}
|
|
93
114
|
catch (error) {
|
|
94
|
-
spinner.fail(chalk.
|
|
115
|
+
spinner.fail(chalk.red('Login failed'));
|
|
95
116
|
if (error.response?.data?.error) {
|
|
96
|
-
console.log(chalk.gray(error.response.data.error));
|
|
117
|
+
console.log(chalk.gray(' ' + error.response.data.error));
|
|
97
118
|
}
|
|
98
119
|
else {
|
|
99
|
-
console.log(chalk.gray(error.message));
|
|
120
|
+
console.log(chalk.gray(' ' + error.message));
|
|
100
121
|
}
|
|
101
122
|
return false;
|
|
102
123
|
}
|
|
103
124
|
}
|
|
104
125
|
async function main() {
|
|
105
|
-
|
|
106
|
-
|
|
126
|
+
const args = process.argv.slice(2);
|
|
127
|
+
const command = args[0];
|
|
128
|
+
// Parse --path option
|
|
129
|
+
const pathIndex = args.indexOf('--path');
|
|
130
|
+
const targetPath = pathIndex >= 0 && args[pathIndex + 1]
|
|
131
|
+
? path.resolve(args[pathIndex + 1])
|
|
132
|
+
: path.resolve(process.cwd());
|
|
133
|
+
// Handle commands
|
|
134
|
+
if (command === 'help' || command === '--help' || command === '-h') {
|
|
135
|
+
showHelp();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (command === 'login') {
|
|
139
|
+
await showBanner();
|
|
140
|
+
const success = await login();
|
|
141
|
+
process.exit(success ? 0 : 1);
|
|
142
|
+
}
|
|
143
|
+
if (command === 'logout') {
|
|
144
|
+
const { clearConfig } = await import('./utils/config.js');
|
|
145
|
+
await clearConfig();
|
|
146
|
+
console.log(chalk.cyan('ā Logged out successfully'));
|
|
147
|
+
process.exit(0);
|
|
148
|
+
}
|
|
149
|
+
if (command === 'key') {
|
|
150
|
+
const config = await getConfig();
|
|
151
|
+
if (!config) {
|
|
152
|
+
console.log(chalk.red('ā Not logged in'));
|
|
153
|
+
console.log(chalk.gray('Run: optiq login'));
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
console.log(chalk.cyan('\nš Your API Key:\n'));
|
|
157
|
+
console.log(chalk.white(config.apiKey || 'No API key found'));
|
|
158
|
+
console.log(chalk.gray('\nUse this for the MCP server or direct API calls'));
|
|
159
|
+
console.log(chalk.gray('Keep this secret!\n'));
|
|
160
|
+
process.exit(0);
|
|
161
|
+
}
|
|
162
|
+
// Check authentication for index/watch commands
|
|
107
163
|
let config = await getConfig();
|
|
164
|
+
if (command === 'index' || command === 'watch') {
|
|
165
|
+
if (!config) {
|
|
166
|
+
console.log(chalk.red('ā Not logged in'));
|
|
167
|
+
console.log(chalk.gray('Run: optiq login'));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
// Safety check
|
|
171
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
172
|
+
if (homeDir && path.resolve(targetPath) === path.resolve(homeDir)) {
|
|
173
|
+
console.log(chalk.red('ā Cannot index home directory'));
|
|
174
|
+
console.log(chalk.gray('Specify a project directory'));
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
// Validate directory
|
|
178
|
+
const validation = await isValidDirectory(targetPath);
|
|
179
|
+
if (!validation.valid) {
|
|
180
|
+
console.log(chalk.red(`ā ${validation.error}`));
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
console.log(chalk.cyan('š ' + path.basename(targetPath)));
|
|
184
|
+
console.log(chalk.gray(` ${validation.fileCount} files ⢠${targetPath}\n`));
|
|
185
|
+
if (command === 'index') {
|
|
186
|
+
await indexOnce(targetPath, config);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
await watchDirectory(targetPath, config);
|
|
190
|
+
}
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// Interactive mode if no command
|
|
194
|
+
await showBanner();
|
|
108
195
|
if (!config) {
|
|
109
196
|
const success = await login();
|
|
110
197
|
if (!success) {
|
|
@@ -116,54 +203,49 @@ async function main() {
|
|
|
116
203
|
}
|
|
117
204
|
}
|
|
118
205
|
else {
|
|
119
|
-
console.log(chalk.
|
|
206
|
+
console.log(chalk.cyan('ā ' + config.email));
|
|
120
207
|
console.log();
|
|
121
208
|
}
|
|
122
|
-
|
|
123
|
-
// Safety check: prevent indexing home directory
|
|
209
|
+
// Safety check
|
|
124
210
|
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
125
211
|
if (homeDir && path.resolve(targetPath) === path.resolve(homeDir)) {
|
|
126
|
-
console.log(chalk.
|
|
127
|
-
console.log(chalk.gray('Please run this from a project directory'));
|
|
212
|
+
console.log(chalk.red('ā Cannot index home directory'));
|
|
128
213
|
process.exit(1);
|
|
129
214
|
}
|
|
130
215
|
// Validate directory
|
|
131
216
|
const validation = await isValidDirectory(targetPath);
|
|
132
217
|
if (!validation.valid) {
|
|
133
|
-
console.log(chalk.
|
|
218
|
+
console.log(chalk.red(`ā ${validation.error}`));
|
|
134
219
|
process.exit(1);
|
|
135
220
|
}
|
|
136
|
-
console.log(chalk.
|
|
137
|
-
console.log(chalk.gray(` ${validation.fileCount} files
|
|
138
|
-
console.log(chalk.gray(` ${targetPath}\n`));
|
|
221
|
+
console.log(chalk.cyan('š ' + path.basename(targetPath)));
|
|
222
|
+
console.log(chalk.gray(` ${validation.fileCount} files ⢠${targetPath}\n`));
|
|
139
223
|
// Ask what to do
|
|
140
224
|
const { action } = await prompts({
|
|
141
225
|
type: 'select',
|
|
142
226
|
name: 'action',
|
|
143
|
-
message: '
|
|
227
|
+
message: 'Choose action:',
|
|
144
228
|
choices: [
|
|
145
|
-
{ title: 'š Watch and auto-index changes', value: 'watch' },
|
|
146
229
|
{ title: 'š¦ Index once', value: 'index' },
|
|
147
|
-
{ title: '
|
|
230
|
+
{ title: 'š Watch & auto-index', value: 'watch' },
|
|
231
|
+
{ title: 'š Show API Key', value: 'key' },
|
|
148
232
|
{ title: 'šŖ Logout', value: 'logout' },
|
|
149
|
-
{ title: 'ā Exit', value: 'exit' },
|
|
150
233
|
],
|
|
151
234
|
});
|
|
152
|
-
if (action
|
|
153
|
-
console.log(chalk.gray('\
|
|
235
|
+
if (!action) {
|
|
236
|
+
console.log(chalk.gray('\nCancelled'));
|
|
154
237
|
process.exit(0);
|
|
155
238
|
}
|
|
156
|
-
if (action === '
|
|
157
|
-
console.log(chalk.
|
|
158
|
-
console.log(chalk.white
|
|
159
|
-
console.log(chalk.gray('\
|
|
160
|
-
console.log(chalk.gray('Keep this key secret and never share it publicly.\n'));
|
|
239
|
+
if (action === 'key') {
|
|
240
|
+
console.log(chalk.cyan('\nš Your API Key:\n'));
|
|
241
|
+
console.log(chalk.white(config.apiKey));
|
|
242
|
+
console.log(chalk.gray('\nKeep this secret!\n'));
|
|
161
243
|
process.exit(0);
|
|
162
244
|
}
|
|
163
245
|
if (action === 'logout') {
|
|
164
246
|
const { clearConfig } = await import('./utils/config.js');
|
|
165
247
|
await clearConfig();
|
|
166
|
-
console.log(chalk.
|
|
248
|
+
console.log(chalk.cyan('\nā Logged out'));
|
|
167
249
|
process.exit(0);
|
|
168
250
|
}
|
|
169
251
|
if (action === 'index') {
|
|
@@ -174,53 +256,72 @@ async function main() {
|
|
|
174
256
|
}
|
|
175
257
|
}
|
|
176
258
|
async function indexOnce(targetPath, config) {
|
|
177
|
-
const spinner = ora({ text: 'Collecting files...', color: '
|
|
259
|
+
const spinner = ora({ text: 'Collecting files...', color: 'cyan' }).start();
|
|
178
260
|
try {
|
|
179
261
|
const files = await collectFiles(targetPath);
|
|
180
262
|
spinner.text = `Reading ${files.length} files...`;
|
|
181
263
|
const fileContents = {};
|
|
264
|
+
let processed = 0;
|
|
182
265
|
for (const file of files) {
|
|
183
266
|
try {
|
|
184
267
|
const content = await fs.readFile(file, 'utf-8');
|
|
185
|
-
const relativePath = path.relative(targetPath, file);
|
|
268
|
+
const relativePath = path.relative(targetPath, file).replace(/\\/g, '/');
|
|
186
269
|
fileContents[relativePath] = content;
|
|
270
|
+
processed++;
|
|
271
|
+
if (processed % 50 === 0) {
|
|
272
|
+
spinner.text = `Reading files... ${processed}/${files.length}`;
|
|
273
|
+
}
|
|
187
274
|
}
|
|
188
275
|
catch (error) {
|
|
189
|
-
// Skip files
|
|
276
|
+
// Skip unreadable files
|
|
190
277
|
}
|
|
191
278
|
}
|
|
192
|
-
spinner.text = 'Uploading to Optiq...';
|
|
193
279
|
const filesArray = Object.entries(fileContents).map(([path, content]) => ({
|
|
194
280
|
path,
|
|
195
281
|
content,
|
|
196
282
|
}));
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
283
|
+
// Batch upload
|
|
284
|
+
const BATCH_SIZE = 50;
|
|
285
|
+
let totalFiles = 0;
|
|
286
|
+
let totalEntities = 0;
|
|
287
|
+
let repoId = '';
|
|
288
|
+
for (let i = 0; i < filesArray.length; i += BATCH_SIZE) {
|
|
289
|
+
const batch = filesArray.slice(i, i + BATCH_SIZE);
|
|
290
|
+
const batchNum = Math.floor(i / BATCH_SIZE) + 1;
|
|
291
|
+
const totalBatches = Math.ceil(filesArray.length / BATCH_SIZE);
|
|
292
|
+
spinner.text = `Uploading... batch ${batchNum}/${totalBatches}`;
|
|
293
|
+
const response = await axios.post(`${BACKEND_URL}/api/nexus/index/content`, {
|
|
294
|
+
repository_path: targetPath,
|
|
295
|
+
files: batch,
|
|
296
|
+
}, {
|
|
297
|
+
headers: {
|
|
298
|
+
'X-API-Key': config.apiKey,
|
|
299
|
+
'Content-Type': 'application/json',
|
|
300
|
+
},
|
|
301
|
+
timeout: 0,
|
|
302
|
+
});
|
|
303
|
+
if (!response.data.success) {
|
|
304
|
+
spinner.fail(chalk.red('Indexing failed'));
|
|
305
|
+
console.log(chalk.gray(response.data.error || 'Unknown error'));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
repoId = response.data.repo_id;
|
|
309
|
+
totalFiles += response.data.stats?.files_indexed || 0;
|
|
310
|
+
totalEntities += response.data.stats?.entities_indexed || 0;
|
|
215
311
|
}
|
|
312
|
+
spinner.succeed(chalk.cyan('Indexed'));
|
|
313
|
+
console.log(chalk.gray(` ${totalFiles} files ⢠${totalEntities} entities`));
|
|
314
|
+
console.log(chalk.cyan('\nš Repository ID:'));
|
|
315
|
+
console.log(chalk.white(` ${repoId}`));
|
|
316
|
+
console.log(chalk.gray('\n Use this ID with the MCP server\n'));
|
|
216
317
|
}
|
|
217
318
|
catch (error) {
|
|
218
|
-
spinner.fail(chalk.
|
|
319
|
+
spinner.fail(chalk.red('ā Failed'));
|
|
219
320
|
if (error.response?.data?.error) {
|
|
220
|
-
console.log(chalk.gray(error.response.data.error));
|
|
321
|
+
console.log(chalk.gray(' ' + error.response.data.error));
|
|
221
322
|
}
|
|
222
323
|
else {
|
|
223
|
-
console.log(chalk.gray(error.message));
|
|
324
|
+
console.log(chalk.gray(' ' + error.message));
|
|
224
325
|
}
|
|
225
326
|
}
|
|
226
327
|
}
|
|
@@ -238,9 +339,8 @@ async function watchDirectory(targetPath, config) {
|
|
|
238
339
|
const existingRepo = repoListResponse.data.repositories.find((r) => r.path === targetPath);
|
|
239
340
|
if (existingRepo) {
|
|
240
341
|
repoId = existingRepo.id;
|
|
241
|
-
console.log(chalk.
|
|
242
|
-
console.log(chalk.
|
|
243
|
-
console.log();
|
|
342
|
+
console.log(chalk.cyan('ā Already indexed'));
|
|
343
|
+
console.log(chalk.gray(` Repo ID: ${repoId}\n`));
|
|
244
344
|
}
|
|
245
345
|
}
|
|
246
346
|
}
|
|
@@ -300,22 +400,20 @@ async function watchDirectory(targetPath, config) {
|
|
|
300
400
|
repoId = response.data.repo_id;
|
|
301
401
|
uploadedCount += batch.length;
|
|
302
402
|
}
|
|
303
|
-
spinner.succeed(chalk.
|
|
304
|
-
console.log(chalk.gray(
|
|
305
|
-
console.log();
|
|
403
|
+
spinner.succeed(chalk.cyan(`Indexed ${files.length} files`));
|
|
404
|
+
console.log(chalk.gray(` Repo ID: ${repoId}\n`));
|
|
306
405
|
}
|
|
307
406
|
catch (error) {
|
|
308
|
-
spinner.fail(chalk.
|
|
407
|
+
spinner.fail(chalk.red('Failed'));
|
|
309
408
|
if (error.response?.data?.error) {
|
|
310
|
-
console.log(chalk.gray(error.response.data.error));
|
|
409
|
+
console.log(chalk.gray(' ' + error.response.data.error));
|
|
311
410
|
}
|
|
312
411
|
else {
|
|
313
|
-
console.log(chalk.gray(error.message));
|
|
412
|
+
console.log(chalk.gray(' ' + error.message));
|
|
314
413
|
}
|
|
315
414
|
return;
|
|
316
415
|
}
|
|
317
416
|
}
|
|
318
|
-
console.log(chalk.white('š Watching for changes...\n'));
|
|
319
417
|
const ignorePatterns = await getGitIgnorePatterns(targetPath);
|
|
320
418
|
const watcher = chokidar.watch(targetPath, {
|
|
321
419
|
ignored: (filePath) => {
|
|
@@ -352,17 +450,14 @@ async function watchDirectory(targetPath, config) {
|
|
|
352
450
|
const uptime = formatUptime(Date.now() - sessionStartTime);
|
|
353
451
|
const timeSinceLastIndex = Math.floor((Date.now() - lastIndexedTime) / 1000);
|
|
354
452
|
const lines = [];
|
|
355
|
-
lines.push(chalk.
|
|
356
|
-
lines.push(`${chalk.cyan('
|
|
357
|
-
lines.push(
|
|
358
|
-
lines.push(` ${chalk.gray('Total Indexed:')} ${chalk.white(totalIndexed)} ${chalk.gray('changes')}`);
|
|
359
|
-
lines.push(` ${chalk.gray('Unique Files:')} ${chalk.white(allIndexedFiles.size)}`);
|
|
360
|
-
lines.push('');
|
|
361
|
-
lines.push(`${chalk.green('ā')} ${chalk.gray('Last Activity:')} ${chalk.white(lastIndexedFile || 'None')}`);
|
|
453
|
+
lines.push(chalk.gray('ā'.repeat(50)));
|
|
454
|
+
lines.push(`${chalk.cyan('š Watching')} ${chalk.gray('ā¢')} ${chalk.white(uptime)} ${chalk.gray('uptime')}`);
|
|
455
|
+
lines.push(`${chalk.gray(' Indexed:')} ${chalk.white(totalIndexed)} ${chalk.gray('changes')} ${chalk.gray('ā¢')} ${chalk.white(allIndexedFiles.size)} ${chalk.gray('files')}`);
|
|
362
456
|
if (lastIndexedFile) {
|
|
363
|
-
|
|
457
|
+
const timeStr = timeSinceLastIndex < 60 ? `${timeSinceLastIndex}s` : `${Math.floor(timeSinceLastIndex / 60)}m`;
|
|
458
|
+
lines.push(`${chalk.gray(' Last:')} ${chalk.white(lastIndexedFile)} ${chalk.gray(`(${timeStr} ago)`)}`);
|
|
364
459
|
}
|
|
365
|
-
lines.push(chalk.
|
|
460
|
+
lines.push(chalk.gray('ā'.repeat(50)));
|
|
366
461
|
lines.push('');
|
|
367
462
|
logUpdate(lines.join('\n'));
|
|
368
463
|
};
|
|
@@ -436,14 +531,14 @@ async function watchDirectory(targetPath, config) {
|
|
|
436
531
|
}
|
|
437
532
|
else {
|
|
438
533
|
logUpdate.clear();
|
|
439
|
-
console.log(chalk.
|
|
440
|
-
console.log(chalk.gray(response.data.error));
|
|
534
|
+
console.log(chalk.red(`ā Failed to index`));
|
|
535
|
+
console.log(chalk.gray(` ${response.data.error}`));
|
|
441
536
|
}
|
|
442
537
|
}
|
|
443
538
|
catch (error) {
|
|
444
539
|
logUpdate.clear();
|
|
445
|
-
console.log(chalk.
|
|
446
|
-
console.log(chalk.gray(error.response?.data || error.message));
|
|
540
|
+
console.log(chalk.red(`ā Failed to index`));
|
|
541
|
+
console.log(chalk.gray(` ${error.response?.data?.error || error.message}`));
|
|
447
542
|
}
|
|
448
543
|
isProcessing = false;
|
|
449
544
|
// Check if there are more pending changes and process them
|
|
@@ -471,11 +566,12 @@ async function watchDirectory(targetPath, config) {
|
|
|
471
566
|
scheduleProcess();
|
|
472
567
|
})
|
|
473
568
|
.on('error', (error) => {
|
|
474
|
-
|
|
569
|
+
logUpdate.clear();
|
|
570
|
+
console.log(chalk.red('ā Watcher error:'), chalk.gray(error.message));
|
|
475
571
|
});
|
|
476
|
-
console.log(chalk.gray('Press Ctrl+C to stop\n'));
|
|
477
572
|
process.on('SIGINT', () => {
|
|
478
|
-
|
|
573
|
+
logUpdate.clear();
|
|
574
|
+
console.log(chalk.cyan('\nā Stopped watching'));
|
|
479
575
|
watcher.close();
|
|
480
576
|
process.exit(0);
|
|
481
577
|
});
|