@arbidocs/cli 0.3.10 → 0.3.11

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,14 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.3.11
4
+
5
+ [compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.10...HEAD)
6
+
7
+ ### 🩹 Fixes
8
+
9
+ - Extract conversation documents from last user message instead of leaf ([#434](https://github.com/arbicity/ARBI-frontend/pull/434))
10
+ - Extract metadata from response.completed SSE event ([#435](https://github.com/arbicity/ARBI-frontend/pull/435))
11
+
3
12
  ## v0.3.10
4
13
 
5
14
  [compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.8...HEAD)
package/dist/index.js CHANGED
@@ -3502,7 +3502,7 @@ function getLatestVersion(skipCache = false) {
3502
3502
  }
3503
3503
  }
3504
3504
  function getCurrentVersion() {
3505
- return "0.3.10";
3505
+ return "0.3.11";
3506
3506
  }
3507
3507
  function readChangelog(fromVersion, toVersion) {
3508
3508
  try {
@@ -3555,17 +3555,17 @@ function showChangelog(fromVersion, toVersion) {
3555
3555
  async function checkForUpdates(autoUpdate) {
3556
3556
  try {
3557
3557
  const latest = getLatestVersion();
3558
- if (!latest || latest === "0.3.10") return;
3558
+ if (!latest || latest === "0.3.11") return;
3559
3559
  if (autoUpdate) {
3560
3560
  warn(`
3561
- Your arbi version is out of date (${"0.3.10"} \u2192 ${latest}). Updating...`);
3561
+ Your arbi version is out of date (${"0.3.11"} \u2192 ${latest}). Updating...`);
3562
3562
  child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
3563
- showChangelog("0.3.10", latest);
3563
+ showChangelog("0.3.11", latest);
3564
3564
  console.log(`Updated to ${latest}.`);
3565
3565
  } else {
3566
3566
  warn(
3567
3567
  `
3568
- Your arbi version is out of date (${"0.3.10"} \u2192 ${latest}).
3568
+ Your arbi version is out of date (${"0.3.11"} \u2192 ${latest}).
3569
3569
  Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3570
3570
  );
3571
3571
  }
@@ -3575,9 +3575,9 @@ Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3575
3575
  function hintUpdateOnError() {
3576
3576
  try {
3577
3577
  const cached = readCache();
3578
- if (cached && cached.latest !== "0.3.10") {
3578
+ if (cached && cached.latest !== "0.3.11") {
3579
3579
  warn(
3580
- `Your arbi version is out of date (${"0.3.10"} \u2192 ${cached.latest}). Run "arbi update".`
3580
+ `Your arbi version is out of date (${"0.3.11"} \u2192 ${cached.latest}). Run "arbi update".`
3581
3581
  );
3582
3582
  }
3583
3583
  } catch {
@@ -3595,30 +3595,32 @@ function registerLoginCommand(program2) {
3595
3595
  clearChatSession();
3596
3596
  const { data: workspaces2 } = await arbi.fetch.GET("/v1/user/workspaces");
3597
3597
  const wsList = workspaces2 || [];
3598
- success(`Logged in as ${email}`);
3599
- if (wsList.length === 0) {
3600
- console.log("No workspaces found.");
3598
+ const memberWorkspaces = wsList.filter((ws2) => ws2.users?.some((u) => u.email === email));
3599
+ if (memberWorkspaces.length === 0) {
3600
+ console.log("No workspaces found. Create one with: arbi workspace create <name>");
3601
3601
  return;
3602
3602
  }
3603
3603
  if (opts.workspace) {
3604
- const ws2 = wsList.find((w) => w.external_id === opts.workspace);
3604
+ const ws2 = memberWorkspaces.find((w) => w.external_id === opts.workspace);
3605
3605
  if (!ws2) {
3606
- error(`Workspace ${opts.workspace} not found.`);
3606
+ error(`Workspace ${opts.workspace} not found or you don't have access.`);
3607
3607
  process.exit(1);
3608
3608
  }
3609
3609
  updateConfig({ selectedWorkspaceId: ws2.external_id });
3610
3610
  success(`Workspace: ${ws2.name} (${ref(ws2.external_id)})`);
3611
3611
  return;
3612
3612
  }
3613
- if (wsList.length === 1) {
3614
- updateConfig({ selectedWorkspaceId: wsList[0].external_id });
3615
- success(`Workspace: ${wsList[0].name} (${ref(wsList[0].external_id)})`);
3613
+ if (memberWorkspaces.length === 1) {
3614
+ updateConfig({ selectedWorkspaceId: memberWorkspaces[0].external_id });
3615
+ success(
3616
+ `Workspace: ${memberWorkspaces[0].name} (${ref(memberWorkspaces[0].external_id)})`
3617
+ );
3616
3618
  return;
3617
3619
  }
3618
- const choices = sdk.formatWorkspaceChoices(wsList);
3620
+ const choices = sdk.formatWorkspaceChoices(memberWorkspaces);
3619
3621
  const selected = await promptSelect("Select workspace", choices);
3620
3622
  updateConfig({ selectedWorkspaceId: selected });
3621
- const ws = wsList.find((w) => w.external_id === selected);
3623
+ const ws = memberWorkspaces.find((w) => w.external_id === selected);
3622
3624
  success(`Workspace: ${ws.name} (${ref(selected)})`);
3623
3625
  dim('\nTip: Run "arbi config alias" to use A as a shortcut for "arbi ask"');
3624
3626
  } catch (err) {
@@ -3771,6 +3773,7 @@ async function nonInteractiveRegister(config, opts) {
3771
3773
  error(`Registration failed: ${sdk.getErrorMessage(err)}`);
3772
3774
  process.exit(1);
3773
3775
  }
3776
+ await loginAfterRegister(config, email, password2);
3774
3777
  }
3775
3778
  async function loginAfterRegister(config, email, password2) {
3776
3779
  try {
@@ -3778,22 +3781,23 @@ async function loginAfterRegister(config, email, password2) {
3778
3781
  success(`Logged in as ${email}`);
3779
3782
  const { data: workspaces2 } = await arbi.fetch.GET("/v1/user/workspaces");
3780
3783
  const wsList = workspaces2 || [];
3781
- if (wsList.length === 0) {
3784
+ const memberWorkspaces = wsList.filter((ws2) => ws2.users?.some((u) => u.email === email));
3785
+ if (memberWorkspaces.length === 0) {
3782
3786
  console.log("Creating your first workspace...");
3783
3787
  const ws2 = await sdk.workspaces.createWorkspace(arbi, "My First Workspace");
3784
3788
  updateConfig({ selectedWorkspaceId: ws2.external_id });
3785
3789
  success(`Workspace: ${ws2.name} (${ref(ws2.external_id)})`);
3786
3790
  return;
3787
3791
  }
3788
- if (wsList.length === 1) {
3789
- updateConfig({ selectedWorkspaceId: wsList[0].external_id });
3790
- success(`Workspace: ${wsList[0].name} (${ref(wsList[0].external_id)})`);
3792
+ if (memberWorkspaces.length === 1) {
3793
+ updateConfig({ selectedWorkspaceId: memberWorkspaces[0].external_id });
3794
+ success(`Workspace: ${memberWorkspaces[0].name} (${ref(memberWorkspaces[0].external_id)})`);
3791
3795
  return;
3792
3796
  }
3793
- const choices = sdk.formatWorkspaceChoices(wsList);
3797
+ const choices = sdk.formatWorkspaceChoices(memberWorkspaces);
3794
3798
  const selected = await promptSelect("Select workspace", choices);
3795
3799
  updateConfig({ selectedWorkspaceId: selected });
3796
- const ws = wsList.find((w) => w.external_id === selected);
3800
+ const ws = memberWorkspaces.find((w) => w.external_id === selected);
3797
3801
  success(`Workspace: ${ws.name} (${ref(selected)})`);
3798
3802
  } catch (err) {
3799
3803
  error(`Login failed: ${sdk.getErrorMessage(err)}`);
@@ -3890,13 +3894,25 @@ process.on("SIGINT", () => {
3890
3894
  });
3891
3895
 
3892
3896
  // src/helpers.ts
3897
+ function formatCliError(err) {
3898
+ if (err instanceof sdk.ArbiApiError && err.apiError && typeof err.apiError === "object") {
3899
+ const base = err.message;
3900
+ const apiErr = err.apiError;
3901
+ const detail = apiErr.detail ?? apiErr.message ?? apiErr.error;
3902
+ if (typeof detail === "string" && detail && !base.includes(detail)) {
3903
+ return `${base} \u2014 ${detail}`;
3904
+ }
3905
+ return base;
3906
+ }
3907
+ return sdk.getErrorMessage(err);
3908
+ }
3893
3909
  function runAction(fn) {
3894
3910
  return async () => {
3895
3911
  try {
3896
3912
  await fn();
3897
3913
  process.exit(0);
3898
3914
  } catch (err) {
3899
- error(`Error: ${sdk.getErrorMessage(err)}`);
3915
+ error(`Error: ${formatCliError(err)}`);
3900
3916
  hintUpdateOnError();
3901
3917
  process.exit(1);
3902
3918
  }
@@ -4028,6 +4044,10 @@ function registerWorkspacesCommand(program2) {
4028
4044
  process.exit(1);
4029
4045
  }
4030
4046
  await sdk.workspaces.deleteWorkspaces(arbi, [targetId]);
4047
+ const session = getChatSession();
4048
+ if (session.workspaceId === targetId) {
4049
+ clearChatSession();
4050
+ }
4031
4051
  success(`Deleted workspace ${targetId}`);
4032
4052
  })()
4033
4053
  );
@@ -4207,6 +4227,23 @@ function registerDocsCommand(program2) {
4207
4227
  }
4208
4228
  const data = await sdk.documents.getDocuments(arbi, docIds);
4209
4229
  console.log(JSON.stringify(data, null, 2));
4230
+ const docs = Array.isArray(data) ? data : [data];
4231
+ for (const d of docs) {
4232
+ const raw = d;
4233
+ if (raw.status === "failed") {
4234
+ const reason = raw.error_reason || raw.status_details || raw.error || null;
4235
+ const docId = raw.external_id;
4236
+ if (reason) {
4237
+ console.error(chalk__default.default.red(`
4238
+ \u26A0 ${docId} processing failed: ${reason}`));
4239
+ } else {
4240
+ console.error(
4241
+ chalk__default.default.red(`
4242
+ \u26A0 ${docId} processing failed (no error details available)`)
4243
+ );
4244
+ }
4245
+ }
4246
+ }
4210
4247
  })()
4211
4248
  );
4212
4249
  doc.command("delete [ids...]").description("Delete documents (interactive picker if no IDs given)").action(
@@ -4270,28 +4307,19 @@ function registerDocsCommand(program2) {
4270
4307
  }
4271
4308
  })()
4272
4309
  );
4273
- doc.command("parsed [doc-id] [stage]").description("Get parsed document content (stage: marker, subchunk, final)").action(
4310
+ doc.command("parsed <doc-id> [stage]").description("Get parsed document content (stage: marker, subchunk, final; default: final)").action(
4274
4311
  (docId, stage) => runAction(async () => {
4275
- const { arbi, accessToken, workspaceKeyHeader, workspaceId, config } = await resolveWorkspace();
4276
- if (!docId) {
4277
- const choices = await fetchDocChoices(arbi, workspaceId);
4278
- docId = await promptSearch("Select document", choices);
4279
- }
4312
+ const { accessToken, workspaceKeyHeader, config } = await resolveWorkspace();
4280
4313
  const validStages = ["marker", "subchunk", "final"];
4281
- if (!stage) {
4282
- stage = await promptSelect("Parsing stage", [
4283
- { name: "Final (processed)", value: "final" },
4284
- { name: "Subchunk", value: "subchunk" },
4285
- { name: "Marker (raw)", value: "marker" }
4286
- ]);
4287
- } else if (!validStages.includes(stage)) {
4288
- error(`Invalid stage: ${stage}. Must be one of: ${validStages.join(", ")}`);
4314
+ const selectedStage = stage ?? "final";
4315
+ if (!validStages.includes(selectedStage)) {
4316
+ error(`Invalid stage: ${selectedStage}. Must be one of: ${validStages.join(", ")}`);
4289
4317
  process.exit(1);
4290
4318
  }
4291
4319
  const data = await sdk.documents.getParsedContent(
4292
4320
  { baseUrl: config.baseUrl, accessToken, workspaceKeyHeader },
4293
4321
  docId,
4294
- stage
4322
+ selectedStage
4295
4323
  );
4296
4324
  console.log(JSON.stringify(data, null, 2));
4297
4325
  })()
@@ -4319,34 +4347,64 @@ function registerUploadCommand(program2) {
4319
4347
  }
4320
4348
  for (const id of result.doc_ext_ids) uploadedDocs.set(id, result.fileName);
4321
4349
  }
4322
- if (opts.watch && uploadedDocs.size > 0) {
4350
+ const isInteractive = process.stdout.isTTY === true;
4351
+ const shouldWatch = opts.watch === true || files.length === 1 && isInteractive;
4352
+ if (shouldWatch && uploadedDocs.size > 0) {
4323
4353
  const pending = new Set(uploadedDocs.keys());
4354
+ const failed = /* @__PURE__ */ new Map();
4324
4355
  console.log(`
4325
4356
  Watching ${pending.size} document(s)...`);
4357
+ let onDone;
4358
+ const done = new Promise((r) => {
4359
+ onDone = r;
4360
+ });
4326
4361
  const conn = await sdk.connectWebSocket({
4327
4362
  baseUrl: config.baseUrl,
4328
4363
  accessToken,
4329
4364
  onMessage: (msg) => {
4330
4365
  if (client.isMessageType(msg, "task_update")) {
4331
4366
  if (!pending.has(msg.doc_ext_id)) return;
4332
- console.log(
4333
- ` ${uploadedDocs.get(msg.doc_ext_id) || msg.file_name}: ${status(msg.status)} (${msg.progress}%)`
4334
- );
4335
- if (msg.status === "completed" || msg.status === "failed") {
4367
+ const docName = uploadedDocs.get(msg.doc_ext_id) || msg.file_name;
4368
+ const extra = msg;
4369
+ if (msg.status === "failed") {
4370
+ const reason = extra.error_reason || extra.status_details || extra.detail || "Unknown error";
4371
+ failed.set(msg.doc_ext_id, reason);
4372
+ console.log(` ${docName}: ${status(msg.status)} \u2014 ${reason}`);
4336
4373
  pending.delete(msg.doc_ext_id);
4337
- if (pending.size === 0) {
4338
- success("\nAll documents processed.");
4339
- conn.close();
4374
+ } else {
4375
+ console.log(` ${docName}: ${status(msg.status)} (${msg.progress}%)`);
4376
+ if (msg.status === "completed") {
4377
+ pending.delete(msg.doc_ext_id);
4340
4378
  }
4341
4379
  }
4380
+ if (pending.size === 0) {
4381
+ conn.close();
4382
+ }
4342
4383
  }
4343
4384
  },
4344
4385
  onClose: () => {
4345
- if (pending.size > 0)
4386
+ if (failed.size > 0) {
4387
+ error(`
4388
+ ${failed.size} document(s) failed to process:`);
4389
+ for (const [docId, reason] of failed) {
4390
+ error(` ${uploadedDocs.get(docId) || docId}: ${reason}`);
4391
+ }
4392
+ }
4393
+ if (pending.size > 0) {
4346
4394
  warn(`
4347
4395
  Connection closed. ${pending.size} document(s) still processing.`);
4396
+ dim('Run "arbi watch" to continue monitoring, or "arbi docs" to check status.');
4397
+ } else if (failed.size === 0 && uploadedDocs.size > 0) {
4398
+ success("\nAll documents processed successfully.");
4399
+ }
4400
+ onDone();
4348
4401
  }
4349
4402
  });
4403
+ await done;
4404
+ } else if (uploadedDocs.size > 0 && !shouldWatch) {
4405
+ dim(
4406
+ 'Tip: Use -W/--watch to monitor processing progress, or run "arbi docs" to check status.'
4407
+ );
4350
4408
  }
4351
4409
  })()
4352
4410
  );
@@ -4393,9 +4451,14 @@ function registerAskCommand(program2) {
4393
4451
  const question = words.join(" ");
4394
4452
  const { arbi, accessToken, workspaceKeyHeader, workspaceId, config } = await resolveWorkspace(opts.workspace);
4395
4453
  const session = getChatSession();
4454
+ const workspaceChanged = session.lastMessageExtId && session.workspaceId && session.workspaceId !== workspaceId;
4455
+ let previousResponseId = null;
4396
4456
  if (opts.new) {
4397
4457
  clearChatSession();
4398
- session.lastMessageExtId = null;
4458
+ } else if (workspaceChanged) {
4459
+ clearChatSession();
4460
+ } else if (session.lastMessageExtId) {
4461
+ previousResponseId = session.lastMessageExtId;
4399
4462
  }
4400
4463
  const docs = await sdk.documents.listDocuments(arbi);
4401
4464
  const docIds = docs.map((d) => d.external_id);
@@ -4408,11 +4471,11 @@ function registerAskCommand(program2) {
4408
4471
  workspaceId,
4409
4472
  question,
4410
4473
  docIds,
4411
- previousResponseId: session.lastMessageExtId,
4474
+ previousResponseId,
4412
4475
  model: opts.config
4413
4476
  });
4414
4477
  } catch (err) {
4415
- const isStaleParent = session.lastMessageExtId && err instanceof Error && err.message.includes("Parent message not found");
4478
+ const isStaleParent = previousResponseId && err instanceof Error && (err.message.includes("404") || err.message.includes("Parent message not found"));
4416
4479
  if (!isStaleParent) throw err;
4417
4480
  clearChatSession();
4418
4481
  res = await sdk.assistant.queryAssistant({
@@ -4441,7 +4504,8 @@ Error: ${message}`))
4441
4504
  process.stdout.write("\n");
4442
4505
  if (result.assistantMessageExtId) {
4443
4506
  const updates = {
4444
- lastMessageExtId: result.assistantMessageExtId
4507
+ lastMessageExtId: result.assistantMessageExtId,
4508
+ workspaceId
4445
4509
  };
4446
4510
  const conversationExtId = result.userMessage?.conversation_ext_id ?? result.metadata?.conversation_ext_id;
4447
4511
  if (conversationExtId) {
@@ -4463,6 +4527,10 @@ function registerWatchCommand(program2) {
4463
4527
  (opts) => runAction(async () => {
4464
4528
  const { config, accessToken, workspaceId } = await resolveWorkspace(opts.workspace);
4465
4529
  console.log(`Watching workspace ${workspaceId}... (Ctrl+C to stop)`);
4530
+ let onDone;
4531
+ const done = new Promise((r) => {
4532
+ onDone = r;
4533
+ });
4466
4534
  await sdk.connectWebSocket({
4467
4535
  baseUrl: config.baseUrl,
4468
4536
  accessToken,
@@ -4475,8 +4543,10 @@ function registerWatchCommand(program2) {
4475
4543
  chalk__default.default.yellow(`
4476
4544
  Connection closed (code ${code}${reason ? ": " + reason : ""})`)
4477
4545
  );
4546
+ onDone();
4478
4547
  }
4479
4548
  });
4549
+ await done;
4480
4550
  })()
4481
4551
  );
4482
4552
  }
@@ -5313,7 +5383,7 @@ console.info = (...args) => {
5313
5383
  _origInfo(...args);
5314
5384
  };
5315
5385
  var program = new commander.Command();
5316
- program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.10");
5386
+ program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.11");
5317
5387
  registerConfigCommand(program);
5318
5388
  registerLoginCommand(program);
5319
5389
  registerRegisterCommand(program);