@optiqcode/cli 2.1.1 → 2.1.2

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
@@ -289,32 +289,50 @@ async function indexOnce(targetPath, config) {
289
289
  }
290
290
  // Generate repository ID from path
291
291
  const repoId = generateRepoId(targetPath);
292
- // Upload in smaller batches to avoid gateway timeouts
293
- const BATCH_SIZE = 50;
292
+ // Upload in small batches to avoid gateway timeouts
293
+ const BATCH_SIZE = 20;
294
294
  let totalChunks = 0;
295
295
  spinner.text = 'Indexing...';
296
296
  for (let i = 0; i < filesArray.length; i += BATCH_SIZE) {
297
297
  const batch = filesArray.slice(i, i + BATCH_SIZE);
298
298
  const batchNum = Math.floor(i / BATCH_SIZE) + 1;
299
299
  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;
300
+ spinner.text = `Indexing... ${batchNum}/${totalBatches}`;
301
+ // Retry logic for transient failures
302
+ let retries = 3;
303
+ let lastError = null;
304
+ while (retries > 0) {
305
+ try {
306
+ const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
307
+ repository_id: repoId,
308
+ branch: 'main',
309
+ files: batch,
310
+ }, {
311
+ headers: {
312
+ 'Content-Type': 'application/json',
313
+ },
314
+ timeout: 120000, // 2 minute timeout per batch
315
+ });
316
+ if (!response.data.success) {
317
+ spinner.fail(chalk.red('Indexing failed'));
318
+ console.log(chalk.gray(response.data.result?.errors?.join('\n') || 'Unknown error'));
319
+ return;
320
+ }
321
+ totalChunks += response.data.result?.chunks_created || 0;
322
+ break; // Success, exit retry loop
323
+ }
324
+ catch (err) {
325
+ lastError = err;
326
+ retries--;
327
+ if (retries > 0) {
328
+ spinner.text = `Retrying batch ${batchNum}... (${retries} attempts left)`;
329
+ await new Promise(r => setTimeout(r, 2000)); // Wait 2s before retry
330
+ }
331
+ }
332
+ }
333
+ if (retries === 0 && lastError) {
334
+ throw lastError;
316
335
  }
317
- totalChunks += response.data.result?.chunks_created || 0;
318
336
  }
319
337
  spinner.succeed(chalk.cyan('Indexed'));
320
338
  console.log(chalk.gray(` ${filesArray.length} files • ${totalChunks} chunks`));
@@ -357,27 +375,46 @@ async function watchDirectory(targetPath, config) {
357
375
  }
358
376
  spinner.text = `Reading... ${Math.min(i + PARALLEL_READS, files.length)}/${files.length}`;
359
377
  }
360
- // Upload in smaller batches to avoid gateway timeouts
361
- const BATCH_SIZE = 50;
378
+ // Upload in small batches to avoid gateway timeouts
379
+ const BATCH_SIZE = 20;
362
380
  for (let i = 0; i < filesArray.length; i += BATCH_SIZE) {
363
381
  const batch = filesArray.slice(i, i + BATCH_SIZE);
364
382
  const batchNum = Math.floor(i / BATCH_SIZE) + 1;
365
383
  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;
384
+ spinner.text = `Indexing... ${batchNum}/${totalBatches}`;
385
+ // Retry logic for transient failures
386
+ let retries = 3;
387
+ let lastError = null;
388
+ while (retries > 0) {
389
+ try {
390
+ const response = await axios.post(`${ENGINE_URL}/api/v1/index`, {
391
+ repository_id: repoId,
392
+ branch: 'main',
393
+ files: batch,
394
+ }, {
395
+ headers: {
396
+ 'Content-Type': 'application/json',
397
+ },
398
+ timeout: 120000,
399
+ });
400
+ if (!response.data.success) {
401
+ spinner.fail(chalk.red('Failed'));
402
+ console.log(chalk.gray(response.data.result?.errors?.join('\n') || 'Unknown error'));
403
+ return;
404
+ }
405
+ break;
406
+ }
407
+ catch (err) {
408
+ lastError = err;
409
+ retries--;
410
+ if (retries > 0) {
411
+ spinner.text = `Retrying batch ${batchNum}... (${retries} left)`;
412
+ await new Promise(r => setTimeout(r, 2000));
413
+ }
414
+ }
415
+ }
416
+ if (retries === 0 && lastError) {
417
+ throw lastError;
381
418
  }
382
419
  }
383
420
  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.2",
4
4
  "description": "CLI tool for Optiq - automatic code indexing and context engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",