@arbidocs/cli 0.3.11 → 0.3.14

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 CHANGED
@@ -5,8 +5,8 @@ var commander = require('commander');
5
5
  var fs = require('fs');
6
6
  var os = require('os');
7
7
  var path = require('path');
8
+ var chalk2 = require('chalk');
8
9
  var sdk = require('@arbidocs/sdk');
9
- var chalk = require('chalk');
10
10
  var prompts = require('@inquirer/prompts');
11
11
  var child_process = require('child_process');
12
12
  var client = require('@arbidocs/client');
@@ -18,7 +18,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
18
18
  var fs__default = /*#__PURE__*/_interopDefault(fs);
19
19
  var os__default = /*#__PURE__*/_interopDefault(os);
20
20
  var path__default = /*#__PURE__*/_interopDefault(path);
21
- var chalk__default = /*#__PURE__*/_interopDefault(chalk);
21
+ var chalk2__default = /*#__PURE__*/_interopDefault(chalk2);
22
22
 
23
23
  var store = new sdk.FileConfigStore();
24
24
  function getConfig() {
@@ -38,6 +38,13 @@ function requireConfig() {
38
38
  throw err;
39
39
  }
40
40
  }
41
+ function resolveConfig() {
42
+ const { config, source } = store.resolveConfigWithFallbacks();
43
+ if (source !== "config") {
44
+ console.error(chalk2__default.default.dim(`Using server URL from ${source}: ${config.baseUrl}`));
45
+ }
46
+ return config;
47
+ }
41
48
  function getCredentials() {
42
49
  return store.getCredentials();
43
50
  }
@@ -54,32 +61,32 @@ function clearChatSession() {
54
61
  store.clearChatSession();
55
62
  }
56
63
  function success(msg) {
57
- console.log(chalk__default.default.green(msg));
64
+ console.log(chalk2__default.default.green(msg));
58
65
  }
59
66
  function error(msg) {
60
- console.error(chalk__default.default.red(msg));
67
+ console.error(chalk2__default.default.red(msg));
61
68
  }
62
69
  function warn(msg) {
63
- console.error(chalk__default.default.yellow(msg));
70
+ console.error(chalk2__default.default.yellow(msg));
64
71
  }
65
72
  function label(key, value) {
66
- console.log(`${chalk__default.default.bold(key)} ${value}`);
73
+ console.log(`${chalk2__default.default.bold(key)} ${value}`);
67
74
  }
68
75
  function dim(msg) {
69
- console.log(chalk__default.default.dim(msg));
76
+ console.log(chalk2__default.default.dim(msg));
70
77
  }
71
78
  function bold(msg) {
72
- console.log(chalk__default.default.bold(msg));
79
+ console.log(chalk2__default.default.bold(msg));
73
80
  }
74
81
  function status(s) {
75
82
  const lower = s.toLowerCase();
76
- if (["healthy", "completed", "available", "online", "on"].includes(lower)) return chalk__default.default.green(s);
77
- if (["failed", "error", "unavailable", "offline"].includes(lower)) return chalk__default.default.red(s);
78
- if (["processing", "pending", "degraded", "warning"].includes(lower)) return chalk__default.default.yellow(s);
83
+ if (["healthy", "completed", "available", "online", "on"].includes(lower)) return chalk2__default.default.green(s);
84
+ if (["failed", "error", "unavailable", "offline"].includes(lower)) return chalk2__default.default.red(s);
85
+ if (["processing", "pending", "degraded", "warning"].includes(lower)) return chalk2__default.default.yellow(s);
79
86
  return s;
80
87
  }
81
88
  function ref(s) {
82
- return chalk__default.default.cyan(s);
89
+ return chalk2__default.default.cyan(s);
83
90
  }
84
91
 
85
92
  // src/commands/config-cmd.ts
