@arbidocs/cli 0.3.3 → 0.3.5

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.
@@ -2,11 +2,12 @@
2
2
  'use strict';
3
3
 
4
4
  var commander = require('commander');
5
- var core = require('@arbidocs/core');
6
- var prompts = require('@inquirer/prompts');
7
5
  var fs = require('fs');
8
- var path = require('path');
9
6
  var os = require('os');
7
+ var path = require('path');
8
+ var core = require('@arbidocs/core');
9
+ var chalk = require('chalk');
10
+ var prompts = require('@inquirer/prompts');
10
11
  var child_process = require('child_process');
11
12
  var sdk = require('@arbidocs/sdk');
12
13
  var module$1 = require('module');
@@ -15,8 +16,9 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
15
16
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
17
 
17
18
  var fs__default = /*#__PURE__*/_interopDefault(fs);
18
- var path__default = /*#__PURE__*/_interopDefault(path);
19
19
  var os__default = /*#__PURE__*/_interopDefault(os);
20
+ var path__default = /*#__PURE__*/_interopDefault(path);
21
+ var chalk__default = /*#__PURE__*/_interopDefault(chalk);
20
22
 
21
23
  var store = new core.FileConfigStore();
22
24
  function getConfig() {
@@ -51,8 +53,48 @@ function updateChatSession(updates) {
51
53
  function clearChatSession() {
52
54
  store.clearChatSession();
53
55
  }
56
+ function success(msg) {
57
+ console.log(chalk__default.default.green(msg));
58
+ }
59
+ function error(msg) {
60
+ console.error(chalk__default.default.red(msg));
61
+ }
62
+ function warn(msg) {
63
+ console.error(chalk__default.default.yellow(msg));
64
+ }
65
+ function label(key, value) {
66
+ console.log(`${chalk__default.default.bold(key)} ${value}`);
67
+ }
68
+ function dim(msg) {
69
+ console.log(chalk__default.default.dim(msg));
70
+ }
71
+ function bold(msg) {
72
+ console.log(chalk__default.default.bold(msg));
73
+ }
74
+ function status(s) {
75
+ 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);
79
+ return s;
80
+ }
81
+ function ref(s) {
82
+ return chalk__default.default.cyan(s);
83
+ }
54
84
 
55
85
  // src/commands/config-cmd.ts
86
+ var ALIAS_LINE = 'alias A="arbi ask"';
87
+ var ALIAS_MARKER = "# arbi-cli alias";
88
+ function getShellRcPath() {
89
+ const shell = process.env.SHELL || "";
90
+ if (shell.includes("zsh")) return path.join(os.homedir(), ".zshrc");
91
+ return path.join(os.homedir(), ".bashrc");
92
+ }
93
+ function isAliasInstalled(rcPath) {
94
+ if (!fs.existsSync(rcPath)) return false;
95
+ const content = fs.readFileSync(rcPath, "utf-8");
96
+ return content.includes(ALIAS_LINE) || content.includes(ALIAS_MARKER);
97
+ }
56
98
  function registerConfigCommand(program2) {
57
99
  const config = program2.command("config").description("Manage CLI configuration");
58
100
  config.command("set-url <url>").description("Set the ARBI server URL").action((url) => {
@@ -60,25 +102,55 @@ function registerConfigCommand(program2) {
60
102
  const parsed = new URL(url);
61
103
  const deploymentDomain = parsed.hostname;
62
104
  updateConfig({ baseUrl: url.replace(/\/+$/, ""), deploymentDomain });
63
- console.log(`Server URL: ${url}`);
64
- console.log(`Domain: ${deploymentDomain}`);
105
+ label("Server URL:", url);
106
+ label("Domain:", deploymentDomain);
65
107
  } catch {
66
- console.error(`Invalid URL: ${url}`);
108
+ error(`Invalid URL: ${url}`);
67
109
  process.exit(1);
68
110
  }
69
111
  });
70
112
  config.command("show").description("Show current configuration").action(() => {
71
113
  const cfg = getConfig();
72
114
  if (!cfg) {
73
- console.log("Not configured. Run: arbi config set-url <url>");
115
+ dim("Not configured. Run: arbi config set-url <url>");
74
116
  return;
75
117
  }
76
- console.log(`Server URL: ${cfg.baseUrl}`);
77
- console.log(`Domain: ${cfg.deploymentDomain}`);
78
- console.log(`Auto-update: ${cfg.autoUpdate ? "on" : "off"}`);
118
+ label("Server URL:", cfg.baseUrl);
119
+ label("Domain:", cfg.deploymentDomain);
120
+ label("Auto-update:", cfg.autoUpdate ? "on" : "off");
121
+ label("Notifications:", cfg.notifications ? "on" : "off");
79
122
  if (cfg.selectedWorkspaceId) {
80
- console.log(`Workspace: ${cfg.selectedWorkspaceId}`);
123
+ label("Workspace:", cfg.selectedWorkspaceId);
124
+ }
125
+ });
126
+ config.command("notifications [on|off]").description("Toggle background WebSocket notifications").action((toggle) => {
127
+ const cfg = getConfig();
128
+ if (!toggle) {
129
+ label("Notifications:", cfg?.notifications ? "on" : "off");
130
+ return;
131
+ }
132
+ if (toggle !== "on" && toggle !== "off") {
133
+ error("Usage: arbi config notifications [on|off]");
134
+ process.exit(1);
135
+ }
136
+ updateConfig({ notifications: toggle === "on" });
137
+ success(`Notifications: ${toggle}`);
138
+ });
139
+ config.command("alias").description('Set up shell alias A for "arbi ask"').action(() => {
140
+ const rcPath = getShellRcPath();
141
+ if (isAliasInstalled(rcPath)) {
142
+ success(`Alias already set up in ${rcPath}`);
143
+ dim("Usage: A what is the meaning of life");
144
+ return;
81
145
  }
146
+ fs.appendFileSync(rcPath, `
147
+ ${ALIAS_MARKER}
148
+ ${ALIAS_LINE}
149
+ `);
150
+ success(`Added alias A="arbi ask" to ${rcPath}`);
151
+ dim("");
152
+ dim(`Run: source ${rcPath}`);
153
+ dim("Then: A what is the meaning of life");
82
154
  });
83
155
  }
84
156
 
@@ -94,8 +166,8 @@ var messages = {
94
166
  TransactionInactiveError: "A request was placed against a transaction which is currently not active, or which is finished.",
95
167
  VersionError: "An attempt was made to open a database using a lower version than the existing version."
96
168
  };
97
- var setErrorCode = (error, value) => {
98
- Object.defineProperty(error, "code", {
169
+ var setErrorCode = (error2, value) => {
170
+ Object.defineProperty(error2, "code", {
99
171
  value,
100
172
  writable: false,
101
173
  enumerable: true,
@@ -3429,7 +3501,7 @@ function getLatestVersion() {
3429
3501
  }
3430
3502
  }
3431
3503
  function getCurrentVersion() {
3432
- return "0.3.3";
3504
+ return "0.3.5";
3433
3505
  }
3434
3506
  async function fetchChangelog(fromVersion, toVersion) {
3435
3507
  try {
@@ -3473,19 +3545,17 @@ async function showChangelog(fromVersion, toVersion) {
3473
3545
  async function checkForUpdates(autoUpdate) {
3474
3546
  try {
3475
3547
  const latest = getLatestVersion();
3476
- if (!latest || latest === "0.3.3") return;
3548
+ if (!latest || latest === "0.3.5") return;
3477
3549
  if (autoUpdate) {
3478
- console.log(
3479
- `
3480
- Your arbi version is out of date (${"0.3.3"} \u2192 ${latest}). Updating...`
3481
- );
3482
- await showChangelog("0.3.3", latest);
3550
+ warn(`
3551
+ Your arbi version is out of date (${"0.3.5"} \u2192 ${latest}). Updating...`);
3552
+ await showChangelog("0.3.5", latest);
3483
3553
  child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
3484
3554
  console.log(`Updated to ${latest}.`);
3485
3555
  } else {
3486
- console.error(
3556
+ warn(
3487
3557
  `
3488
- Your arbi version is out of date (${"0.3.3"} \u2192 ${latest}).
3558
+ Your arbi version is out of date (${"0.3.5"} \u2192 ${latest}).
3489
3559
  Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3490
3560
  );
3491
3561
  }
@@ -3495,9 +3565,9 @@ Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3495
3565
  function hintUpdateOnError() {
3496
3566
  try {
3497
3567
  const cached = readCache();
3498
- if (cached && cached.latest !== "0.3.3") {
3499
- console.error(
3500
- `Your arbi version is out of date (${"0.3.3"} \u2192 ${cached.latest}). Run "arbi update".`
3568
+ if (cached && cached.latest !== "0.3.5") {
3569
+ warn(
3570
+ `Your arbi version is out of date (${"0.3.5"} \u2192 ${cached.latest}). Run "arbi update".`
3501
3571
  );
3502
3572
  }
3503
3573
  } catch {
@@ -3514,7 +3584,7 @@ function registerLoginCommand(program2) {
3514
3584
  const { arbi } = await core.performPasswordLogin(config, email, pw, store);
3515
3585
  const { data: workspaces2 } = await arbi.fetch.GET("/api/user/workspaces");
3516
3586
  const wsList = workspaces2 || [];
3517
- console.log(`Logged in as ${email}`);
3587
+ success(`Logged in as ${email}`);
3518
3588
  if (wsList.length === 0) {
3519
3589
  console.log("No workspaces found.");
3520
3590
  return;
@@ -3522,25 +3592,26 @@ function registerLoginCommand(program2) {
3522
3592
  if (opts.workspace) {
3523
3593
  const ws2 = wsList.find((w) => w.external_id === opts.workspace);
3524
3594
  if (!ws2) {
3525
- console.error(`Workspace ${opts.workspace} not found.`);
3595
+ error(`Workspace ${opts.workspace} not found.`);
3526
3596
  process.exit(1);
3527
3597
  }
3528
3598
  updateConfig({ selectedWorkspaceId: ws2.external_id });
3529
- console.log(`Workspace: ${ws2.name} (${ws2.external_id})`);
3599
+ success(`Workspace: ${ws2.name} (${ref(ws2.external_id)})`);
3530
3600
  return;
3531
3601
  }
3532
3602
  if (wsList.length === 1) {
3533
3603
  updateConfig({ selectedWorkspaceId: wsList[0].external_id });
3534
- console.log(`Workspace: ${wsList[0].name} (${wsList[0].external_id})`);
3604
+ success(`Workspace: ${wsList[0].name} (${ref(wsList[0].external_id)})`);
3535
3605
  return;
3536
3606
  }
3537
3607
  const choices = core.formatWorkspaceChoices(wsList);
3538
3608
  const selected = await promptSelect("Select workspace", choices);
3539
3609
  updateConfig({ selectedWorkspaceId: selected });
3540
3610
  const ws = wsList.find((w) => w.external_id === selected);
3541
- console.log(`Workspace: ${ws.name} (${selected})`);
3611
+ success(`Workspace: ${ws.name} (${ref(selected)})`);
3612
+ dim('\nTip: Run "arbi config alias" to use A as a shortcut for "arbi ask"');
3542
3613
  } catch (err) {
3543
- console.error(`Login failed: ${core.getErrorMessage(err)}`);
3614
+ error(`Login failed: ${core.getErrorMessage(err)}`);
3544
3615
  process.exit(1);
3545
3616
  } finally {
3546
3617
  await checkForUpdates(getConfig()?.autoUpdate);
@@ -3564,7 +3635,7 @@ async function getVerificationCode(email, apiKey) {
3564
3635
  return Array.isArray(words) ? words.join(" ") : String(words);
3565
3636
  }
3566
3637
  function registerRegisterCommand(program2) {
3567
- program2.command("register").description("Register a new ARBI account").option("--non-interactive", "CI/automation mode (requires SUPPORT_API_KEY env var)").option("-e, --email <email>", "Email address (or ARBI_EMAIL env var)").option("-p, --password <password>", "Password (or ARBI_PASSWORD env var)").option("-c, --verification-code <code>", "Verification code (skip prompt)").option("--first-name <name>", "First name").option("--last-name <name>", "Last name").option("-w, --workspace <id>", "Workspace ID to select after login").action(async (opts) => {
3638
+ program2.command("register").description("Register a new ARBI account").option("--non-interactive", "CI/automation mode (requires SUPPORT_API_KEY env var)").option("-e, --email <email>", "Email address (or ARBI_EMAIL env var)").option("-p, --password <password>", "Password (or ARBI_PASSWORD env var)").option("-c, --verification-code <code>", "Verification code (skip prompt)").option("--first-name <name>", "First name").option("--last-name <name>", "Last name").action(async (opts) => {
3568
3639
  const config = requireConfig();
3569
3640
  if (opts.nonInteractive) {
3570
3641
  await nonInteractiveRegister(config, opts);
@@ -3597,10 +3668,10 @@ async function smartRegister(config, opts) {
3597
3668
  body: { email }
3598
3669
  });
3599
3670
  if (verifyResponse.error) {
3600
- console.error(`Failed to send verification email: ${JSON.stringify(verifyResponse.error)}`);
3671
+ error(`Failed to send verification email: ${JSON.stringify(verifyResponse.error)}`);
3601
3672
  process.exit(1);
3602
3673
  }
3603
- console.log("Verification email sent. Check your inbox.");
3674
+ success("Verification email sent. Check your inbox.");
3604
3675
  verificationCode = await promptInput("Verification code");
3605
3676
  }
3606
3677
  }
@@ -3612,7 +3683,7 @@ async function smartRegister(config, opts) {
3612
3683
  pw = await promptPassword("Password");
3613
3684
  const confirmPw = await promptPassword("Confirm password");
3614
3685
  if (pw !== confirmPw) {
3615
- console.error("Passwords do not match.");
3686
+ error("Passwords do not match.");
3616
3687
  process.exit(1);
3617
3688
  }
3618
3689
  }
@@ -3627,16 +3698,16 @@ async function smartRegister(config, opts) {
3627
3698
  firstName,
3628
3699
  lastName
3629
3700
  });
3630
- console.log(`
3701
+ success(`
3631
3702
  Registered successfully as ${email}`);
3632
3703
  } catch (err) {
3633
- console.error(`Registration failed: ${core.getErrorMessage(err)}`);
3704
+ error(`Registration failed: ${core.getErrorMessage(err)}`);
3634
3705
  process.exit(1);
3635
3706
  }
3636
3707
  const allFlagsProvided = !!(opts.email || process.env.ARBI_EMAIL) && !!(opts.password || process.env.ARBI_PASSWORD) && !!opts.verificationCode;
3637
3708
  const doLogin = allFlagsProvided || await promptConfirm("Log in now?");
3638
3709
  if (doLogin) {
3639
- await loginAfterRegister(config, email, pw, opts.workspace);
3710
+ await loginAfterRegister(config, email, pw);
3640
3711
  }
3641
3712
  }
3642
3713
  async function nonInteractiveRegister(config, opts) {
@@ -3644,11 +3715,11 @@ async function nonInteractiveRegister(config, opts) {
3644
3715
  const password2 = opts.password || process.env.ARBI_PASSWORD;
3645
3716
  const supportApiKey = process.env.SUPPORT_API_KEY;
3646
3717
  if (!email) {
3647
- console.error("Email required. Use --email <email> or set ARBI_EMAIL");
3718
+ error("Email required. Use --email <email> or set ARBI_EMAIL");
3648
3719
  process.exit(1);
3649
3720
  }
3650
3721
  if (!password2) {
3651
- console.error("Password required. Use --password <password> or set ARBI_PASSWORD");
3722
+ error("Password required. Use --password <password> or set ARBI_PASSWORD");
3652
3723
  process.exit(1);
3653
3724
  }
3654
3725
  const arbi = sdk.createArbiClient({
@@ -3662,7 +3733,7 @@ async function nonInteractiveRegister(config, opts) {
3662
3733
  verificationCode = opts.verificationCode;
3663
3734
  } else {
3664
3735
  if (!supportApiKey) {
3665
- console.error(
3736
+ error(
3666
3737
  "Verification code required. Use --verification-code <code> or set SUPPORT_API_KEY for CI mode"
3667
3738
  );
3668
3739
  process.exit(1);
@@ -3671,7 +3742,7 @@ async function nonInteractiveRegister(config, opts) {
3671
3742
  body: { email }
3672
3743
  });
3673
3744
  if (verifyResponse.error) {
3674
- console.error(`verify-email failed: ${JSON.stringify(verifyResponse.error)}`);
3745
+ error(`verify-email failed: ${JSON.stringify(verifyResponse.error)}`);
3675
3746
  process.exit(1);
3676
3747
  }
3677
3748
  verificationCode = await getVerificationCode(email, supportApiKey);
@@ -3684,42 +3755,38 @@ async function nonInteractiveRegister(config, opts) {
3684
3755
  firstName: opts.firstName ?? "Test",
3685
3756
  lastName: opts.lastName ?? "User"
3686
3757
  });
3687
- console.log(`Registered: ${email}`);
3758
+ success(`Registered: ${email}`);
3688
3759
  } catch (err) {
3689
- console.error(`Registration failed: ${core.getErrorMessage(err)}`);
3760
+ error(`Registration failed: ${core.getErrorMessage(err)}`);
3690
3761
  process.exit(1);
3691
3762
  }
3692
3763
  }
3693
- async function loginAfterRegister(config, email, password2, workspaceId) {
3764
+ async function loginAfterRegister(config, email, password2) {
3694
3765
  try {
3695
3766
  const { arbi } = await core.performPasswordLogin(config, email, password2, store);
3767
+ success(`Logged in as ${email}`);
3696
3768
  const { data: workspaces2 } = await arbi.fetch.GET("/api/user/workspaces");
3697
3769
  const wsList = workspaces2 || [];
3698
- console.log(`Logged in as ${email}`);
3699
- if (wsList.length === 0) return;
3700
- if (workspaceId) {
3701
- const ws = wsList.find((w) => w.external_id === workspaceId);
3702
- if (ws) {
3703
- updateConfig({ selectedWorkspaceId: ws.external_id });
3704
- console.log(`Workspace: ${ws.name} (${ws.external_id})`);
3705
- } else {
3706
- console.error(`Workspace ${workspaceId} not found.`);
3707
- }
3770
+ if (wsList.length === 0) {
3771
+ console.log("Creating your first workspace...");
3772
+ const ws2 = await core.workspaces.createWorkspace(arbi, "My First Workspace");
3773
+ updateConfig({ selectedWorkspaceId: ws2.external_id });
3774
+ success(`Workspace: ${ws2.name} (${ref(ws2.external_id)})`);
3708
3775
  return;
3709
3776
  }
3710
3777
  if (wsList.length === 1) {
3711
3778
  updateConfig({ selectedWorkspaceId: wsList[0].external_id });
3712
- console.log(`Workspace: ${wsList[0].name} (${wsList[0].external_id})`);
3713
- } else if (wsList.length > 1) {
3714
- const choices = core.formatWorkspaceChoices(wsList);
3715
- const selected = await promptSelect("Select workspace", choices);
3716
- updateConfig({ selectedWorkspaceId: selected });
3717
- const ws = wsList.find((w) => w.external_id === selected);
3718
- console.log(`Workspace: ${ws.name} (${selected})`);
3779
+ success(`Workspace: ${wsList[0].name} (${ref(wsList[0].external_id)})`);
3780
+ return;
3719
3781
  }
3782
+ const choices = core.formatWorkspaceChoices(wsList);
3783
+ const selected = await promptSelect("Select workspace", choices);
3784
+ updateConfig({ selectedWorkspaceId: selected });
3785
+ const ws = wsList.find((w) => w.external_id === selected);
3786
+ success(`Workspace: ${ws.name} (${ref(selected)})`);
3720
3787
  } catch (err) {
3721
- console.error(`Login failed: ${core.getErrorMessage(err)}`);
3722
- console.error("You can log in later with: arbi login");
3788
+ error(`Login failed: ${core.getErrorMessage(err)}`);
3789
+ error("You can log in later with: arbi login");
3723
3790
  }
3724
3791
  }
3725
3792
 
@@ -3728,7 +3795,7 @@ function registerLogoutCommand(program2) {
3728
3795
  program2.command("logout").description("Log out of ARBI").action(() => {
3729
3796
  deleteCredentials();
3730
3797
  updateConfig({ selectedWorkspaceId: void 0 });
3731
- console.log("Logged out.");
3798
+ success("Logged out.");
3732
3799
  });
3733
3800
  }
3734
3801
 
@@ -3738,28 +3805,85 @@ function registerStatusCommand(program2) {
3738
3805
  const config = getConfig();
3739
3806
  const creds = getCredentials();
3740
3807
  if (!config?.baseUrl) {
3741
- console.log("Not configured. Run: arbi config set-url <url>");
3808
+ dim("Not configured. Run: arbi config set-url <url>");
3742
3809
  return;
3743
3810
  }
3744
- console.log(`Server: ${config.baseUrl}`);
3811
+ label("Server:", config.baseUrl);
3745
3812
  if (creds) {
3746
- console.log(`User: ${creds.email}`);
3813
+ label("User:", creds.email);
3747
3814
  } else {
3748
- console.log("User: (not logged in)");
3815
+ label("User:", "(not logged in)");
3749
3816
  }
3750
3817
  if (config.selectedWorkspaceId) {
3751
- console.log(`Workspace: ${config.selectedWorkspaceId}`);
3818
+ label("Workspace:", config.selectedWorkspaceId);
3752
3819
  } else {
3753
- console.log("Workspace: (none selected)");
3820
+ label("Workspace:", "(none selected)");
3754
3821
  }
3755
3822
  });
3756
3823
  }
3824
+ var activeConnection = null;
3825
+ function timestamp() {
3826
+ return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-GB", { hour12: false });
3827
+ }
3828
+ function colorize(level, text) {
3829
+ if (level === "success") return chalk__default.default.green(text);
3830
+ if (level === "error") return chalk__default.default.red(text);
3831
+ if (level === "warning") return chalk__default.default.yellow(text);
3832
+ return text;
3833
+ }
3834
+ async function startBackgroundNotifications(baseUrl, accessToken) {
3835
+ if (activeConnection) return;
3836
+ try {
3837
+ activeConnection = await core.connectWithReconnect({
3838
+ baseUrl,
3839
+ accessToken,
3840
+ onMessage: (msg) => {
3841
+ const { text, level } = core.formatWsMessage(msg);
3842
+ process.stderr.write(`
3843
+ ${colorize(level, `[${timestamp()}] ${text}`)}
3844
+ `);
3845
+ },
3846
+ onClose: () => {
3847
+ activeConnection = null;
3848
+ },
3849
+ onReconnecting: (attempt, maxRetries) => {
3850
+ process.stderr.write(
3851
+ `
3852
+ ${chalk__default.default.yellow(`[${timestamp()}] Reconnecting... (${attempt}/${maxRetries})`)}
3853
+ `
3854
+ );
3855
+ },
3856
+ onReconnected: () => {
3857
+ process.stderr.write(`
3858
+ ${chalk__default.default.green(`[${timestamp()}] Reconnected`)}
3859
+ `);
3860
+ },
3861
+ onReconnectFailed: () => {
3862
+ process.stderr.write(`
3863
+ ${chalk__default.default.red(`[${timestamp()}] Reconnection failed`)}
3864
+ `);
3865
+ }
3866
+ });
3867
+ } catch {
3868
+ }
3869
+ }
3870
+ function stopBackgroundNotifications() {
3871
+ activeConnection?.close();
3872
+ activeConnection = null;
3873
+ }
3874
+ process.on("exit", stopBackgroundNotifications);
3875
+ process.on("SIGINT", () => {
3876
+ stopBackgroundNotifications();
3877
+ process.exit(0);
3878
+ });
3879
+
3880
+ // src/helpers.ts
3757
3881
  function runAction(fn) {
3758
3882
  return async () => {
3759
3883
  try {
3760
3884
  await fn();
3761
3885
  } catch (err) {
3762
- console.error(`Error: ${core.getErrorMessage(err)}`);
3886
+ error(`Error: ${core.getErrorMessage(err)}`);
3763
3887
  hintUpdateOnError();
3764
3888
  process.exit(1);
3765
3889
  }
@@ -3770,7 +3894,7 @@ async function resolveAuth() {
3770
3894
  return await core.resolveAuth(store);
3771
3895
  } catch (err) {
3772
3896
  if (err instanceof core.ArbiError) {
3773
- console.error(err.message);
3897
+ error(err.message);
3774
3898
  process.exit(1);
3775
3899
  }
3776
3900
  throw err;
@@ -3778,17 +3902,22 @@ async function resolveAuth() {
3778
3902
  }
3779
3903
  async function resolveWorkspace(workspaceOpt) {
3780
3904
  try {
3781
- return await core.resolveWorkspace(store, workspaceOpt);
3905
+ const ctx = await core.resolveWorkspace(store, workspaceOpt);
3906
+ if (getConfig()?.notifications) {
3907
+ startBackgroundNotifications(ctx.config.baseUrl, ctx.accessToken).catch(() => {
3908
+ });
3909
+ }
3910
+ return ctx;
3782
3911
  } catch (err) {
3783
3912
  if (err instanceof core.ArbiError) {
3784
- console.error(err.message);
3913
+ error(err.message);
3785
3914
  process.exit(1);
3786
3915
  }
3787
3916
  throw err;
3788
3917
  }
3789
3918
  }
3790
3919
  function printTable(columns, rows) {
3791
- console.log(columns.map((c) => c.header.padEnd(c.width)).join(""));
3920
+ console.log(chalk__default.default.bold(columns.map((c) => c.header.padEnd(c.width)).join("")));
3792
3921
  for (const row of rows) {
3793
3922
  console.log(
3794
3923
  columns.map((c) => {
@@ -3802,7 +3931,7 @@ function parseJsonArg(input2, example) {
3802
3931
  try {
3803
3932
  return JSON.parse(input2);
3804
3933
  } catch {
3805
- console.error(`Invalid JSON. Example: ${example}`);
3934
+ error(`Invalid JSON. Example: ${example}`);
3806
3935
  process.exit(1);
3807
3936
  }
3808
3937
  }
@@ -3849,9 +3978,9 @@ function registerWorkspacesCommand(program2) {
3849
3978
  if (id) {
3850
3979
  const ws2 = data.find((w) => w.external_id === id);
3851
3980
  if (!ws2) {
3852
- console.error(`Workspace ${id} not found.`);
3853
- console.error("Available workspaces:");
3854
- for (const w of data) console.error(` ${w.external_id} ${w.name}`);
3981
+ error(`Workspace ${id} not found.`);
3982
+ error("Available workspaces:");
3983
+ for (const w of data) error(` ${w.external_id} ${w.name}`);
3855
3984
  process.exit(1);
3856
3985
  }
3857
3986
  selectedId = id;
@@ -3861,7 +3990,7 @@ function registerWorkspacesCommand(program2) {
3861
3990
  }
3862
3991
  updateConfig({ selectedWorkspaceId: selectedId });
3863
3992
  const ws = data.find((w) => w.external_id === selectedId);
3864
- console.log(`Selected: ${ws.name} (${selectedId})`);
3993
+ success(`Selected: ${ws.name} (${ref(selectedId)})`);
3865
3994
  })()
3866
3995
  );
3867
3996
  workspace.command("create <name>").description("Create a new workspace").option("-d, --description <text>", "Workspace description").option("--public", "Make workspace public", false).action(
@@ -3873,14 +4002,14 @@ function registerWorkspacesCommand(program2) {
3873
4002
  opts.description,
3874
4003
  opts.public ?? false
3875
4004
  );
3876
- console.log(`Created: ${data.name} (${data.external_id})`);
4005
+ success(`Created: ${data.name} (${ref(data.external_id)})`);
3877
4006
  })()
3878
4007
  );
3879
4008
  workspace.command("delete <id>").description("Delete a workspace").action(
3880
4009
  (id) => runAction(async () => {
3881
4010
  const { arbi } = await resolveAuth();
3882
4011
  const data = await core.workspaces.deleteWorkspace(arbi, id);
3883
- console.log(data?.detail ?? `Deleted workspace ${id}`);
4012
+ success(data?.detail ?? `Deleted workspace ${id}`);
3884
4013
  })()
3885
4014
  );
3886
4015
  workspace.command("update <id> <json>").description("Update workspace properties (pass JSON)").action(
@@ -3888,7 +4017,7 @@ function registerWorkspacesCommand(program2) {
3888
4017
  const body = parseJsonArg(json, `arbi workspace update wrk-123 '{"name": "New Name"}'`);
3889
4018
  const { arbi } = await resolveWorkspace(id);
3890
4019
  const data = await core.workspaces.updateWorkspace(arbi, id, body);
3891
- console.log(`Updated: ${data.name} (${data.external_id})`);
4020
+ success(`Updated: ${data.name} (${ref(data.external_id)})`);
3892
4021
  })()
3893
4022
  );
3894
4023
  workspace.command("users").description("List users in the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
@@ -3932,14 +4061,14 @@ function registerWorkspacesCommand(program2) {
3932
4061
  const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
3933
4062
  const role = opts.role ?? "collaborator";
3934
4063
  const data = await core.workspaces.addWorkspaceUsers(arbi, workspaceId, emails, role);
3935
- for (const u of data) console.log(`Added: ${u.user.email} as ${u.role}`);
4064
+ for (const u of data) success(`Added: ${u.user.email} as ${u.role}`);
3936
4065
  })()
3937
4066
  );
3938
4067
  workspace.command("remove-user <user-ids...>").description("Remove users from the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
3939
4068
  (userIds, opts) => runAction(async () => {
3940
4069
  const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
3941
4070
  await core.workspaces.removeWorkspaceUsers(arbi, workspaceId, userIds);
3942
- console.log(`Removed ${userIds.length} user(s).`);
4071
+ success(`Removed ${userIds.length} user(s).`);
3943
4072
  })()
3944
4073
  );
3945
4074
  workspace.command("set-role <role> <user-ids...>").description("Update user roles (owner, collaborator, guest)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
@@ -3951,19 +4080,19 @@ function registerWorkspacesCommand(program2) {
3951
4080
  userIds,
3952
4081
  role
3953
4082
  );
3954
- for (const u of data) console.log(`Updated: ${u.user.email} \u2192 ${u.role}`);
4083
+ for (const u of data) success(`Updated: ${u.user.email} \u2192 ${u.role}`);
3955
4084
  })()
3956
4085
  );
3957
4086
  workspace.command("copy <target-workspace-id> <doc-ids...>").description("Copy documents to another workspace").option("-w, --workspace <id>", "Source workspace ID (defaults to selected workspace)").action(
3958
4087
  (targetId, docIds, opts) => runAction(async () => {
3959
4088
  const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
3960
4089
  const data = await core.workspaces.copyDocuments(arbi, workspaceId, targetId, docIds);
3961
- console.log(`${data.detail} (${data.documents_copied} document(s) copied)`);
4090
+ success(`${data.detail} (${data.documents_copied} document(s) copied)`);
3962
4091
  })()
3963
4092
  );
3964
4093
  }
3965
- function statusSymbol(status) {
3966
- switch (status) {
4094
+ function statusSymbol(status2) {
4095
+ switch (status2) {
3967
4096
  case "completed":
3968
4097
  return "\u2713";
3969
4098
  // ✓
@@ -4060,7 +4189,7 @@ function registerDocsCommand(program2) {
4060
4189
  docIds = selected;
4061
4190
  }
4062
4191
  await core.documents.deleteDocuments(arbi, docIds);
4063
- console.log(`Deleted ${docIds.length} document(s).`);
4192
+ success(`Deleted ${docIds.length} document(s).`);
4064
4193
  })()
4065
4194
  );
4066
4195
  doc.command("update [json]").description("Update documents (interactive form if no JSON given)").action(
@@ -4070,7 +4199,7 @@ function registerDocsCommand(program2) {
4070
4199
  const docs = Array.isArray(parsed) ? parsed : parsed.documents;
4071
4200
  const { arbi } = await resolveWorkspace();
4072
4201
  const data = await core.documents.updateDocuments(arbi, docs);
4073
- console.log(`Updated ${data.length} document(s).`);
4202
+ success(`Updated ${data.length} document(s).`);
4074
4203
  } else {
4075
4204
  const { arbi, workspaceId } = await resolveWorkspace();
4076
4205
  const choices = await fetchDocChoices(arbi, workspaceId);
@@ -4096,7 +4225,7 @@ function registerDocsCommand(program2) {
4096
4225
  const data = await core.documents.updateDocuments(arbi, [
4097
4226
  { external_id: docId, [field]: value }
4098
4227
  ]);
4099
- console.log(`Updated ${data.length} document(s).`);
4228
+ success(`Updated ${data.length} document(s).`);
4100
4229
  }
4101
4230
  })()
4102
4231
  );
@@ -4104,9 +4233,9 @@ function registerDocsCommand(program2) {
4104
4233
  (urls, opts) => runAction(async () => {
4105
4234
  const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
4106
4235
  const data = await core.documents.uploadUrl(arbi, urls, workspaceId, opts.shared ?? false);
4107
- console.log(`Uploaded: ${data.doc_ext_ids.join(", ")}`);
4236
+ success(`Uploaded: ${data.doc_ext_ids.join(", ")}`);
4108
4237
  if (data.duplicates && data.duplicates.length > 0) {
4109
- console.log(`Duplicates: ${data.duplicates.join(", ")}`);
4238
+ warn(`Duplicates: ${data.duplicates.join(", ")}`);
4110
4239
  }
4111
4240
  })()
4112
4241
  );
@@ -4125,7 +4254,7 @@ function registerDocsCommand(program2) {
4125
4254
  { name: "Marker (raw)", value: "marker" }
4126
4255
  ]);
4127
4256
  } else if (!validStages.includes(stage)) {
4128
- console.error(`Invalid stage: ${stage}. Must be one of: ${validStages.join(", ")}`);
4257
+ error(`Invalid stage: ${stage}. Must be one of: ${validStages.join(", ")}`);
4129
4258
  process.exit(1);
4130
4259
  }
4131
4260
  const data = await core.documents.getParsedContent(
@@ -4142,7 +4271,7 @@ function registerUploadCommand(program2) {
4142
4271
  (files, opts) => runAction(async () => {
4143
4272
  for (const f of files) {
4144
4273
  if (!fs__default.default.existsSync(f)) {
4145
- console.error(`File not found: ${f}`);
4274
+ error(`File not found: ${f}`);
4146
4275
  process.exit(1);
4147
4276
  }
4148
4277
  }
@@ -4153,9 +4282,9 @@ function registerUploadCommand(program2) {
4153
4282
  const auth = { baseUrl: config.baseUrl, accessToken, workspaceKeyHeader };
4154
4283
  for (const filePath of files) {
4155
4284
  const result = await core.documents.uploadLocalFile(auth, workspaceId, filePath);
4156
- console.log(`Uploaded: ${result.fileName} (${result.doc_ext_ids.join(", ")})`);
4285
+ success(`Uploaded: ${result.fileName} (${result.doc_ext_ids.join(", ")})`);
4157
4286
  if (result.duplicates && result.duplicates.length > 0) {
4158
- console.log(` Duplicates: ${result.duplicates.join(", ")}`);
4287
+ warn(` Duplicates: ${result.duplicates.join(", ")}`);
4159
4288
  }
4160
4289
  for (const id of result.doc_ext_ids) uploadedDocs.set(id, result.fileName);
4161
4290
  }
@@ -4170,12 +4299,12 @@ Watching ${pending.size} document(s)...`);
4170
4299
  if (sdk.isMessageType(msg, "task_update")) {
4171
4300
  if (!pending.has(msg.doc_ext_id)) return;
4172
4301
  console.log(
4173
- ` ${uploadedDocs.get(msg.doc_ext_id) || msg.file_name}: ${msg.status} (${msg.progress}%)`
4302
+ ` ${uploadedDocs.get(msg.doc_ext_id) || msg.file_name}: ${status(msg.status)} (${msg.progress}%)`
4174
4303
  );
4175
4304
  if (msg.status === "completed" || msg.status === "failed") {
4176
4305
  pending.delete(msg.doc_ext_id);
4177
4306
  if (pending.size === 0) {
4178
- console.log("\nAll documents processed.");
4307
+ success("\nAll documents processed.");
4179
4308
  conn.close();
4180
4309
  }
4181
4310
  }
@@ -4183,7 +4312,7 @@ Watching ${pending.size} document(s)...`);
4183
4312
  },
4184
4313
  onClose: () => {
4185
4314
  if (pending.size > 0)
4186
- console.log(`
4315
+ warn(`
4187
4316
  Connection closed. ${pending.size} document(s) still processing.`);
4188
4317
  }
4189
4318
  });
@@ -4221,7 +4350,7 @@ function registerDownloadCommand(program2) {
4221
4350
  const outputPath = opts.output || path__default.default.join(process.cwd(), filename);
4222
4351
  const buffer = Buffer.from(await res.arrayBuffer());
4223
4352
  fs__default.default.writeFileSync(outputPath, buffer);
4224
- console.log(
4353
+ success(
4225
4354
  `Downloaded: ${path__default.default.basename(outputPath)} (${(buffer.length / (1024 * 1024)).toFixed(1)} MB)`
4226
4355
  );
4227
4356
  })()
@@ -4254,12 +4383,12 @@ function registerAskCommand(program2) {
4254
4383
  onAgentStep: (data) => {
4255
4384
  if (opts.verbose) {
4256
4385
  const focus = data.focus || data.status || "";
4257
- console.error(`
4258
- [agent] ${focus}`);
4386
+ console.error(chalk__default.default.dim(`
4387
+ [agent] ${focus}`));
4259
4388
  }
4260
4389
  },
4261
- onError: (message) => console.error(`
4262
- Error: ${message}`)
4390
+ onError: (message) => console.error(chalk__default.default.red(`
4391
+ Error: ${message}`))
4263
4392
  });
4264
4393
  process.stdout.write("\n");
4265
4394
  if (result.assistantMessageExtId) {
@@ -4275,8 +4404,11 @@ Error: ${message}`)
4275
4404
  })()
4276
4405
  );
4277
4406
  }
4278
- function timestamp() {
4279
- return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-GB", { hour12: false });
4407
+ function colorize2(level, text) {
4408
+ if (level === "success") return chalk__default.default.green(text);
4409
+ if (level === "error") return chalk__default.default.red(text);
4410
+ if (level === "warning") return chalk__default.default.yellow(text);
4411
+ return text;
4280
4412
  }
4281
4413
  function registerWatchCommand(program2) {
4282
4414
  program2.command("watch").description("Watch workspace activity in real time").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
@@ -4287,23 +4419,14 @@ function registerWatchCommand(program2) {
4287
4419
  baseUrl: config.baseUrl,
4288
4420
  accessToken,
4289
4421
  onMessage: (msg) => {
4290
- if (sdk.isMessageType(msg, "task_update")) {
4291
- console.log(
4292
- `[${timestamp()}] task_update: ${msg.file_name} - ${msg.status} (${msg.progress}%)`
4293
- );
4294
- } else if (sdk.isMessageType(msg, "batch_complete")) {
4295
- console.log(
4296
- `[${timestamp()}] batch_complete: ${msg.batch_type} - ${msg.doc_ext_ids.length} docs`
4297
- );
4298
- } else if (sdk.isMessageType(msg, "error")) {
4299
- console.log(`[${timestamp()}] error: ${msg.message}`);
4300
- } else {
4301
- console.log(`[${timestamp()}] ${msg.type}: ${JSON.stringify(msg)}`);
4302
- }
4422
+ const { text, level } = core.formatWsMessage(msg);
4423
+ console.log(colorize2(level, text));
4303
4424
  },
4304
4425
  onClose: (code, reason) => {
4305
- console.log(`
4306
- Connection closed (code ${code}${reason ? ": " + reason : ""})`);
4426
+ console.log(
4427
+ chalk__default.default.yellow(`
4428
+ Connection closed (code ${code}${reason ? ": " + reason : ""})`)
4429
+ );
4307
4430
  }
4308
4431
  });
4309
4432
  })()
@@ -4344,7 +4467,7 @@ function registerContactsCommand(program2) {
4344
4467
  }
4345
4468
  const data = await core.contacts.addContacts(arbi, emails);
4346
4469
  for (const c of data) {
4347
- console.log(`Added: ${c.email} (${c.external_id}) \u2014 ${c.status}`);
4470
+ success(`Added: ${c.email} (${c.external_id}) \u2014 ${c.status}`);
4348
4471
  }
4349
4472
  })()
4350
4473
  );
@@ -4371,7 +4494,7 @@ function registerContactsCommand(program2) {
4371
4494
  if (contactIds.length === 0) return;
4372
4495
  }
4373
4496
  await core.contacts.removeContacts(arbi, contactIds);
4374
- console.log(`Removed ${contactIds.length} contact(s).`);
4497
+ success(`Removed ${contactIds.length} contact(s).`);
4375
4498
  })()
4376
4499
  );
4377
4500
  contacts.action(async () => {
@@ -4413,7 +4536,7 @@ function registerDmCommand(program2) {
4413
4536
  if (!recipient) {
4414
4537
  const contacts = await core.contacts.listContacts(arbi);
4415
4538
  if (contacts.length === 0) {
4416
- console.error("No contacts found. Add contacts first: arbi contacts add <email>");
4539
+ error("No contacts found. Add contacts first: arbi contacts add <email>");
4417
4540
  process.exit(1);
4418
4541
  }
4419
4542
  recipient = await promptSelect(
@@ -4437,15 +4560,15 @@ function registerDmCommand(program2) {
4437
4560
  const contacts = await core.contacts.listContacts(arbi);
4438
4561
  const match = contacts.find((c) => c.email === recipient);
4439
4562
  if (!match) {
4440
- console.error(`No contact found with email: ${recipient}`);
4441
- console.error("Add them first: arbi contacts add " + recipient);
4563
+ error(`No contact found with email: ${recipient}`);
4564
+ error("Add them first: arbi contacts add " + recipient);
4442
4565
  process.exit(1);
4443
4566
  }
4444
4567
  recipientExtId = match.user?.external_id ?? match.external_id;
4445
4568
  }
4446
4569
  const data = await core.dm.sendDM(arbi, [{ recipient_ext_id: recipientExtId, content }]);
4447
4570
  for (const n of data) {
4448
- console.log(`Sent: ${n.external_id} \u2192 ${n.recipient.email}`);
4571
+ success(`Sent: ${n.external_id} \u2192 ${n.recipient.email}`);
4449
4572
  }
4450
4573
  })()
4451
4574
  );
@@ -4474,7 +4597,7 @@ function registerDmCommand(program2) {
4474
4597
  if (msgIds.length === 0) return;
4475
4598
  }
4476
4599
  const data = await core.dm.markRead(arbi, msgIds);
4477
- console.log(`Marked ${data.length} message(s) as read.`);
4600
+ success(`Marked ${data.length} message(s) as read.`);
4478
4601
  })()
4479
4602
  );
4480
4603
  dm.command("delete [ids...]").description("Delete messages (interactive picker if no IDs given)").action(
@@ -4501,7 +4624,7 @@ function registerDmCommand(program2) {
4501
4624
  if (msgIds.length === 0) return;
4502
4625
  }
4503
4626
  await core.dm.deleteDMs(arbi, msgIds);
4504
- console.log(`Deleted ${msgIds.length} message(s).`);
4627
+ success(`Deleted ${msgIds.length} message(s).`);
4505
4628
  })()
4506
4629
  );
4507
4630
  dm.action(async () => {
@@ -4579,7 +4702,7 @@ function registerTagsCommand(program2) {
4579
4702
  instruction,
4580
4703
  shared
4581
4704
  });
4582
- console.log(`Created: ${data.name} (${data.external_id})`);
4705
+ success(`Created: ${data.name} (${ref(data.external_id)})`);
4583
4706
  })()
4584
4707
  );
4585
4708
  tags.command("delete [id]").description("Delete a tag (interactive picker if no ID given)").action(
@@ -4590,7 +4713,7 @@ function registerTagsCommand(program2) {
4590
4713
  id = await promptSelect("Select tag to delete", choices);
4591
4714
  }
4592
4715
  const data = await core.tags.deleteTag(arbi, id);
4593
- console.log(data?.detail ?? `Deleted tag ${id}`);
4716
+ success(data?.detail ?? `Deleted tag ${id}`);
4594
4717
  })()
