@arbidocs/cli 0.3.49 → 0.3.51

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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.3.51
4
+
5
+ [compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.50...HEAD)
6
+
7
+ ### 🔥 Performance
8
+
9
+ - Stop auto-refetching workspace documents/conversations/tags ([#650](https://github.com/arbicity/ARBI-frontend/pull/650), [#651](https://github.com/arbicity/ARBI-frontend/pull/651))
10
+
11
+ ### 🩹 Fixes
12
+
13
+ - Exclude /arbi-files/ from static-asset nginx location so image uploads reach MinIO ([#646](https://github.com/arbicity/ARBI-frontend/pull/646))
14
+ - Make workspace switch sequential and race-free ([#648](https://github.com/arbicity/ARBI-frontend/pull/648), [#649](https://github.com/arbicity/ARBI-frontend/pull/649))
15
+ - Omit doc_ext_ids by default in retrieve, cap explicit selection at 5000 ([#652](https://github.com/arbicity/ARBI-frontend/pull/652))
16
+
17
+ ## v0.3.50
18
+
19
+ [compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.49...HEAD)
20
+
21
+ ### 🚀 Enhancements
22
+
23
+ - Use FileX icon for empty document status ([#643](https://github.com/arbicity/ARBI-frontend/pull/643))
24
+ - **cli:** Improve reprocess progress with two-phase reporting ([#584](https://github.com/arbicity/ARBI-frontend/pull/584))
25
+
3
26
  ## v0.3.49
4
27
 
5
28
  [compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.48...HEAD)
package/dist/index.js CHANGED
@@ -3641,7 +3641,7 @@ function getLatestVersion(skipCache = false) {
3641
3641
  }
3642
3642
  }
3643
3643
  function getCurrentVersion() {
3644
- return "0.3.49";
3644
+ return "0.3.51";
3645
3645
  }
3646
3646
  function readChangelog(fromVersion, toVersion) {
3647
3647
  try {
@@ -3694,17 +3694,17 @@ function showChangelog(fromVersion, toVersion) {
3694
3694
  async function checkForUpdates(autoUpdate) {
3695
3695
  try {
3696
3696
  const latest = getLatestVersion();
3697
- if (!latest || latest === "0.3.49") return;
3697
+ if (!latest || latest === "0.3.51") return;
3698
3698
  if (autoUpdate) {
3699
3699
  warn(`
3700
- Your arbi version is out of date (${"0.3.49"} \u2192 ${latest}). Updating...`);
3700
+ Your arbi version is out of date (${"0.3.51"} \u2192 ${latest}). Updating...`);
3701
3701
  child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
3702
- showChangelog("0.3.49", latest);
3702
+ showChangelog("0.3.51", latest);
3703
3703
  console.log(`Updated to ${latest}.`);
3704
3704
  } else {
3705
3705
  warn(
3706
3706
  `
3707
- Your arbi version is out of date (${"0.3.49"} \u2192 ${latest}).
3707
+ Your arbi version is out of date (${"0.3.51"} \u2192 ${latest}).
3708
3708
  Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3709
3709
  );
3710
3710
  }
@@ -3714,9 +3714,9 @@ Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3714
3714
  function hintUpdateOnError() {
3715
3715
  try {
3716
3716
  const cached = readCache();
3717
- if (cached && cached.latest !== "0.3.49") {
3717
+ if (cached && cached.latest !== "0.3.51") {
3718
3718
  warn(
3719
- `Your arbi version is out of date (${"0.3.49"} \u2192 ${cached.latest}). Run "arbi update".`
3719
+ `Your arbi version is out of date (${"0.3.51"} \u2192 ${cached.latest}). Run "arbi update".`
3720
3720
  );
3721
3721
  }
3722
3722
  } catch {
@@ -5338,10 +5338,16 @@ function registerDocsCommand(program2) {
5338
5338
  "--status-interval <seconds>",
5339
5339
  "Seconds between progress lines (0 to disable periodic printing).",
5340
5340
  "5"
5341
- ).option("-v, --verbose", "Print a log line after each batch in addition to periodic stats.").option("-q, --quiet", "Suppress periodic progress lines \u2014 only print the final summary.").action(
5341
+ ).option("-v, --verbose", "Print a log line after each batch in addition to periodic stats.").option("-q, --quiet", "Suppress periodic progress lines \u2014 only print the final summary.").option("-W, --watch", "Watch document processing progress after submission").option("--no-watch", "Skip watching document processing").action(
5342
5342
  (ids, opts) => runAction(async () => {
5343
- const { arbi } = await resolveWorkspace(void 0, { skipNotifications: true });
5343
+ const isInteractive = process.stdout.isTTY === true;
5344
+ const watchPref = getConfig()?.watch !== false;
5345
+ const willWatch = opts.watch === false ? false : opts.watch === true || watchPref && isInteractive;
5346
+ const { arbi, config, accessToken } = await resolveWorkspace(void 0, {
5347
+ skipNotifications: true
5348
+ });
5344
5349
  let docIds;
5350
+ const docNames = /* @__PURE__ */ new Map();
5345
5351
  if (ids && ids.length > 0) {
5346
5352
  if (opts.ext || opts.folder) {
5347
5353
  warn("--ext/--folder are ignored when explicit IDs are given.");
@@ -5366,6 +5372,9 @@ function registerDocsCommand(program2) {
5366
5372
  );
5367
5373
  }
5368
5374
  docIds = filtered.map((d) => d.external_id);
5375
+ for (const d of filtered) {
5376
+ docNames.set(d.external_id, d.file_name ?? "Unnamed");
5377
+ }
5369
5378
  } else {
5370
5379
  error("Provide document IDs or use --status to select documents to reprocess.");
5371
5380
  process.exit(1);
@@ -5406,11 +5415,21 @@ function registerDocsCommand(program2) {
5406
5415
  const pad = (n) => n.toString().padStart(2, "0");
5407
5416
  return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
5408
5417
  };
5418
+ let procCompleted = 0;
5419
+ let procFailed = 0;
5420
+ const procPending = /* @__PURE__ */ new Set();
5421
+ const procFailedDetails = /* @__PURE__ */ new Map();
5409
5422
  const printStatus = (prefix = "") => {
5410
5423
  const now = Date.now();
5411
5424
  const elapsed = now - startMs;
5412
- const rate = submitted > 0 ? submitted / elapsed * 1e3 : 0;
5413
- const bar = `[${formatClock(now)}] ${submitted}/${total} patched=${succeeded} failed=${failed} rate=${rate.toFixed(1)}/s elapsed=${formatDuration(elapsed)}`;
5425
+ const submitRate = submitted > 0 ? submitted / elapsed * 1e3 : 0;
5426
+ let bar = `[${formatClock(now)}] submitted=${submitted}/${total} api_ok=${succeeded} api_err=${failed} rate=${submitRate.toFixed(1)}/s elapsed=${formatDuration(elapsed)}`;
5427
+ if (willWatch) {
5428
+ const procRate = procCompleted > 0 ? procCompleted / elapsed * 1e3 : 0;
5429
+ const pendingCount = procPending.size;
5430
+ const eta = procRate > 0 ? pendingCount / procRate : 0;
5431
+ bar += ` | proc_ok=${procCompleted} proc_err=${procFailed} proc_pending=${pendingCount} rate(proc)=${procRate.toFixed(1)}/s eta(processing)=${formatDuration(eta * 1e3)}`;
5432
+ }
5414
5433
  console.log(`${prefix}${bar}`);
5415
5434
  };
5416
5435
  let statusTimer;
@@ -5437,6 +5456,65 @@ function registerDocsCommand(program2) {
5437
5456
  return false;
5438
5457
  }
5439
5458
  };
5459
+ let conn = null;
5460
+ let onWatchDone = null;
5461
+ let watchDonePromise = null;
5462
+ let submissionDone = false;
5463
+ if (willWatch) {
5464
+ watchDonePromise = new Promise((r) => {
5465
+ onWatchDone = r;
5466
+ });
5467
+ try {
5468
+ conn = await sdk.connectWithReconnect({
5469
+ baseUrl: config.baseUrl,
5470
+ accessToken,
5471
+ onReconnecting: (attempt, max) => {
5472
+ warn(` WebSocket reconnecting (${attempt}/${max})...`);
5473
+ },
5474
+ onReconnectFailed: () => {
5475
+ error(' WebSocket reconnection failed. Run "arbi watch" to resume monitoring.');
5476
+ },
5477
+ onMessage: (msg) => {
5478
+ if (!client.isMessageType(msg, "task_update")) return;
5479
+ if (!procPending.has(msg.doc_ext_id)) return;
5480
+ const docName = docNames.get(msg.doc_ext_id) || msg.file_name;
5481
+ const extra = msg;
5482
+ if (msg.status === "failed") {
5483
+ procFailed += 1;
5484
+ procPending.delete(msg.doc_ext_id);
5485
+ const wsReason = extra.error_reason || extra.status_details || extra.detail || "";
5486
+ const logFailure = (reason) => {
5487
+ const suffix = reason ? ` \u2014 ${reason}` : "";
5488
+ procFailedDetails.set(msg.doc_ext_id, `${docName}${suffix}`);
5489
+ console.log(` ${docName}: ${chalk2__default.default.red("processing failed")}${suffix}`);
5490
+ if (submissionDone && procPending.size === 0) conn?.close();
5491
+ };
5492
+ if (wsReason) {
5493
+ logFailure(wsReason);
5494
+ } else {
5495
+ sdk.documents.getDocuments(arbi, [msg.doc_ext_id]).then((docs) => {
5496
+ const d = docs[0];
5497
+ logFailure(d?.error_message || "");
5498
+ }).catch(() => logFailure(""));
5499
+ }
5500
+ } else if (msg.status === "completed" || msg.status === "skipped" || msg.status === "empty") {
5501
+ procCompleted += 1;
5502
+ procPending.delete(msg.doc_ext_id);
5503
+ }
5504
+ if (msg.status !== "failed" && submissionDone && procPending.size === 0) {
5505
+ conn?.close();
5506
+ }
5507
+ },
5508
+ onClose: () => {
5509
+ onWatchDone?.();
5510
+ }
5511
+ });
5512
+ } catch {
5513
+ warn("WebSocket connection failed. Proceeding without processing watch.");
5514
+ conn = null;
5515
+ watchDonePromise = null;
5516
+ }
5517
+ }
5440
5518
  try {
5441
5519
  for (let i = 0; i < docIds.length; i += batchSize) {
5442
5520
  const batch = docIds.slice(i, i + batchSize);
@@ -5451,6 +5529,7 @@ function registerDocsCommand(program2) {
5451
5529
  if (batchOk) {
5452
5530
  succeeded += batch.length;
5453
5531
  submitted += batch.length;
5532
+ for (const id of batch) procPending.add(id);
5454
5533
  if (opts.verbose) {
5455
5534
  console.log(` [${submitted}/${total}] Triggered reprocessing...`);
5456
5535
  }
@@ -5465,6 +5544,7 @@ function registerDocsCommand(program2) {
5465
5544
  const docOk = await submitBatch([id]);
5466
5545
  if (docOk) {
5467
5546
  succeeded += 1;
5547
+ procPending.add(id);
5468
5548
  } else {
5469
5549
  failed += 1;
5470
5550
  failedIds.push(id);
@@ -5482,10 +5562,11 @@ function registerDocsCommand(program2) {
5482
5562
  } finally {
5483
5563
  if (statusTimer) clearInterval(statusTimer);
5484
5564
  }
5565
+ submissionDone = true;
5485
5566
  console.log("");
5486
5567
  printStatus();
5487
5568
  if (failed > 0) {
5488
- warn(`${failed} document(s) failed to reprocess.`);
5569
+ warn(`${failed} document(s) failed to submit.`);
5489
5570
  const preview = failedIds.slice(0, 20);
5490
5571
  preview.forEach((id) => console.log(` ${chalk2__default.default.red("\u2717")} ${id}`));
5491
5572
  if (failedIds.length > preview.length) {
@@ -5493,7 +5574,60 @@ function registerDocsCommand(program2) {
5493
5574
  }
5494
5575
  }
5495
5576
  if (succeeded > 0) {
5496
- success(`Triggered reprocessing for ${succeeded} document(s).`);
5577
+ success(`Submitted ${succeeded} document(s) for reprocessing.`);
5578
+ }
5579
+ if (watchDonePromise && conn && procPending.size > 0) {
5580
+ console.log(chalk2__default.default.bold(`
5581
+ Watching processing for ${procPending.size} document(s)...`));
5582
+ let watchTimer;
5583
+ if (!opts.quiet && statusIntervalMs > 0) {
5584
+ watchTimer = setInterval(() => printStatus(" "), statusIntervalMs);
5585
+ }
5586
+ await watchDonePromise;
5587
+ if (watchTimer) clearInterval(watchTimer);
5588
+ const totalElapsed = formatDuration(Date.now() - startMs);
5589
+ if (procFailedDetails.size > 0) {
5590
+ console.log(
5591
+ `
5592
+ Processing complete: completed=${procCompleted} failed=${procFailed} elapsed=${totalElapsed}`
5593
+ );
5594
+ error("Failed documents:");
5595
+ for (const [, detail] of procFailedDetails) {
5596
+ error(` ${detail}`);
5597
+ }
5598
+ } else if (procPending.size > 0) {
5599
+ warn(`
5600
+ Disconnected. ${procPending.size} document(s) still processing.`);
5601
+ dim('Run "arbi watch" to continue monitoring, or "arbi docs" to check status.');
5602
+ } else {
5603
+ success(
5604
+ `
5605
+ Processing complete: completed=${procCompleted} failed=0 elapsed=${totalElapsed} ${chalk2__default.default.green("\u2713 all ok")}`
5606
+ );
5607
+ }
5608
+ } else if (succeeded > 0 && !willWatch) {
5609
+ dim(
5610
+ 'Tip: Use -W/--watch to monitor processing progress, or run "arbi docs" to check status.'
5611
+ );
5612
+ } else if (watchDonePromise && conn && procPending.size === 0) {
5613
+ conn.close();
5614
+ await watchDonePromise;
5615
+ const totalElapsed = formatDuration(Date.now() - startMs);
5616
+ if (procFailedDetails.size > 0) {
5617
+ console.log(
5618
+ `
5619
+ Processing complete: completed=${procCompleted} failed=${procFailed} elapsed=${totalElapsed}`
5620
+ );
5621
+ error("Failed documents:");
5622
+ for (const [, detail] of procFailedDetails) {
5623
+ error(` ${detail}`);
5624
+ }
5625
+ } else {
5626
+ success(
5627
+ `
5628
+ Processing complete: completed=${procCompleted} failed=0 elapsed=${totalElapsed} ${chalk2__default.default.green("\u2713 all ok")}`
5629
+ );
5630
+ }
5497
5631
  }
5498
5632
  })()
5499
5633
  );
@@ -6790,6 +6924,7 @@ function printCitationDetail(num, resolved) {
6790
6924
  console.log(chalk2__default.default.dim(" (no passage data available)"));
6791
6925
  }
6792
6926
  }
6927
+ var MAX_INDIVIDUALLY_SELECTED_DOCS = 5e3;
6793
6928
  function chunkScore(chunk) {
6794
6929
  return chunk.metadata.rerank_score ?? chunk.metadata.score ?? 0;
6795
6930
  }
@@ -6802,20 +6937,28 @@ function fmtScore(score) {
6802
6937
  return `[${pct}%]`;
6803
6938
  }
6804
6939
  function registerFindCommand(program2) {
6805
- program2.command("find <query...>").description("Search documents without LLM generation (retrieve only)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-m, --mode <mode>", "Search mode: semantic, keyword, hybrid", "semantic").option("-d, --docs <ids>", "Comma-separated document IDs to search within").option("--min-score <n>", "Minimum relevance score 0-1", "0.2").option("-l, --limit <n>", "Max results to display", "20").option("--flat", "Flat list sorted by relevance (instead of grouped by document)").option("--toc <ids>", "Comma-separated doc IDs to fetch table of contents for").option("--full-context <ids>", "Comma-separated doc IDs to fetch full content for").option("--json", "Raw JSON output for scripting").action(
6940
+ program2.command("find <query...>").description("Search documents without LLM generation (retrieve only)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-m, --mode <mode>", "Search mode: semantic, keyword, hybrid", "semantic").option(
6941
+ "-d, --docs <ids>",
6942
+ `Comma-separated document IDs to search within (omit to search the whole workspace; max ${MAX_INDIVIDUALLY_SELECTED_DOCS} when set)`
6943
+ ).option("--min-score <n>", "Minimum relevance score 0-1", "0.2").option("-l, --limit <n>", "Max results to display", "20").option("--flat", "Flat list sorted by relevance (instead of grouped by document)").option("--toc <ids>", "Comma-separated doc IDs to fetch table of contents for").option("--full-context <ids>", "Comma-separated doc IDs to fetch full content for").option("--json", "Raw JSON output for scripting").action(
6806
6944
  (words, opts) => runAction(async () => {
6807
6945
  const query = words.join(" ");
6808
6946
  const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
6809
6947
  let docIds;
6810
6948
  if (opts.docs) {
6811
- docIds = opts.docs.split(",").map((id) => id.trim());
6949
+ docIds = opts.docs.split(",").map((id) => id.trim()).filter((id) => id.length > 0);
6950
+ if (docIds.length > MAX_INDIVIDUALLY_SELECTED_DOCS) {
6951
+ console.error(
6952
+ chalk2__default.default.red(
6953
+ `Error: ${docIds.length.toLocaleString()} document IDs supplied \u2014 maximum is ${MAX_INDIVIDUALLY_SELECTED_DOCS.toLocaleString()}.
6954
+ Narrow your selection, or omit -d to search the whole workspace.`
6955
+ )
6956
+ );
6957
+ process.exitCode = 1;
6958
+ return;
6959
+ }
6812
6960
  } else {
6813
- const docs = await sdk.documents.listDocuments(arbi);
6814
- docIds = docs.map((d) => d.external_id);
6815
- }
6816
- if (docIds.length === 0) {
6817
- console.log("No documents found in workspace.");
6818
- return;
6961
+ docIds = [];
6819
6962
  }
6820
6963
  const searchMode = opts.mode ?? "semantic";
6821
6964
  const tocDocIds = opts.toc ? opts.toc.split(",").map((id) => id.trim()) : void 0;
@@ -8606,7 +8749,7 @@ console.info = (...args) => {
8606
8749
  _origInfo(...args);
8607
8750
  };
8608
8751
  var program = new commander.Command();
8609
- program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.49");
8752
+ program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.51");
8610
8753
  registerConfigCommand(program);
8611
8754
  registerLoginCommand(program);
8612
8755
  registerRegisterCommand(program);