@@ -118,7 +125,9 @@ function registerConfigCommand(program2) {
118
125
  label("Server URL:", cfg.baseUrl);
119
126
  label("Domain:", cfg.deploymentDomain);
120
127
  label("Auto-update:", cfg.autoUpdate ? "on" : "off");
121
- label("Notifications:", cfg.notifications ? "on" : "off");
128
+ label("Verbose:", cfg.verbose !== false ? "on" : "off");
129
+ label("Watch:", cfg.watch !== false ? "on" : "off");
130
+ label("Notifications:", cfg.notifications !== false ? "on" : "off");
122
131
  if (cfg.selectedWorkspaceId) {
123
132
  label("Workspace:", cfg.selectedWorkspaceId);
124
133
  }
@@ -126,7 +135,7 @@ function registerConfigCommand(program2) {
126
135
  config.command("notifications [on|off]").description("Toggle background WebSocket notifications").action((toggle) => {
127
136
  const cfg = getConfig();
128
137
  if (!toggle) {
129
- label("Notifications:", cfg?.notifications ? "on" : "off");
138
+ label("Notifications:", cfg?.notifications !== false ? "on" : "off");
130
139
  return;
131
140
  }
132
141
  if (toggle !== "on" && toggle !== "off") {
@@ -136,6 +145,32 @@ function registerConfigCommand(program2) {
136
145
  updateConfig({ notifications: toggle === "on" });
137
146
  success(`Notifications: ${toggle}`);
138
147
  });
148
+ config.command("verbose [on|off]").description("Toggle verbose agent steps in ask (default: on)").action((toggle) => {
149
+ const cfg = getConfig();
150
+ if (!toggle) {
151
+ label("Verbose:", cfg?.verbose !== false ? "on" : "off");
152
+ return;
153
+ }
154
+ if (toggle !== "on" && toggle !== "off") {
155
+ error("Usage: arbi config verbose [on|off]");
156
+ process.exit(1);
157
+ }
158
+ updateConfig({ verbose: toggle === "on" });
159
+ success(`Verbose: ${toggle}`);
160
+ });
161
+ config.command("watch [on|off]").description("Toggle upload watch (default: on)").action((toggle) => {
162
+ const cfg = getConfig();
163
+ if (!toggle) {
164
+ label("Watch:", cfg?.watch !== false ? "on" : "off");
165
+ return;
166
+ }
167
+ if (toggle !== "on" && toggle !== "off") {
168
+ error("Usage: arbi config watch [on|off]");
169
+ process.exit(1);
170
+ }
171
+ updateConfig({ watch: toggle === "on" });
172
+ success(`Watch: ${toggle}`);
173
+ });
139
174
  config.command("alias").description('Set up shell alias A for "arbi ask"').action(() => {
140
175
  const rcPath = getShellRcPath();
141
176
  if (isAliasInstalled(rcPath)) {
@@ -3502,7 +3537,7 @@ function getLatestVersion(skipCache = false) {
3502
3537
  }
3503
3538
  }
3504
3539
  function getCurrentVersion() {
3505
- return "0.3.11";
3540
+ return "0.3.14";
3506
3541
  }
3507
3542
  function readChangelog(fromVersion, toVersion) {
3508
3543
  try {
@@ -3555,17 +3590,17 @@ function showChangelog(fromVersion, toVersion) {
3555
3590
  async function checkForUpdates(autoUpdate) {
3556
3591
  try {
3557
3592
  const latest = getLatestVersion();
3558
- if (!latest || latest === "0.3.11") return;
3593
+ if (!latest || latest === "0.3.14") return;
3559
3594
  if (autoUpdate) {
3560
3595
  warn(`
3561
- Your arbi version is out of date (${"0.3.11"} \u2192 ${latest}). Updating...`);
3596
+ Your arbi version is out of date (${"0.3.14"} \u2192 ${latest}). Updating...`);
3562
3597
  child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
3563
- showChangelog("0.3.11", latest);
3598
+ showChangelog("0.3.14", latest);
3564
3599
  console.log(`Updated to ${latest}.`);
3565
3600
  } else {
3566
3601
  warn(
3567
3602
  `
3568
- Your arbi version is out of date (${"0.3.11"} \u2192 ${latest}).
3603
+ Your arbi version is out of date (${"0.3.14"} \u2192 ${latest}).
3569
3604
  Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3570
3605
  );
3571
3606
  }
@@ -3575,9 +3610,9 @@ Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3575
3610
  function hintUpdateOnError() {
3576
3611
  try {
3577
3612
  const cached = readCache();
3578
- if (cached && cached.latest !== "0.3.11") {
3613
+ if (cached && cached.latest !== "0.3.14") {
3579
3614
  warn(
3580
- `Your arbi version is out of date (${"0.3.11"} \u2192 ${cached.latest}). Run "arbi update".`
3615
+ `Your arbi version is out of date (${"0.3.14"} \u2192 ${cached.latest}). Run "arbi update".`
3581
3616
  );
3582
3617
  }
3583
3618
  } catch {
@@ -3658,7 +3693,11 @@ function registerRegisterCommand(program2) {
3658
3693
  });
3659
3694
  }
3660
3695
  async function smartRegister(config, opts) {
3661
- const email = opts.email || process.env.ARBI_EMAIL || await promptInput("Email");
3696
+ let email = opts.email || process.env.ARBI_EMAIL || await promptInput("Email");
3697
+ if ((opts.email || process.env.ARBI_EMAIL) && !email.includes("@")) {
3698
+ email = `${email}@${config.deploymentDomain}`;
3699
+ console.log(`Using email: ${email}`);
3700
+ }
3662
3701
  const arbi = client.createArbiClient({
3663
3702
  baseUrl: config.baseUrl,
3664
3703
  deploymentDomain: config.deploymentDomain,
@@ -3724,13 +3763,17 @@ Registered successfully as ${email}`);
3724
3763
  }
3725
3764
  }
3726
3765
  async function nonInteractiveRegister(config, opts) {
3727
- const email = opts.email || process.env.ARBI_EMAIL;
3766
+ let email = opts.email || process.env.ARBI_EMAIL;
3728
3767
  const password2 = opts.password || process.env.ARBI_PASSWORD;
3729
3768
  const supportApiKey = process.env.SUPPORT_API_KEY;
3730
3769
  if (!email) {
3731
3770
  error("Email required. Use --email <email> or set ARBI_EMAIL");
3732
3771
  process.exit(1);
3733
3772
  }
3773
+ if (!email.includes("@")) {
3774
+ email = `${email}@${config.deploymentDomain}`;
3775
+ console.log(`Using email: ${email}`);
3776
+ }
3734
3777
  if (!password2) {
3735
3778
  error("Password required. Use --password <password> or set ARBI_PASSWORD");
3736
3779
  process.exit(1);
@@ -3837,14 +3880,62 @@ function registerStatusCommand(program2) {
3837
3880
  }
3838
3881
  });
3839
3882
  }
3883
+ var MAX_TASKS = 50;
3884
+ var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
3885
+ function getTasksFile() {
3886
+ const configDir = process.env.ARBI_CONFIG_DIR ?? path__default.default.join(os__default.default.homedir(), ".arbi");
3887
+ return path__default.default.join(configDir, "tasks.json");
3888
+ }
3889
+ function ensureDir(filePath) {
3890
+ const dir = path__default.default.dirname(filePath);
3891
+ if (!fs__default.default.existsSync(dir)) {
3892
+ fs__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
3893
+ }
3894
+ }
3895
+ function readTasks() {
3896
+ try {
3897
+ const content = fs__default.default.readFileSync(getTasksFile(), "utf-8");
3898
+ return JSON.parse(content);
3899
+ } catch {
3900
+ return [];
3901
+ }
3902
+ }
3903
+ function writeTasks(tasks) {
3904
+ const filePath = getTasksFile();
3905
+ ensureDir(filePath);
3906
+ fs__default.default.writeFileSync(filePath, JSON.stringify(tasks, null, 2) + "\n", { mode: 384 });
3907
+ }
3908
+ function getTasks() {
3909
+ const now = Date.now();
3910
+ const tasks = readTasks().filter((t) => now - new Date(t.submittedAt).getTime() < MAX_AGE_MS);
3911
+ return tasks;
3912
+ }
3913
+ function addTask(task) {
3914
+ const tasks = [task, ...getTasks().filter((t) => t.id !== task.id)].slice(0, MAX_TASKS);
3915
+ writeTasks(tasks);
3916
+ }
3917
+ function updateTaskStatus(id, status2) {
3918
+ const tasks = readTasks();
3919
+ const task = tasks.find((t) => t.id === id);
3920
+ if (task) {
3921
+ task.status = status2;
3922
+ writeTasks(tasks);
3923
+ }
3924
+ }
3925
+ function getLatestTask() {
3926
+ const tasks = getTasks();
3927
+ return tasks[0] ?? null;
3928
+ }
3929
+
3930
+ // src/notifications.ts
3840
3931
  var activeConnection = null;
3841
3932
  function timestamp() {
3842
3933
  return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-GB", { hour12: false });
3843
3934
  }
3844
3935
  function colorize(level, text) {
3845
- if (level === "success") return chalk__default.default.green(text);
3846
- if (level === "error") return chalk__default.default.red(text);
3847
- if (level === "warning") return chalk__default.default.yellow(text);
3936
+ if (level === "success") return chalk2__default.default.green(text);
3937
+ if (level === "error") return chalk2__default.default.red(text);
3938
+ if (level === "warning") return chalk2__default.default.yellow(text);
3848
3939
  return text;
3849
3940
  }
3850
3941
  async function startBackgroundNotifications(baseUrl, accessToken) {
@@ -3854,6 +3945,9 @@ async function startBackgroundNotifications(baseUrl, accessToken) {
3854
3945
  baseUrl,
3855
3946
  accessToken,
3856
3947
  onMessage: (msg) => {
3948
+ if (client.isMessageType(msg, "response_complete")) {
3949
+ updateTaskStatus(msg.response_id, msg.status);
3950
+ }
3857
3951
  const { text, level } = sdk.formatWsMessage(msg);
3858
3952
  process.stderr.write(`
3859
3953
  ${colorize(level, `[${timestamp()}] ${text}`)}
@@ -3865,18 +3959,18 @@ ${colorize(level, `[${timestamp()}] ${text}`)}
3865
3959
  onReconnecting: (attempt, maxRetries) => {
3866
3960
  process.stderr.write(
3867
3961
  `
3868
- ${chalk__default.default.yellow(`[${timestamp()}] Reconnecting... (${attempt}/${maxRetries})`)}
3962
+ ${chalk2__default.default.yellow(`[${timestamp()}] Reconnecting... (${attempt}/${maxRetries})`)}
3869
3963
  `
3870
3964
  );
3871
3965
  },
3872
3966
  onReconnected: () => {
3873
3967
  process.stderr.write(`
3874
- ${chalk__default.default.green(`[${timestamp()}] Reconnected`)}
3968
+ ${chalk2__default.default.green(`[${timestamp()}] Reconnected`)}
3875
3969
  `);
3876
3970
  },
3877
3971
  onReconnectFailed: () => {
3878
3972
  process.stderr.write(`
3879
- ${chalk__default.default.red(`[${timestamp()}] Reconnection failed`)}
3973
+ ${chalk2__default.default.red(`[${timestamp()}] Reconnection failed`)}
3880
3974
  `);
3881
3975
  }
3882
3976
  });
@@ -3894,7 +3988,31 @@ process.on("SIGINT", () => {
3894
3988
  });
3895
3989
 
3896
3990
  // src/helpers.ts
3991
+ var CONNECTION_ERROR_HINTS = {
3992
+ ECONNREFUSED: "Connection refused. Is the backend running?",
3993
+ ECONNRESET: "Connection reset by server. The backend may have restarted.",
3994
+ ENOTFOUND: "DNS resolution failed. Check the server URL.",
3995
+ ETIMEDOUT: "Connection timed out. Check network connectivity.",
3996
+ UNABLE_TO_VERIFY_LEAF_SIGNATURE: "TLS certificate cannot be verified. The cert may be expired or self-signed.",
3997
+ CERT_HAS_EXPIRED: "TLS certificate has expired. Renew with manage-deployment.",
3998
+ ERR_TLS_CERT_ALTNAME_INVALID: "TLS certificate hostname mismatch. Check the server URL.",
3999
+ DEPTH_ZERO_SELF_SIGNED_CERT: "Self-signed TLS certificate. The cert may need to be renewed.",
4000
+ SELF_SIGNED_CERT_IN_CHAIN: "Self-signed certificate in chain. The cert may need to be renewed."
4001
+ };
4002
+ function diagnoseConnectionError(err) {
4003
+ const code = sdk.getErrorCode(err);
4004
+ if (code && code in CONNECTION_ERROR_HINTS) {
4005
+ return CONNECTION_ERROR_HINTS[code];
4006
+ }
4007
+ const msg = err instanceof Error ? err.message : "";
4008
+ if (msg === "fetch failed" || msg.includes("fetch failed")) {
4009
+ return "Network error connecting to the server. Run `arbi health` to diagnose.";
4010
+ }
4011
+ return void 0;
4012
+ }
3897
4013
  function formatCliError(err) {
4014
+ const connectionHint = diagnoseConnectionError(err);
4015
+ if (connectionHint) return connectionHint;
3898
4016
  if (err instanceof sdk.ArbiApiError && err.apiError && typeof err.apiError === "object") {
3899
4017
  const base = err.message;
3900
4018
  const apiErr = err.apiError;
@@ -3920,6 +4038,7 @@ function runAction(fn) {
3920
4038
  }
3921
4039
  async function resolveAuth() {
3922
4040
  try {
4041
+ resolveConfig();
3923
4042
  return await sdk.resolveAuth(store);
3924
4043
  } catch (err) {
3925
4044
  if (err instanceof sdk.ArbiError) {
@@ -3931,8 +4050,9 @@ async function resolveAuth() {
3931
4050
  }
3932
4051
  async function resolveWorkspace(workspaceOpt) {
3933
4052
  try {
4053
+ resolveConfig();
3934
4054
  const ctx = await sdk.resolveWorkspace(store, workspaceOpt);
3935
- if (getConfig()?.notifications) {
4055
+ if (getConfig()?.notifications !== false) {
3936
4056
  startBackgroundNotifications(ctx.config.baseUrl, ctx.accessToken).catch(() => {
3937
4057
  });
3938
4058
  }
@@ -3946,7 +4066,7 @@ async function resolveWorkspace(workspaceOpt) {
3946
4066
  }
3947
4067
  }
3948
4068
  function printTable(columns, rows) {
3949
- console.log(chalk__default.default.bold(columns.map((c) => c.header.padEnd(c.width)).join("")));
4069
+ console.log(chalk2__default.default.bold(columns.map((c) => c.header.padEnd(c.width)).join("")));
3950
4070
  for (const row of rows) {
3951
4071
  console.log(
3952
4072
  columns.map((c) => {
@@ -4234,11 +4354,11 @@ function registerDocsCommand(program2) {
4234
4354
  const reason = raw.error_reason || raw.status_details || raw.error || null;
4235
4355
  const docId = raw.external_id;
4236
4356
  if (reason) {
4237
- console.error(chalk__default.default.red(`
4357
+ console.error(chalk2__default.default.red(`
4238
4358
  \u26A0 ${docId} processing failed: ${reason}`));
4239
4359
  } else {
4240
4360
  console.error(
4241
- chalk__default.default.red(`
4361
+ chalk2__default.default.red(`
4242
4362
  \u26A0 ${docId} processing failed (no error details available)`)
4243
4363
  );
4244
4364
  }
@@ -4326,11 +4446,11 @@ function registerDocsCommand(program2) {
4326
4446
  );
4327
4447
  }
4328
4448
  function registerUploadCommand(program2) {
4329
- program2.command("upload <files...>").description("Upload documents to the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-W, --watch", "Watch document processing progress after upload").action(
4330
- (files, opts) => runAction(async () => {
4331
- for (const f of files) {
4332
- if (!fs__default.default.existsSync(f)) {
4333
- error(`File not found: ${f}`);
4449
+ program2.command("add <paths...>").alias("upload").description("Add files, directories, or zip archives to the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-W, --watch", "Watch document processing progress after upload").option("--no-watch", "Skip watching document processing").action(
4450
+ (paths, opts) => runAction(async () => {
4451
+ for (const p of paths) {
4452
+ if (!fs__default.default.existsSync(p)) {
4453
+ error(`Path not found: ${p}`);
4334
4454
  process.exit(1);
4335
4455
  }
4336
4456
  }
@@ -4339,16 +4459,54 @@ function registerUploadCommand(program2) {
4339
4459
  );
4340
4460
  const uploadedDocs = /* @__PURE__ */ new Map();
4341
4461
  const auth = { baseUrl: config.baseUrl, accessToken, workspaceKeyHeader };
4342
- for (const filePath of files) {
4343
- const result = await sdk.documents.uploadLocalFile(auth, workspaceId, filePath);
4344
- success(`Uploaded: ${result.fileName} (${result.doc_ext_ids.join(", ")})`);
4345
- if (result.duplicates && result.duplicates.length > 0) {
4346
- warn(` Duplicates: ${result.duplicates.join(", ")}`);
4462
+ for (const filePath of paths) {
4463
+ const stat = fs__default.default.statSync(filePath);
4464
+ if (stat.isDirectory()) {
4465
+ const result = await sdk.documentsNode.uploadDirectory(auth, workspaceId, filePath);
4466
+ if (result.doc_ext_ids.length === 0) {
4467
+ warn(`No supported files found in directory: ${filePath}`);
4468
+ continue;
4469
+ }
4470
+ for (const [folder, info] of result.folders) {
4471
+ success(
4472
+ ` ${folder}: ${info.fileCount} file(s) \u2192 ${info.doc_ext_ids.length} uploaded`
4473
+ );
4474
+ if (info.duplicates.length > 0) {
4475
+ warn(` Duplicates: ${info.duplicates.join(", ")}`);
4476
+ }
4477
+ }
4478
+ success(
4479
+ `Uploaded directory: ${filePath} (${result.doc_ext_ids.length} document(s) total)`
4480
+ );
4481
+ for (const id of result.doc_ext_ids) uploadedDocs.set(id, filePath);
4482
+ } else if (filePath.toLowerCase().endsWith(".zip")) {
4483
+ const result = await sdk.documentsNode.uploadZip(auth, workspaceId, filePath);
4484
+ if (result.doc_ext_ids.length === 0) {
4485
+ warn(`No supported files found in zip: ${filePath}`);
4486
+ continue;
4487
+ }
4488
+ for (const [folder, info] of result.folders) {
4489
+ success(
4490
+ ` ${folder}: ${info.fileCount} file(s) \u2192 ${info.doc_ext_ids.length} uploaded`
4491
+ );
4492
+ if (info.duplicates.length > 0) {
4493
+ warn(` Duplicates: ${info.duplicates.join(", ")}`);
4494
+ }
4495
+ }
4496
+ success(`Uploaded zip: ${filePath} (${result.doc_ext_ids.length} document(s) total)`);
4497
+ for (const id of result.doc_ext_ids) uploadedDocs.set(id, filePath);
4498
+ } else {
4499
+ const result = await sdk.documentsNode.uploadLocalFile(auth, workspaceId, filePath);
4500
+ success(`Uploaded: ${result.fileName} (${result.doc_ext_ids.join(", ")})`);
4501
+ if (result.duplicates && result.duplicates.length > 0) {
4502
+ warn(` Duplicates: ${result.duplicates.join(", ")}`);
4503
+ }
4504
+ for (const id of result.doc_ext_ids) uploadedDocs.set(id, result.fileName);
4347
4505
  }
4348
- for (const id of result.doc_ext_ids) uploadedDocs.set(id, result.fileName);
4349
4506
  }
4350
4507
  const isInteractive = process.stdout.isTTY === true;
4351
- const shouldWatch = opts.watch === true || files.length === 1 && isInteractive;
4508
+ const watchPref = getConfig()?.watch !== false;
4509
+ const shouldWatch = opts.watch === false ? false : opts.watch === true || watchPref && isInteractive;
4352
4510
  if (shouldWatch && uploadedDocs.size > 0) {
4353
4511
  const pending = new Set(uploadedDocs.keys());
4354
4512
  const failed = /* @__PURE__ */ new Map();
@@ -4446,22 +4604,55 @@ function registerDownloadCommand(program2) {
4446
4604
  );
4447
4605
  }
4448
4606
  function registerAskCommand(program2) {
4449
- program2.command("ask <question...>").description("Ask the RAG assistant a question (no quotes needed)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-c, --config <id>", "Config ext_id to use (e.g. cfg-xxx)").option("-n, --new", "Start a new conversation (ignore previous context)").option("-v, --verbose", "Show agent steps and tool calls").action(
4607
+ program2.command("ask <question...>").description("Ask the RAG assistant a question (no quotes needed)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-c, --continue <msg-id>", "Continue from a specific message ID").option("--config <id>", "Config ext_id to use (e.g. cfg-xxx)").option("-n, --new", "Start a new conversation (ignore previous context)").option("-b, --background", "Submit as background task (fire and forget)").option("-q, --quiet", "Suppress agent steps and tool calls").option("--json", "Output in JSON format (background mode only)").action(
4450
4608
  (words, opts) => runAction(async () => {
4451
4609
  const question = words.join(" ");
4452
4610
  const { arbi, accessToken, workspaceKeyHeader, workspaceId, config } = await resolveWorkspace(opts.workspace);
4453
- const session = getChatSession();
4454
- const workspaceChanged = session.lastMessageExtId && session.workspaceId && session.workspaceId !== workspaceId;
4455
4611
  let previousResponseId = null;
4456
- if (opts.new) {
4612
+ if (opts.continue) {
4613
+ previousResponseId = opts.continue;
4614
+ } else if (opts.new) {
4457
4615
  clearChatSession();
4458
- } else if (workspaceChanged) {
4459
- clearChatSession();
4460
- } else if (session.lastMessageExtId) {
4461
- previousResponseId = session.lastMessageExtId;
4616
+ } else {
4617
+ const session = getChatSession();
4618
+ const workspaceChanged = session.lastMessageExtId && session.workspaceId && session.workspaceId !== workspaceId;
4619
+ if (workspaceChanged) {
4620
+ clearChatSession();
4621
+ } else if (session.lastMessageExtId) {
4622
+ previousResponseId = session.lastMessageExtId;
4623
+ }
4462
4624
  }
4463
4625
  const docs = await sdk.documents.listDocuments(arbi);
4464
4626
  const docIds = docs.map((d) => d.external_id);
4627
+ if (opts.background) {
4628
+ const result2 = await sdk.responses.submitBackgroundQuery({
4629
+ baseUrl: config.baseUrl,
4630
+ accessToken,
4631
+ workspaceKeyHeader,
4632
+ workspaceId,
4633
+ question,
4634
+ docIds,
4635
+ previousResponseId,
4636
+ model: opts.config
4637
+ });
4638
+ addTask({
4639
+ id: result2.id,
4640
+ question: question.slice(0, 200),
4641
+ workspaceId,
4642
+ submittedAt: (/* @__PURE__ */ new Date()).toISOString(),
4643
+ status: "queued",
4644
+ model: result2.model
4645
+ });
4646
+ if (opts.json) {
4647
+ console.log(JSON.stringify({ id: result2.id, status: result2.status }));
4648
+ } else {
4649
+ console.log(`Task queued: ${chalk2__default.default.cyan(result2.id)}`);
4650
+ console.log(
4651
+ chalk2__default.default.dim("Use `arbi task status` or `arbi task result` to check progress.")
4652
+ );
4653
+ }
4654
+ return;
4655
+ }
4465
4656
  let res;
4466
4657
  try {
4467
4658
  res = await sdk.assistant.queryAssistant({
@@ -4489,19 +4680,47 @@ function registerAskCommand(program2) {
4489
4680
  model: opts.config
4490
4681
  });
4491
4682
  }
4683
+ const verbose = opts.quiet === true ? false : getConfig()?.verbose !== false;
4684
+ let elapsedTime = null;
4492
4685
  const result = await sdk.streamSSE(res, {
4493
4686
  onToken: (content) => process.stdout.write(content),
4494
4687
  onAgentStep: (data) => {
4495
- if (opts.verbose) {
4496
- const focus = data.focus || data.step || "";
4497
- console.error(chalk__default.default.dim(`
4498
- [agent] ${focus}`));
4688
+ if (verbose) {
4689
+ const label2 = sdk.formatAgentStepLabel(data);
4690
+ if (label2) console.error(chalk2__default.default.dim(`
4691
+ [agent] ${label2}`));
4499
4692
  }
4500
4693
  },
4501
- onError: (message) => console.error(chalk__default.default.red(`
4694
+ onElapsedTime: (t) => {
4695
+ elapsedTime = t;
4696
+ },
4697
+ onError: (message) => console.error(chalk2__default.default.red(`
4502
4698
  Error: ${message}`))
4503
4699
  });
4504
4700
  process.stdout.write("\n");
4701
+ const parts = [];
4702
+ if (result.agentSteps.length > 0) {
4703
+ let stepLabel = `${result.agentSteps.length} step${result.agentSteps.length === 1 ? "" : "s"}`;
4704
+ if (result.toolCallCount > 0) {
4705
+ stepLabel += ` (${result.toolCallCount} tool call${result.toolCallCount === 1 ? "" : "s"})`;
4706
+ }
4707
+ parts.push(stepLabel);
4708
+ }
4709
+ if (result.usage) {
4710
+ parts.push(`${result.usage.total_tokens.toLocaleString()} tokens`);
4711
+ }
4712
+ if (result.context && result.context.context_window > 0) {
4713
+ const used = result.context.all_llm_calls?.last_input_tokens ?? result.context.total_input;
4714
+ parts.push(
4715
+ `${used.toLocaleString()}/${result.context.context_window.toLocaleString()} context`
4716
+ );
4717
+ }
4718
+ if (elapsedTime != null) {
4719
+ parts.push(`${elapsedTime.toFixed(1)}s`);
4720
+ }
4721
+ if (parts.length > 0) {
4722
+ console.error(chalk2__default.default.dim(`[${parts.join(" \xB7 ")}]`));
4723
+ }
4505
4724
  if (result.assistantMessageExtId) {
4506
4725
  const updates = {
4507
4726
  lastMessageExtId: result.assistantMessageExtId,
@@ -4517,36 +4736,73 @@ Error: ${message}`))
4517
4736
  );
4518
4737
  }
4519
4738
  function colorize2(level, text) {
4520
- if (level === "success") return chalk__default.default.green(text);
4521
- if (level === "error") return chalk__default.default.red(text);
4522
- if (level === "warning") return chalk__default.default.yellow(text);
4739
+ if (level === "success") return chalk2__default.default.green(text);
4740
+ if (level === "error") return chalk2__default.default.red(text);
4741
+ if (level === "warning") return chalk2__default.default.yellow(text);
4523
4742
  return text;
4524
4743
  }
4525
4744
  function registerWatchCommand(program2) {
4526
- program2.command("watch").description("Watch workspace activity in real time").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
4745
+ program2.command("watch").description("Watch workspace activity in real time").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-t, --timeout <seconds>", "Auto-close after N seconds").option("-n, --count <n>", "Stop after N messages").option("--json", "Output NDJSON (one JSON object per line)").action(
4527
4746
  (opts) => runAction(async () => {
4528
4747
  const { config, accessToken, workspaceId } = await resolveWorkspace(opts.workspace);
4529
- console.log(`Watching workspace ${workspaceId}... (Ctrl+C to stop)`);
4748
+ const timeoutSec = opts.timeout ? parseInt(opts.timeout, 10) : void 0;
4749
+ const maxCount = opts.count ? parseInt(opts.count, 10) : void 0;
4750
+ const jsonMode = opts.json ?? false;
4751
+ if (!jsonMode) {
4752
+ const parts = [`Watching workspace ${workspaceId}...`];
4753
+ if (timeoutSec) parts.push(`(timeout: ${timeoutSec}s)`);
4754
+ if (maxCount) parts.push(`(max: ${maxCount} messages)`);
4755
+ parts.push("(Ctrl+C to stop)");
4756
+ console.log(parts.join(" "));
4757
+ }
4758
+ let messageCount = 0;
4530
4759
  let onDone;
4531
4760
  const done = new Promise((r) => {
4532
4761
  onDone = r;
4533
4762
  });
4534
- await sdk.connectWebSocket({
4763
+ const conn = await sdk.connectWebSocket({
4535
4764
  baseUrl: config.baseUrl,
4536
4765
  accessToken,
4537
4766
  onMessage: (msg) => {
4538
- const { text, level } = sdk.formatWsMessage(msg);
4539
- console.log(colorize2(level, text));
4767
+ messageCount++;
4768
+ if (jsonMode) {
4769
+ console.log(JSON.stringify(msg));
4770
+ } else {
4771
+ const { text, level } = sdk.formatWsMessage(msg);
4772
+ console.log(colorize2(level, text));
4773
+ }
4774
+ if (maxCount && messageCount >= maxCount) {
4775
+ if (!jsonMode) console.log(chalk2__default.default.dim(`
4776
+ Reached ${maxCount} messages, closing.`));
4777
+ conn.close();
4778
+ }
4540
4779
  },
4541
4780
  onClose: (code, reason) => {
4542
- console.log(
4543
- chalk__default.default.yellow(`
4781
+ if (!jsonMode) {
4782
+ console.log(
4783
+ chalk2__default.default.yellow(`
4544
4784
  Connection closed (code ${code}${reason ? ": " + reason : ""})`)
4545
- );
4785
+ );
4786
+ }
4546
4787
  onDone();
4547
4788
  }
4548
4789
  });
4790
+ let timer;
4791
+ if (timeoutSec) {
4792
+ timer = setTimeout(() => {
4793
+ if (!jsonMode) console.log(chalk2__default.default.dim(`
4794
+ Timeout (${timeoutSec}s), closing.`));
4795
+ conn.close();
4796
+ }, timeoutSec * 1e3);
4797
+ }
4798
+ const sigintHandler = () => {
4799
+ if (timer) clearTimeout(timer);
4800
+ conn.close();
4801
+ };
4802
+ process.on("SIGINT", sigintHandler);
4549
4803
  await done;
4804
+ if (timer) clearTimeout(timer);
4805
+ process.removeListener("SIGINT", sigintHandler);
4550
4806
  })()
4551
4807
  );
4552
4808
  }
@@ -5373,6 +5629,326 @@ Updated to ${latest}.`);
5373
5629
  success("Auto-update enabled. ARBI CLI will update automatically on login.");
5374
5630
  });
5375
5631
  }
5632
+ function registerQuickstartCommand(program2) {
5633
+ program2.command("quickstart").description("Interactive setup wizard \u2014 configure, register/login, and select a workspace").argument("[url]", "Server URL (auto-detected if omitted)").action(async (url) => {
5634
+ console.log("\nWelcome to ARBI CLI setup!\n");
5635
+ const { config, source } = store.resolveConfigWithFallbacks();
5636
+ if (url) {
5637
+ const domain = new URL(url).hostname;
5638
+ config.baseUrl = url.replace(/\/$/, "");
5639
+ config.deploymentDomain = domain;
5640
+ store.saveConfig(config);
5641
+ }
5642
+ const useDetected = await promptConfirm(`Use server ${config.baseUrl}?`, true);
5643
+ if (!useDetected) {
5644
+ const customUrl = await promptInput("Server URL");
5645
+ try {
5646
+ const domain = new URL(customUrl).hostname;
5647
+ config.baseUrl = customUrl.replace(/\/$/, "");
5648
+ config.deploymentDomain = domain;
5649
+ store.saveConfig(config);
5650
+ } catch {
5651
+ error("Invalid URL");
5652
+ process.exit(1);
5653
+ }
5654
+ } else if (source !== "config") {
5655
+ store.saveConfig(config);
5656
+ }
5657
+ dim(`Server: ${config.baseUrl}`);
5658
+ const action = await promptSelect("Do you have an account?", [
5659
+ { name: "Yes, log me in", value: "login" },
5660
+ { name: "No, register a new account", value: "register" }
5661
+ ]);
5662
+ const arbiClient = client.createArbiClient({
5663
+ baseUrl: config.baseUrl,
5664
+ deploymentDomain: config.deploymentDomain,
5665
+ credentials: "omit"
5666
+ });
5667
+ await arbiClient.crypto.initSodium();
5668
+ let email;
5669
+ let password2;
5670
+ if (action === "register") {
5671
+ email = await promptInput("Email");
5672
+ password2 = await promptPassword("Password");
5673
+ const confirmPw = await promptPassword("Confirm password");
5674
+ if (password2 !== confirmPw) {
5675
+ error("Passwords do not match.");
5676
+ process.exit(1);
5677
+ }
5678
+ const codeMethod = await promptSelect("Verification method", [
5679
+ { name: "I have an invitation code", value: "code" },
5680
+ { name: "Send me a verification email", value: "email" }
5681
+ ]);
5682
+ let verificationCode;
5683
+ if (codeMethod === "code") {
5684
+ verificationCode = await promptInput("Invitation code");
5685
+ } else {
5686
+ console.log("Sending verification email...");
5687
+ const verifyResponse = await arbiClient.fetch.POST("/v1/user/verify-email", {
5688
+ body: { email }
5689
+ });
5690
+ if (verifyResponse.error) {
5691
+ error(`Failed to send verification email: ${JSON.stringify(verifyResponse.error)}`);
5692
+ process.exit(1);
5693
+ }
5694
+ success("Verification email sent. Check your inbox.");
5695
+ verificationCode = await promptInput("Verification code");
5696
+ }
5697
+ try {
5698
+ const firstName = await promptInput("First name", false) || "User";
5699
+ const lastName = await promptInput("Last name", false) || "";
5700
+ await arbiClient.auth.register({
5701
+ email,
5702
+ password: password2,
5703
+ verificationCode,
5704
+ firstName,
5705
+ lastName
5706
+ });
5707
+ success(`Registered as ${email}`);
5708
+ } catch (err) {
5709
+ error(`Registration failed: ${sdk.getErrorMessage(err)}`);
5710
+ process.exit(1);
5711
+ }
5712
+ } else {
5713
+ email = await promptInput("Email");
5714
+ password2 = await promptPassword("Password");
5715
+ }
5716
+ try {
5717
+ const { arbi } = await sdk.performPasswordLogin(config, email, password2, store);
5718
+ success(`Logged in as ${email}`);
5719
+ const { data: workspaces2 } = await arbi.fetch.GET("/v1/user/workspaces");
5720
+ const wsList = workspaces2 || [];
5721
+ const memberWorkspaces = wsList.filter((ws) => ws.users?.some((u) => u.email === email));
5722
+ let workspaceId;
5723
+ let workspaceName;
5724
+ if (memberWorkspaces.length === 0) {
5725
+ console.log("Creating your first workspace...");
5726
+ const ws = await sdk.workspaces.createWorkspace(arbi, "My Workspace");
5727
+ workspaceId = ws.external_id;
5728
+ workspaceName = ws.name;
5729
+ } else {
5730
+ const choices = [
5731
+ ...sdk.formatWorkspaceChoices(memberWorkspaces),
5732
+ { name: "+ Create new workspace", value: "__new__", description: "" }
5733
+ ];
5734
+ const selected = await promptSelect("Select workspace", choices);
5735
+ if (selected === "__new__") {
5736
+ const name = await promptInput("Workspace name", false) || "My Workspace";
5737
+ const ws = await sdk.workspaces.createWorkspace(arbi, name);
5738
+ workspaceId = ws.external_id;
5739
+ workspaceName = ws.name;
5740
+ } else {
5741
+ workspaceId = selected;
5742
+ workspaceName = memberWorkspaces.find((w) => w.external_id === selected)?.name || "";
5743
+ }
5744
+ }
5745
+ updateConfig({ selectedWorkspaceId: workspaceId });
5746
+ console.log("");
5747
+ success("Setup complete!");
5748
+ console.log("");
5749
+ console.log(` Server: ${ref(config.baseUrl)}`);
5750
+ console.log(` Account: ${ref(email)}`);
5751
+ console.log(` Workspace: ${workspaceName} (${ref(workspaceId)})`);
5752
+ console.log("");
5753
+ dim('Try: arbi ask "hello"');
5754
+ } catch (err) {
5755
+ error(`Login failed: ${sdk.getErrorMessage(err)}`);
5756
+ process.exit(1);
5757
+ }
5758
+ });
5759
+ }
5760
+ var CENTRAL_API_URL2 = "https://central.arbi.work";
5761
+ var DEFAULT_PASSWORD = "agent-dev-1234";
5762
+ async function getVerificationCode2(email, apiKey) {
5763
+ const params = new URLSearchParams({ email });
5764
+ const res = await fetch(`${CENTRAL_API_URL2}/license-management/verify-ci?${params.toString()}`, {
5765
+ method: "GET",
5766
+ headers: { "x-api-key": apiKey }
5767
+ });
5768
+ if (!res.ok) {
5769
+ const body = await res.text().catch(() => "");
5770
+ throw new Error(`Failed to get verification code: ${res.status} ${body}`);
5771
+ }
5772
+ const data = await res.json();
5773
+ const words = data?.verification_words ?? data?.verification_code ?? null;
5774
+ if (!words) throw new Error("No verification code in response");
5775
+ return Array.isArray(words) ? words.join(" ") : String(words);
5776
+ }
5777
+ function registerAgentCreateCommand(program2) {
5778
+ program2.command("agent-create").description("Create a bot/test account (requires SUPPORT_API_KEY)").argument("[url]", "Server URL (auto-detected if omitted)").option("-p, --password <password>", "Account password", DEFAULT_PASSWORD).option("--workspace-name <name>", "Workspace name", "Agent Workspace").option("--email <email>", "Custom email (default: agent-{timestamp}@{domain})").action(
5779
+ async (url, opts) => {
5780
+ const { config, source } = store.resolveConfigWithFallbacks();
5781
+ if (url) {
5782
+ const domain = new URL(url).hostname;
5783
+ config.baseUrl = url.replace(/\/$/, "");
5784
+ config.deploymentDomain = domain;
5785
+ store.saveConfig(config);
5786
+ dim(`Server: ${config.baseUrl}`);
5787
+ } else {
5788
+ dim(`Server: ${config.baseUrl} (from ${source})`);
5789
+ }
5790
+ const supportApiKey = process.env.SUPPORT_API_KEY;
5791
+ if (!supportApiKey) {
5792
+ error(
5793
+ "SUPPORT_API_KEY is required.\nSet it with: export SUPPORT_API_KEY=<key>\nOr source from .env: source .env && arbi agent-create"
5794
+ );
5795
+ process.exit(1);
5796
+ }
5797
+ const timestamp2 = Date.now();
5798
+ let email = opts.email || `agent-${timestamp2}@${config.deploymentDomain}`;
5799
+ if (!email.includes("@")) {
5800
+ email = `${email}@${config.deploymentDomain}`;
5801
+ }
5802
+ dim(`Email: ${email}`);
5803
+ const arbiClient = client.createArbiClient({
5804
+ baseUrl: config.baseUrl,
5805
+ deploymentDomain: config.deploymentDomain,
5806
+ credentials: "omit"
5807
+ });
5808
+ await arbiClient.crypto.initSodium();
5809
+ const verifyResponse = await arbiClient.fetch.POST("/v1/user/verify-email", {
5810
+ body: { email }
5811
+ });
5812
+ if (verifyResponse.error) {
5813
+ error(`verify-email failed: ${JSON.stringify(verifyResponse.error)}`);
5814
+ process.exit(1);
5815
+ }
5816
+ let verificationCode;
5817
+ try {
5818
+ verificationCode = await getVerificationCode2(email, supportApiKey);
5819
+ } catch (err) {
5820
+ error(`Failed to get verification code: ${sdk.getErrorMessage(err)}`);
5821
+ process.exit(1);
5822
+ }
5823
+ try {
5824
+ await arbiClient.auth.register({
5825
+ email,
5826
+ password: opts.password,
5827
+ verificationCode,
5828
+ firstName: "Agent",
5829
+ lastName: `${timestamp2}`
5830
+ });
5831
+ } catch (err) {
5832
+ error(`Registration failed: ${sdk.getErrorMessage(err)}`);
5833
+ process.exit(1);
5834
+ }
5835
+ try {
5836
+ const { arbi } = await sdk.performPasswordLogin(config, email, opts.password, store);
5837
+ const ws = await sdk.workspaces.createWorkspace(arbi, opts.workspaceName);
5838
+ updateConfig({ selectedWorkspaceId: ws.external_id });
5839
+ console.log("");
5840
+ success("Agent account created!");
5841
+ console.log("");
5842
+ console.log(` Email: ${ref(email)}`);
5843
+ console.log(` Password: ${ref(opts.password)}`);
5844
+ console.log(` Workspace: ${ws.name} (${ref(ws.external_id)})`);
5845
+ console.log(` Server: ${ref(config.baseUrl)}`);
5846
+ console.log("");
5847
+ dim('Ready to use: arbi ask "hello"');
5848
+ } catch (err) {
5849
+ error(`Post-registration setup failed: ${sdk.getErrorMessage(err)}`);
5850
+ process.exit(1);
5851
+ }
5852
+ }
5853
+ );
5854
+ }
5855
+ function formatAge(isoDate) {
5856
+ const ms = Date.now() - new Date(isoDate).getTime();
5857
+ if (ms < 6e4) return `${Math.round(ms / 1e3)}s`;
5858
+ if (ms < 36e5) return `${Math.round(ms / 6e4)}m`;
5859
+ if (ms < 864e5) return `${Math.round(ms / 36e5)}h`;
5860
+ return `${Math.round(ms / 864e5)}d`;
5861
+ }
5862
+ function resolveTaskId(taskIdArg) {
5863
+ if (taskIdArg) return taskIdArg;
5864
+ const latest = getLatestTask();
5865
+ if (!latest) {
5866
+ console.error(chalk2__default.default.red('No tasks found. Submit one with: arbi ask -b "your question"'));
5867
+ process.exit(1);
5868
+ }
5869
+ return latest.id;
5870
+ }
5871
+ function statusColor(s) {
5872
+ if (s === "completed") return chalk2__default.default.green(s);
5873
+ if (s === "failed") return chalk2__default.default.red(s);
5874
+ if (s === "queued" || s === "in_progress") return chalk2__default.default.yellow(s);
5875
+ return s;
5876
+ }
5877
+ function registerTaskCommand(program2) {
5878
+ const task = program2.command("task").description("Manage background tasks");
5879
+ task.action(async (_opts, cmd) => {
5880
+ await cmd.commands.find((c) => c.name() === "list").parseAsync([], { from: "user" });
5881
+ });
5882
+ task.command("list").description("List background tasks").action(
5883
+ () => runAction(async () => {
5884
+ const tasks = getTasks();
5885
+ if (tasks.length === 0) {
5886
+ console.log('No tasks. Submit one with: arbi ask -b "your question"');
5887
+ return;
5888
+ }
5889
+ printTable(
5890
+ [
5891
+ { header: "ID", width: 20, value: (r) => r.id },
5892
+ { header: "STATUS", width: 14, value: (r) => statusColor(r.status) },
5893
+ { header: "QUESTION", width: 42, value: (r) => r.question },
5894
+ { header: "AGE", width: 6, value: (r) => formatAge(r.submittedAt) }
5895
+ ],
5896
+ tasks
5897
+ );
5898
+ })()
5899
+ );
5900
+ task.command("status [task-id]").description("Check current task status (defaults to most recent)").option("-w, --workspace <id>", "Workspace ID").option("--json", "Output in JSON format").action(
5901
+ (taskId, opts) => runAction(async () => {
5902
+ const id = resolveTaskId(taskId);
5903
+ const { accessToken, workspaceKeyHeader, config } = await resolveWorkspace(opts?.workspace);
5904
+ const result = await sdk.responses.getResponse(
5905
+ { baseUrl: config.baseUrl, accessToken, workspaceKeyHeader },
5906
+ id
5907
+ );
5908
+ if (result.status === "completed" || result.status === "failed") {
5909
+ updateTaskStatus(id, result.status);
5910
+ }
5911
+ if (opts?.json) {
5912
+ console.log(JSON.stringify(result, null, 2));
5913
+ } else {
5914
+ console.log(`${chalk2__default.default.bold("ID:")} ${result.id}`);
5915
+ console.log(`${chalk2__default.default.bold("Status:")} ${statusColor(result.status)}`);
5916
+ if (result.model) console.log(`${chalk2__default.default.bold("Model:")} ${result.model}`);
5917
+ if (result.usage) {
5918
+ console.log(`${chalk2__default.default.bold("Tokens:")} ${result.usage.total_tokens.toLocaleString()}`);
5919
+ }
5920
+ }
5921
+ })()
5922
+ );
5923
+ task.command("result [task-id]").description("Fetch and print the completed task result").option("-w, --workspace <id>", "Workspace ID").option("--json", "Output in JSON format").action(
5924
+ (taskId, opts) => runAction(async () => {
5925
+ const id = resolveTaskId(taskId);
5926
+ const { accessToken, workspaceKeyHeader, config } = await resolveWorkspace(opts?.workspace);
5927
+ const result = await sdk.responses.getResponse(
5928
+ { baseUrl: config.baseUrl, accessToken, workspaceKeyHeader },
5929
+ id
5930
+ );
5931
+ if (result.status === "completed" || result.status === "failed") {
5932
+ updateTaskStatus(id, result.status);
5933
+ }
5934
+ if (opts?.json) {
5935
+ console.log(JSON.stringify(result, null, 2));
5936
+ return;
5937
+ }
5938
+ if (result.status !== "completed") {
5939
+ console.error(
5940
+ chalk2__default.default.yellow(`Task is ${result.status}. Use \`arbi task status\` to check progress.`)
5941
+ );
5942
+ process.exit(1);
5943
+ }
5944
+ const text = sdk.responses.extractResponseText(result);
5945
+ process.stdout.write(text + "\n");
5946
+ if (result.usage) {
5947
+ console.error(chalk2__default.default.dim(`[${result.usage.total_tokens.toLocaleString()} tokens]`));
5948
+ }
5949
+ })()
5950
+ );
5951
+ }
5376
5952
 
5377
5953
  // src/index.ts
5378
5954
  console.debug = () => {
@@ -5383,7 +5959,7 @@ console.info = (...args) => {
5383
5959
  _origInfo(...args);
5384
5960
  };
5385
5961
  var program = new commander.Command();
5386
- program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.11");
5962
+ program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.14");
5387
5963
  registerConfigCommand(program);
5388
5964
  registerLoginCommand(program);
5389
5965
  registerRegisterCommand(program);
@@ -5405,6 +5981,9 @@ registerAgentconfigCommand(program);
5405
5981
  registerHealthCommand(program);
5406
5982
  registerTuiCommand(program);
5407
5983
  registerUpdateCommand(program);
5984
+ registerQuickstartCommand(program);
5985
+ registerAgentCreateCommand(program);
5986
+ registerTaskCommand(program);
5408
5987
  program.parse();
5409
5988
  //# sourceMappingURL=index.js.map
5410
5989
  //# sourceMappingURL=index.js.map