4595
4718
  );
4596
4719
  tags.command("update [id] [json]").description("Update a tag (interactive picker + form if no args)").action(
@@ -4616,7 +4739,7 @@ function registerTagsCommand(program2) {
4616
4739
  }
4617
4740
  }
4618
4741
  const data = await core.tags.updateTag(arbi, id, body);
4619
- console.log(`Updated: ${data.name} (${data.external_id})`);
4742
+ success(`Updated: ${data.name} (${ref(data.external_id)})`);
4620
4743
  })()
4621
4744
  );
4622
4745
  tags.action(async (_opts, cmd) => {
@@ -4662,7 +4785,7 @@ function registerDoctagsCommand(program2) {
4662
4785
  docIds = await pickDocs(arbi, workspaceId, "Select documents to tag");
4663
4786
  if (docIds.length === 0) return;
4664
4787
  const data = await core.doctags.assignDocTags(arbi, tagId, docIds, opts?.note);
4665
- console.log(`Created ${data.length} doctag(s) for tag ${tagId}.`);
4788
+ success(`Created ${data.length} doctag(s) for tag ${tagId}.`);
4666
4789
  })()
4667
4790
  );
4668
4791
  doctagsCmd.command("delete [tag-id] [doc-ids...]").description("Remove a tag from documents (interactive pickers if no args)").action(
@@ -4673,7 +4796,7 @@ function registerDoctagsCommand(program2) {
4673
4796
  docIds = await pickDocs(arbi, workspaceId, "Select documents to untag");
4674
4797
  if (docIds.length === 0) return;
4675
4798
  await core.doctags.removeDocTags(arbi, tagId, docIds);
4676
- console.log(`Removed tag ${tagId} from ${docIds.length} document(s).`);
4799
+ success(`Removed tag ${tagId} from ${docIds.length} document(s).`);
4677
4800
  })()
