@optiqcode/cli 2.1.1 → 2.1.3

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.
@@ -74,32 +74,51 @@ export async function index(options) {
74
74
  spinner.text = 'Indexing with Optiq Engine...';
75
75
  // Generate repository ID from path
76
76
  const repoId = generateRepoId(targetPath);
77
- // Batch upload files (50 at a time to avoid gateway timeouts)
78
- const BATCH_SIZE = 50;
77
+ // Batch upload files (20 at a time to avoid gateway timeouts)
78
+ const BATCH_SIZE = 20;
79
79
  let uploadedCount = 0;
80
80
  let totalChunksCreated = 0;
81
81
  for (let i = 0; i < fileContents.length; i += BATCH_SIZE) {
82
82
  const batch = fileContents.slice(i, i + BATCH_SIZE);
83
83
  const batchNum = Math.floor(i / BATCH_SIZE) + 1;
84
84
  const totalBatches = Math.ceil(fileContents.length / BATCH_SIZE);
85
- spinner.text = `Indexing batch ${batchNum}/${totalBatches} (${uploadedCount}/${fileContents.length} files)...`;
86
- const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
87
- repository_id: repoId,
88
- branch: 'main',
89
- files: batch,
90
- }, {
91
- headers: {
92
- 'Content-Type': 'application/json',
93
- },
94
- timeout: 0, // No timeout for large codebases
95
- });
96
- if (!response.data.success) {
97
- spinner.fail(chalk.red(' Indexing failed'));
98
- console.log(chalk.red(response.data.result?.errors?.join('\n') || 'Unknown error'));
99
- return;
85
+ spinner.text = `Indexing ${batchNum}/${totalBatches}...`;
86
+ // Retry logic for transient failures
87
+ let retries = 3;
88
+ let lastError = null;
89
+ while (retries > 0) {
90
+ try {
91
+ const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
92
+ repository_id: repoId,
93
+ branch: 'main',
94
+ files: batch,
95
+ }, {
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ },
99
+ timeout: 120000,
100
+ });
101
+ if (!response.data.success) {
102
+ spinner.fail(chalk.red('✗ Indexing failed'));
103
+ console.log(chalk.red(response.data.result?.errors?.join('\n') || 'Unknown error'));
104
+ return;
105
+ }
106
+ totalChunksCreated += response.data.result?.chunks_created || 0;
107
+ uploadedCount += batch.length;
108
+ break;
109
+ }
110
+ catch (err) {
111
+ lastError = err;
112
+ retries--;
113
+ if (retries > 0) {
114
+ spinner.text = `Retrying batch ${batchNum}... (${retries} left)`;
115
+ await new Promise(r => setTimeout(r, 2000));
116
+ }
117
+ }
118
+ }
119
+ if (retries === 0 && lastError) {
120
+ throw lastError;
100
121
  }
101
- totalChunksCreated += response.data.result?.chunks_created || 0;
102
- uploadedCount += batch.length;
103
122
  }
104
123
  spinner.succeed(chalk.green('✓ Indexing complete'));
105
124
  console.log(chalk.blue('📊 Repository ID:'), chalk.bold(repoId));
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@ import { getConfig, saveConfig } from './utils/config.js';
10
10
  import { isValidDirectory, getGitIgnorePatterns, shouldIgnoreFile } from './utils/files.js';
11
11
  const BACKEND_URL = process.env.OPTIQ_BACKEND_URL || 'https://api.optiqcode.com';
12
12
  const ENGINE_URL = process.env.OPTIQ_ENGINE_URL || 'https://api.optiqcode.com';
13
+ // Debug mode - set OPTIQ_DEBUG=1 to see request details
14
+ const DEBUG = process.env.OPTIQ_DEBUG === '1';
13
15
  // Helper to generate repository ID from path