4678
4801
  );
4679
4802
  doctagsCmd.command("generate").description("AI-generate doctags (interactive pickers if no flags)").option("--tags <ids>", "Comma-separated tag IDs").option("--docs <ids>", "Comma-separated document IDs").action(
@@ -4765,7 +4888,7 @@ function registerConversationsCommand(program2) {
4765
4888
  "Select conversation to delete"
4766
4889
  );
4767
4890
  const data = await core.conversations.deleteConversation(arbi, conversationId);
4768
- console.log(data?.detail ?? `Deleted conversation ${conversationId}`);
4891
+ success(data?.detail ?? `Deleted conversation ${conversationId}`);
4769
4892
  })()
4770
4893
  );
4771
4894
  conv.command("share [conversation-id]").description("Share a conversation (interactive picker if no ID given)").action(
@@ -4774,7 +4897,7 @@ function registerConversationsCommand(program2) {
4774
4897
  if (!conversationId)
4775
4898
  conversationId = await pickConversation(arbi, workspaceId, "Select conversation to share");
4776
4899
  const data = await core.conversations.shareConversation(arbi, conversationId);
4777
- console.log(data?.detail ?? `Shared conversation ${conversationId}`);
4900
+ success(data?.detail ?? `Shared conversation ${conversationId}`);
4778
4901
  })()
4779
4902
  );
4780
4903
  conv.command("title [conversation-id] [title]").description("Update conversation title (interactive if no args)").action(
@@ -4783,7 +4906,7 @@ function registerConversationsCommand(program2) {
4783
4906
  if (!conversationId) conversationId = await pickConversation(arbi, workspaceId);
4784
4907
  if (!title) title = await promptInput("New title");
4785
4908
  const data = await core.conversations.updateConversationTitle(arbi, conversationId, title);
4786
- console.log(data?.detail ?? `Updated title to: ${title}`);
4909
+ success(data?.detail ?? `Updated title to: ${title}`);
4787
4910
  })()
4788
4911
  );
4789
4912
  conv.command("add-user [conversation-id] [user-id]").description("Add a user to a conversation (interactive if no args)").action(
@@ -4792,7 +4915,7 @@ function registerConversationsCommand(program2) {
4792
4915
  if (!conversationId) conversationId = await pickConversation(arbi, workspaceId);
4793
4916
  if (!userId) userId = await promptInput("User ext_id or email");
4794
4917
  const data = await core.conversations.addConversationUser(arbi, conversationId, userId);
4795
- console.log(data?.detail ?? `Added user ${userId} to conversation`);
4918
+ success(data?.detail ?? `Added user ${userId} to conversation`);
4796
4919
  })()