14
16
  function generateRepoId(targetPath) {
15
17
  // Use path basename + hash of full path for uniqueness
@@ -289,32 +291,64 @@ async function indexOnce(targetPath, config) {
289
291
  }
290
292
  // Generate repository ID from path
291
293
  const repoId = generateRepoId(targetPath);
292
- // Upload in smaller batches to avoid gateway timeouts
293
- const BATCH_SIZE = 50;
294
+ // Upload in small batches to avoid gateway timeouts
295
+ const BATCH_SIZE = 10;
294
296
  let totalChunks = 0;
297
+ if (DEBUG) {
298
+ console.log(chalk.gray(`\n[DEBUG] Sending to: ${ENGINE_URL}/api/v1/index`));
299
+ console.log(chalk.gray(`[DEBUG] Repo ID: ${repoId}`));
300
+ console.log(chalk.gray(`[DEBUG] Total files: ${filesArray.length}`));
301
+ }
295
302
  spinner.text = 'Indexing...';
296
303
  for (let i = 0; i < filesArray.length; i += BATCH_SIZE) {
297
304
  const batch = filesArray.slice(i, i + BATCH_SIZE);
298
305
  const batchNum = Math.floor(i / BATCH_SIZE) + 1;
299
306
  const totalBatches = Math.ceil(filesArray.length / BATCH_SIZE);
300
- spinner.text = `Indexing... ${batchNum}/${totalBatches} (parallel processing)`;
301
- // Call the Rust engine's /api/v1/index endpoint
302
- const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
303
- repository_id: repoId,
304
- branch: 'main',
305
- files: batch,
306
- }, {
307
- headers: {
308
- 'Content-Type': 'application/json',
309
- },
310
- timeout: 0, // No timeout - parallel processing handles large batches
311
- });
312
- if (!response.data.success) {
313
- spinner.fail(chalk.red('Indexing failed'));
314
- console.log(chalk.gray(response.data.result?.errors?.join('\n') || 'Unknown error'));
315
- return;
307
+ spinner.text = `Indexing... ${batchNum}/${totalBatches}`;
308
+ if (DEBUG) {
309
+ console.log(chalk.gray(`\n[DEBUG] Batch ${batchNum}: ${batch.map(f => f.path).join(', ')}`));
310
+ }
311
+ // Retry logic for transient failures
312
+ let retries = 3;
313
+ let lastError = null;
314
+ while (retries > 0) {
315
+ try {
316
+ const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
317
+ repository_id: repoId,
318
+ branch: 'main',
319
+ files: batch,
320
+ }, {
321
+ headers: {
322
+ 'Content-Type': 'application/json',
323
+ },
324
+ timeout: 120000, // 2 minute timeout per batch
325
+ });
326
+ if (!response.data.success) {
327
+ spinner.fail(chalk.red('Indexing failed'));
328
+ console.log(chalk.gray(response.data.result?.errors?.join('\n') || 'Unknown error'));
329
+ return;
330
+ }
331
+ totalChunks += response.data.result?.chunks_created || 0;
332
+ break; // Success, exit retry loop
333
+ }
334
+ catch (err) {
335
+ lastError = err;
336
+ retries--;
337
+ if (DEBUG) {
338
+ console.log(chalk.red(`\n[DEBUG] Error: ${err.code || err.message}`));
339
+ if (err.response) {
340
+ console.log(chalk.red(`[DEBUG] Status: ${err.response.status}`));
341
+ }
342
+ }
343
+ if (retries > 0) {
344
+ spinner.text = `Retrying batch ${batchNum}... (${retries} attempts left)`;
345
+ await new Promise(r => setTimeout(r, 2000)); // Wait 2s before retry
346
+ }
347
+ }
348
+ }
349
+ if (retries === 0 && lastError) {
350
+ throw lastError;
316
351
  }
317
- totalChunks += response.data.result?.chunks_created || 0;
318
352
  }
319
353
  spinner.succeed(chalk.cyan('Indexed'));
320
354
  console.log(chalk.gray(` ${filesArray.length} files • ${totalChunks} chunks`));
@@ -357,27 +391,46 @@ async function watchDirectory(targetPath, config) {
357
391
  }
358
392
  spinner.text = `Reading... ${Math.min(i + PARALLEL_READS, files.length)}/${files.length}`;
359
393
  }
360
- // Upload in smaller batches to avoid gateway timeouts
361
- const BATCH_SIZE = 50;
394
+ // Upload in small batches to avoid gateway timeouts
395
+ const BATCH_SIZE = 20;
362
396
  for (let i = 0; i < filesArray.length; i += BATCH_SIZE) {
363
397
  const batch = filesArray.slice(i, i + BATCH_SIZE);
364
398
  const batchNum = Math.floor(i / BATCH_SIZE) + 1;
365
399
  const totalBatches = Math.ceil(filesArray.length / BATCH_SIZE);
366
- spinner.text = `Indexing... ${batchNum}/${totalBatches} (parallel processing)`;
367
- const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
368
- repository_id: repoId,
369
- branch: 'main',
370
- files: batch,
371
- }, {
372
- headers: {
373
- 'Content-Type': 'application/json',
374
- },
375
- timeout: 0,
376
- });
377
- if (!response.data.success) {
378
- spinner.fail(chalk.red('Failed'));
379
- console.log(chalk.gray(response.data.result?.errors?.join('\n') || 'Unknown error'));
380
- return;
400
+ spinner.text = `Indexing... ${batchNum}/${totalBatches}`;
401
+ // Retry logic for transient failures
402
+ let retries = 3;
403
+ let lastError = null;
404
+ while (retries > 0) {
405
+ try {
406
+ const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
407
+ repository_id: repoId,
408
+ branch: 'main',
409
+ files: batch,
410
+ }, {
411
+ headers: {
412
+ 'Content-Type': 'application/json',
413
+ },
414
+ timeout: 120000,
415
+ });
416
+ if (!response.data.success) {
417
+ spinner.fail(chalk.red('Failed'));
418
+ console.log(chalk.gray(response.data.result?.errors?.join('\n') || 'Unknown error'));
419
+ return;
420
+ }
421
+ break;
422
+ }
423
+ catch (err) {
424
+ lastError = err;
425
+ retries--;
426
+ if (retries > 0) {
427
+ spinner.text = `Retrying batch ${batchNum}... (${retries} left)`;
428
+ await new Promise(r => setTimeout(r, 2000));
429
+ }
430
+ }
431
+ }
432
+ if (retries === 0 && lastError) {
433
+ throw lastError;
381
434
  }
382
435
  }
383
436
  spinner.succeed(chalk.cyan(`Indexed ${files.length} files`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optiqcode/cli",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "CLI tool for Optiq - automatic code indexing and context engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",