4797
4920
  );
4798
4921
  conv.command("remove-user [conversation-id] [user-id]").description("Remove a user from a conversation (interactive if no args)").action(
@@ -4801,7 +4924,7 @@ function registerConversationsCommand(program2) {
4801
4924
  if (!conversationId) conversationId = await pickConversation(arbi, workspaceId);
4802
4925
  if (!userId) userId = await promptInput("User ext_id");
4803
4926
  const data = await core.conversations.removeConversationUser(arbi, conversationId, userId);
4804
- console.log(data?.detail ?? `Removed user ${userId} from conversation`);
4927
+ success(data?.detail ?? `Removed user ${userId} from conversation`);
4805
4928
  })()
4806
4929
  );
4807
4930
  conv.command("message <message-id>").description("Get message details").action(
@@ -4815,7 +4938,7 @@ function registerConversationsCommand(program2) {
4815
4938
  (messageId) => runAction(async () => {
4816
4939
  const { arbi } = await resolveAuth();
4817
4940
  const data = await core.conversations.deleteMessage(arbi, messageId);
4818
- console.log(data?.detail ?? `Deleted message ${messageId}`);
4941
+ success(data?.detail ?? `Deleted message ${messageId}`);
4819
4942
  })()
4820
4943
  );
4821
4944
  conv.action(async (_opts, cmd) => {
@@ -4836,7 +4959,7 @@ function registerSettingsCommand(program2) {
4836
4959
  const body = parseJsonArg(json, `arbi settings set '{"hide_online_status": true}'`);
4837
4960
  const { arbi } = await resolveAuth();
4838
4961
  await core.settings.updateSettings(arbi, body);
4839
- console.log("Settings updated.");
4962
+ success("Settings updated.");
4840
4963
  })()
4841
4964
  );
4842
4965
  settings.action(async () => {
@@ -5041,7 +5164,7 @@ function registerAgentconfigCommand(program2) {
5041
5164
  if (opts?.tag) body.tag_ext_id = opts.tag;
5042
5165
  if (opts?.message) body.parent_message_ext_id = opts.message;
5043
5166
  const data = await core.agentconfig.saveConfig(arbi, body);
5044
- console.log(`Saved: ${data.title || "(untitled)"} (${data.external_id})`);
5167
+ success(`Saved: ${data.title || "(untitled)"} (${ref(data.external_id)})`);
5045
5168
  })()
5046
5169
  );
5047
5170
  ac.command("delete [config-id]").description("Delete a configuration (picker if no ID)").action(
@@ -5049,7 +5172,7 @@ function registerAgentconfigCommand(program2) {
5049
5172
  const { arbi } = await resolveAuth();
5050
5173
  if (!configId) configId = await pickConfig(arbi, "Select configuration to delete");
5051
5174
  const data = await core.agentconfig.deleteConfig(arbi, configId);
5052
- console.log(data.detail);
5175
+ success(data.detail);
5053
5176
  })()
5054
5177
  );
5055
5178
  ac.command("schema").description("Show JSON schema for all configuration models").action(
@@ -5068,20 +5191,20 @@ function registerHealthCommand(program2) {
5068
5191
  runAction(async () => {
5069
5192
  const { arbi } = await resolveAuth();
5070
5193
  const data = await core.health.getHealth(arbi);
5071
- console.log(`Status: ${data.status}`);
5072
- if (data.backend_git_hash) console.log(`Backend: ${data.backend_git_hash}`);
5073
- if (data.frontend_docker_version) console.log(`Frontend: ${data.frontend_docker_version}`);
5194
+ label("Status:", status(data.status));
5195
+ if (data.backend_git_hash) label("Backend:", data.backend_git_hash);
5196
+ if (data.frontend_docker_version) label("Frontend:", data.frontend_docker_version);
5074
5197
  if (data.services.length > 0) {
5075
- console.log("\nServices:");
5198
+ bold("\nServices:");
5076
5199
  for (const s of data.services) {
5077
- console.log(` ${s.name}: ${s.status}${s.detail ? ` \u2014 ${s.detail}` : ""}`);
5200
+ console.log(` ${s.name}: ${status(s.status)}${s.detail ? ` \u2014 ${s.detail}` : ""}`);
5078
5201
  }
5079
5202
  }
5080
5203
  if (data.models_health) {
5081
- console.log(`
5204
+ bold(`
5082
5205
  Models (${data.models_health.application}):`);
5083
5206
  for (const m of data.models_health.models) {
5084
- console.log(` ${m.model}: ${m.status}${m.detail ? ` \u2014 ${m.detail}` : ""}`);
5207
+ console.log(` ${m.model}: ${status(m.status)}${m.detail ? ` \u2014 ${m.detail}` : ""}`);
5085
5208
  }
5086
5209
  }
5087
5210
  })
@@ -5107,7 +5230,7 @@ Models (${data.models_health.application}):`);
5107
5230
  }
5108
5231
  function registerTuiCommand(program2) {
5109
5232
  program2.command("tui").description("Launch interactive terminal UI").option("-w, --workspace <id>", "Workspace ID to use").allowUnknownOption(true).action((opts, cmd) => {
5110
- const require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
5233
+ const require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
5111
5234
  const entryPoint = require2.resolve("@arbidocs/tui");
5112
5235
  const args = [];
5113
5236
  if (opts.workspace) {
@@ -5124,31 +5247,31 @@ function registerTuiCommand(program2) {
5124
5247
  function registerUpdateCommand(program2) {
5125
5248
  const update = program2.command("update").description("Update ARBI CLI to the latest version").action(async () => {
5126
5249
  const current = getCurrentVersion();
5127
- console.log(`Current version: ${current}`);
5250
+ label("Current version:", current);
5128
5251
  console.log("Checking for updates...\n");
5129
5252
  try {
5130
5253
  const latest = getLatestVersion() || child_process.execSync("npm view @arbidocs/cli version", { encoding: "utf8" }).trim();
5131
5254
  if (latest === current) {
5132
- console.log("Already up to date.");
5255
+ success("Already up to date.");
5133
5256
  return;
5134
5257
  }
5135
- console.log(`New version available: ${latest}`);
5258
+ success(`New version available: ${latest}`);
5136
5259
  await showChangelog(current, latest);
5137
5260
  console.log("\nUpdating...\n");
5138
5261
  child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
5139
- console.log(`
5262
+ success(`
5140
5263
  Updated to ${latest}.`);
5141
5264
  } catch (err) {
5142
5265
  const msg = err instanceof Error ? err.message : String(err);
5143
- console.error(`Update failed: ${msg}`);
5144
- console.error("\nYou can update manually with:");
5145
- console.error(" npm install -g @arbidocs/cli@latest");
5266
+ error(`Update failed: ${msg}`);
5267
+ error("\nYou can update manually with:");
5268
+ dim(" npm install -g @arbidocs/cli@latest");
5146
5269
  process.exit(1);
5147
5270
  }
5148
5271
  });
5149
5272
  update.command("auto").description("Enable automatic updates on login").action(() => {
5150
5273
  updateConfig({ autoUpdate: true });
5151
- console.log("Auto-update enabled. ARBI CLI will update automatically on login.");
5274
+ success("Auto-update enabled. ARBI CLI will update automatically on login.");
5152
5275
  });
5153
5276
  }
5154
5277
 
@@ -5161,7 +5284,7 @@ console.info = (...args) => {
5161
5284
  _origInfo(...args);
5162
5285
  };
5163
5286
  var program = new commander.Command();
5164
- program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.3");
5287
+ program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.5");
5165
5288
  registerConfigCommand(program);
5166
5289
  registerLoginCommand(program);
5167
5290
  registerRegisterCommand(program);
@@ -5184,5 +5307,5 @@ registerHealthCommand(program);
5184
5307
  registerTuiCommand(program);
5185
5308
  registerUpdateCommand(program);
5186
5309
  program.parse();
5187
- //# sourceMappingURL=index.cjs.map
5188
- //# sourceMappingURL=index.cjs.map
5310
+ //# sourceMappingURL=index.js.map
5311
+ //# sourceMappingURL=index.js.map