@arbidocs/cli 0.3.11 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -5
- package/dist/index.js +398 -58
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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
|
|
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(
|
|
64
|
+
console.log(chalk2__default.default.green(msg));
|
|
58
65
|
}
|
|
59
66
|
function error(msg) {
|
|
60
|
-
console.error(
|
|
67
|
+
console.error(chalk2__default.default.red(msg));
|
|
61
68
|
}
|
|
62
69
|
function warn(msg) {
|
|
63
|
-
console.error(
|
|
70
|
+
console.error(chalk2__default.default.yellow(msg));
|
|
64
71
|
}
|
|
65
72
|
function label(key, value) {
|
|
66
|
-
console.log(`${
|
|
73
|
+
console.log(`${chalk2__default.default.bold(key)} ${value}`);
|
|
67
74
|
}
|
|
68
75
|
function dim(msg) {
|
|
69
|
-
console.log(
|
|
76
|
+
console.log(chalk2__default.default.dim(msg));
|
|
70
77
|
}
|
|
71
78
|
function bold(msg) {
|
|
72
|
-
console.log(
|
|
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
|
|
77
|
-
if (["failed", "error", "unavailable", "offline"].includes(lower)) return
|
|
78
|
-
if (["processing", "pending", "degraded", "warning"].includes(lower)) return
|
|
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
|
|
89
|
+
return chalk2__default.default.cyan(s);
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
// src/commands/config-cmd.ts
|
|
@@ -3502,7 +3509,7 @@ function getLatestVersion(skipCache = false) {
|
|
|
3502
3509
|
}
|
|
3503
3510
|
}
|
|
3504
3511
|
function getCurrentVersion() {
|
|
3505
|
-
return "0.3.
|
|
3512
|
+
return "0.3.13";
|
|
3506
3513
|
}
|
|
3507
3514
|
function readChangelog(fromVersion, toVersion) {
|
|
3508
3515
|
try {
|
|
@@ -3555,17 +3562,17 @@ function showChangelog(fromVersion, toVersion) {
|
|
|
3555
3562
|
async function checkForUpdates(autoUpdate) {
|
|
3556
3563
|
try {
|
|
3557
3564
|
const latest = getLatestVersion();
|
|
3558
|
-
if (!latest || latest === "0.3.
|
|
3565
|
+
if (!latest || latest === "0.3.13") return;
|
|
3559
3566
|
if (autoUpdate) {
|
|
3560
3567
|
warn(`
|
|
3561
|
-
Your arbi version is out of date (${"0.3.
|
|
3568
|
+
Your arbi version is out of date (${"0.3.13"} \u2192 ${latest}). Updating...`);
|
|
3562
3569
|
child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
|
|
3563
|
-
showChangelog("0.3.
|
|
3570
|
+
showChangelog("0.3.13", latest);
|
|
3564
3571
|
console.log(`Updated to ${latest}.`);
|
|
3565
3572
|
} else {
|
|
3566
3573
|
warn(
|
|
3567
3574
|
`
|
|
3568
|
-
Your arbi version is out of date (${"0.3.
|
|
3575
|
+
Your arbi version is out of date (${"0.3.13"} \u2192 ${latest}).
|
|
3569
3576
|
Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
3570
3577
|
);
|
|
3571
3578
|
}
|
|
@@ -3575,9 +3582,9 @@ Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
|
3575
3582
|
function hintUpdateOnError() {
|
|
3576
3583
|
try {
|
|
3577
3584
|
const cached = readCache();
|
|
3578
|
-
if (cached && cached.latest !== "0.3.
|
|
3585
|
+
if (cached && cached.latest !== "0.3.13") {
|
|
3579
3586
|
warn(
|
|
3580
|
-
`Your arbi version is out of date (${"0.3.
|
|
3587
|
+
`Your arbi version is out of date (${"0.3.13"} \u2192 ${cached.latest}). Run "arbi update".`
|
|
3581
3588
|
);
|
|
3582
3589
|
}
|
|
3583
3590
|
} catch {
|
|
@@ -3658,7 +3665,11 @@ function registerRegisterCommand(program2) {
|
|
|
3658
3665
|
});
|
|
3659
3666
|
}
|
|
3660
3667
|
async function smartRegister(config, opts) {
|
|
3661
|
-
|
|
3668
|
+
let email = opts.email || process.env.ARBI_EMAIL || await promptInput("Email");
|
|
3669
|
+
if ((opts.email || process.env.ARBI_EMAIL) && !email.includes("@")) {
|
|
3670
|
+
email = `${email}@${config.deploymentDomain}`;
|
|
3671
|
+
console.log(`Using email: ${email}`);
|
|
3672
|
+
}
|
|
3662
3673
|
const arbi = client.createArbiClient({
|
|
3663
3674
|
baseUrl: config.baseUrl,
|
|
3664
3675
|
deploymentDomain: config.deploymentDomain,
|
|
@@ -3724,13 +3735,17 @@ Registered successfully as ${email}`);
|
|
|
3724
3735
|
}
|
|
3725
3736
|
}
|
|
3726
3737
|
async function nonInteractiveRegister(config, opts) {
|
|
3727
|
-
|
|
3738
|
+
let email = opts.email || process.env.ARBI_EMAIL;
|
|
3728
3739
|
const password2 = opts.password || process.env.ARBI_PASSWORD;
|
|
3729
3740
|
const supportApiKey = process.env.SUPPORT_API_KEY;
|
|
3730
3741
|
if (!email) {
|
|
3731
3742
|
error("Email required. Use --email <email> or set ARBI_EMAIL");
|
|
3732
3743
|
process.exit(1);
|
|
3733
3744
|
}
|
|
3745
|
+
if (!email.includes("@")) {
|
|
3746
|
+
email = `${email}@${config.deploymentDomain}`;
|
|
3747
|
+
console.log(`Using email: ${email}`);
|
|
3748
|
+
}
|
|
3734
3749
|
if (!password2) {
|
|
3735
3750
|
error("Password required. Use --password <password> or set ARBI_PASSWORD");
|
|
3736
3751
|
process.exit(1);
|
|
@@ -3842,9 +3857,9 @@ function timestamp() {
|
|
|
3842
3857
|
return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-GB", { hour12: false });
|
|
3843
3858
|
}
|
|
3844
3859
|
function colorize(level, text) {
|
|
3845
|
-
if (level === "success") return
|
|
3846
|
-
if (level === "error") return
|
|
3847
|
-
if (level === "warning") return
|
|
3860
|
+
if (level === "success") return chalk2__default.default.green(text);
|
|
3861
|
+
if (level === "error") return chalk2__default.default.red(text);
|
|
3862
|
+
if (level === "warning") return chalk2__default.default.yellow(text);
|
|
3848
3863
|
return text;
|
|
3849
3864
|
}
|
|
3850
3865
|
async function startBackgroundNotifications(baseUrl, accessToken) {
|
|
@@ -3865,18 +3880,18 @@ ${colorize(level, `[${timestamp()}] ${text}`)}
|
|
|
3865
3880
|
onReconnecting: (attempt, maxRetries) => {
|
|
3866
3881
|
process.stderr.write(
|
|
3867
3882
|
`
|
|
3868
|
-
${
|
|
3883
|
+
${chalk2__default.default.yellow(`[${timestamp()}] Reconnecting... (${attempt}/${maxRetries})`)}
|
|
3869
3884
|
`
|
|
3870
3885
|
);
|
|
3871
3886
|
},
|
|
3872
3887
|
onReconnected: () => {
|
|
3873
3888
|
process.stderr.write(`
|
|
3874
|
-
${
|
|
3889
|
+
${chalk2__default.default.green(`[${timestamp()}] Reconnected`)}
|
|
3875
3890
|
`);
|
|
3876
3891
|
},
|
|
3877
3892
|
onReconnectFailed: () => {
|
|
3878
3893
|
process.stderr.write(`
|
|
3879
|
-
${
|
|
3894
|
+
${chalk2__default.default.red(`[${timestamp()}] Reconnection failed`)}
|
|
3880
3895
|
`);
|
|
3881
3896
|
}
|
|
3882
3897
|
});
|
|
@@ -3894,7 +3909,31 @@ process.on("SIGINT", () => {
|
|
|
3894
3909
|
});
|
|
3895
3910
|
|
|
3896
3911
|
// src/helpers.ts
|
|
3912
|
+
var CONNECTION_ERROR_HINTS = {
|
|
3913
|
+
ECONNREFUSED: "Connection refused. Is the backend running?",
|
|
3914
|
+
ECONNRESET: "Connection reset by server. The backend may have restarted.",
|
|
3915
|
+
ENOTFOUND: "DNS resolution failed. Check the server URL.",
|
|
3916
|
+
ETIMEDOUT: "Connection timed out. Check network connectivity.",
|
|
3917
|
+
UNABLE_TO_VERIFY_LEAF_SIGNATURE: "TLS certificate cannot be verified. The cert may be expired or self-signed.",
|
|
3918
|
+
CERT_HAS_EXPIRED: "TLS certificate has expired. Renew with manage-deployment.",
|
|
3919
|
+
ERR_TLS_CERT_ALTNAME_INVALID: "TLS certificate hostname mismatch. Check the server URL.",
|
|
3920
|
+
DEPTH_ZERO_SELF_SIGNED_CERT: "Self-signed TLS certificate. The cert may need to be renewed.",
|
|
3921
|
+
SELF_SIGNED_CERT_IN_CHAIN: "Self-signed certificate in chain. The cert may need to be renewed."
|
|
3922
|
+
};
|
|
3923
|
+
function diagnoseConnectionError(err) {
|
|
3924
|
+
const code = sdk.getErrorCode(err);
|
|
3925
|
+
if (code && code in CONNECTION_ERROR_HINTS) {
|
|
3926
|
+
return CONNECTION_ERROR_HINTS[code];
|
|
3927
|
+
}
|
|
3928
|
+
const msg = err instanceof Error ? err.message : "";
|
|
3929
|
+
if (msg === "fetch failed" || msg.includes("fetch failed")) {
|
|
3930
|
+
return "Network error connecting to the server. Run `arbi health` to diagnose.";
|
|
3931
|
+
}
|
|
3932
|
+
return void 0;
|
|
3933
|
+
}
|
|
3897
3934
|
function formatCliError(err) {
|
|
3935
|
+
const connectionHint = diagnoseConnectionError(err);
|
|
3936
|
+
if (connectionHint) return connectionHint;
|
|
3898
3937
|
if (err instanceof sdk.ArbiApiError && err.apiError && typeof err.apiError === "object") {
|
|
3899
3938
|
const base = err.message;
|
|
3900
3939
|
const apiErr = err.apiError;
|
|
@@ -3920,6 +3959,7 @@ function runAction(fn) {
|
|
|
3920
3959
|
}
|
|
3921
3960
|
async function resolveAuth() {
|
|
3922
3961
|
try {
|
|
3962
|
+
resolveConfig();
|
|
3923
3963
|
return await sdk.resolveAuth(store);
|
|
3924
3964
|
} catch (err) {
|
|
3925
3965
|
if (err instanceof sdk.ArbiError) {
|
|
@@ -3931,6 +3971,7 @@ async function resolveAuth() {
|
|
|
3931
3971
|
}
|
|
3932
3972
|
async function resolveWorkspace(workspaceOpt) {
|
|
3933
3973
|
try {
|
|
3974
|
+
resolveConfig();
|
|
3934
3975
|
const ctx = await sdk.resolveWorkspace(store, workspaceOpt);
|
|
3935
3976
|
if (getConfig()?.notifications) {
|
|
3936
3977
|
startBackgroundNotifications(ctx.config.baseUrl, ctx.accessToken).catch(() => {
|
|
@@ -3946,7 +3987,7 @@ async function resolveWorkspace(workspaceOpt) {
|
|
|
3946
3987
|
}
|
|
3947
3988
|
}
|
|
3948
3989
|
function printTable(columns, rows) {
|
|
3949
|
-
console.log(
|
|
3990
|
+
console.log(chalk2__default.default.bold(columns.map((c) => c.header.padEnd(c.width)).join("")));
|
|
3950
3991
|
for (const row of rows) {
|
|
3951
3992
|
console.log(
|
|
3952
3993
|
columns.map((c) => {
|
|
@@ -4234,11 +4275,11 @@ function registerDocsCommand(program2) {
|
|
|
4234
4275
|
const reason = raw.error_reason || raw.status_details || raw.error || null;
|
|
4235
4276
|
const docId = raw.external_id;
|
|
4236
4277
|
if (reason) {
|
|
4237
|
-
console.error(
|
|
4278
|
+
console.error(chalk2__default.default.red(`
|
|
4238
4279
|
\u26A0 ${docId} processing failed: ${reason}`));
|
|
4239
4280
|
} else {
|
|
4240
4281
|
console.error(
|
|
4241
|
-
|
|
4282
|
+
chalk2__default.default.red(`
|
|
4242
4283
|
\u26A0 ${docId} processing failed (no error details available)`)
|
|
4243
4284
|
);
|
|
4244
4285
|
}
|
|
@@ -4326,11 +4367,11 @@ function registerDocsCommand(program2) {
|
|
|
4326
4367
|
);
|
|
4327
4368
|
}
|
|
4328
4369
|
function registerUploadCommand(program2) {
|
|
4329
|
-
program2.command("upload <
|
|
4330
|
-
(
|
|
4331
|
-
for (const
|
|
4332
|
-
if (!fs__default.default.existsSync(
|
|
4333
|
-
error(`
|
|
4370
|
+
program2.command("upload <paths...>").description("Upload 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").action(
|
|
4371
|
+
(paths, opts) => runAction(async () => {
|
|
4372
|
+
for (const p of paths) {
|
|
4373
|
+
if (!fs__default.default.existsSync(p)) {
|
|
4374
|
+
error(`Path not found: ${p}`);
|
|
4334
4375
|
process.exit(1);
|
|
4335
4376
|
}
|
|
4336
4377
|
}
|
|
@@ -4339,16 +4380,53 @@ function registerUploadCommand(program2) {
|
|
|
4339
4380
|
);
|
|
4340
4381
|
const uploadedDocs = /* @__PURE__ */ new Map();
|
|
4341
4382
|
const auth = { baseUrl: config.baseUrl, accessToken, workspaceKeyHeader };
|
|
4342
|
-
for (const filePath of
|
|
4343
|
-
const
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4383
|
+
for (const filePath of paths) {
|
|
4384
|
+
const stat = fs__default.default.statSync(filePath);
|
|
4385
|
+
if (stat.isDirectory()) {
|
|
4386
|
+
const result = await sdk.documentsNode.uploadDirectory(auth, workspaceId, filePath);
|
|
4387
|
+
if (result.doc_ext_ids.length === 0) {
|
|
4388
|
+
warn(`No supported files found in directory: ${filePath}`);
|
|
4389
|
+
continue;
|
|
4390
|
+
}
|
|
4391
|
+
for (const [folder, info] of result.folders) {
|
|
4392
|
+
success(
|
|
4393
|
+
` ${folder}: ${info.fileCount} file(s) \u2192 ${info.doc_ext_ids.length} uploaded`
|
|
4394
|
+
);
|
|
4395
|
+
if (info.duplicates.length > 0) {
|
|
4396
|
+
warn(` Duplicates: ${info.duplicates.join(", ")}`);
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
success(
|
|
4400
|
+
`Uploaded directory: ${filePath} (${result.doc_ext_ids.length} document(s) total)`
|
|
4401
|
+
);
|
|
4402
|
+
for (const id of result.doc_ext_ids) uploadedDocs.set(id, filePath);
|
|
4403
|
+
} else if (filePath.toLowerCase().endsWith(".zip")) {
|
|
4404
|
+
const result = await sdk.documentsNode.uploadZip(auth, workspaceId, filePath);
|
|
4405
|
+
if (result.doc_ext_ids.length === 0) {
|
|
4406
|
+
warn(`No supported files found in zip: ${filePath}`);
|
|
4407
|
+
continue;
|
|
4408
|
+
}
|
|
4409
|
+
for (const [folder, info] of result.folders) {
|
|
4410
|
+
success(
|
|
4411
|
+
` ${folder}: ${info.fileCount} file(s) \u2192 ${info.doc_ext_ids.length} uploaded`
|
|
4412
|
+
);
|
|
4413
|
+
if (info.duplicates.length > 0) {
|
|
4414
|
+
warn(` Duplicates: ${info.duplicates.join(", ")}`);
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
success(`Uploaded zip: ${filePath} (${result.doc_ext_ids.length} document(s) total)`);
|
|
4418
|
+
for (const id of result.doc_ext_ids) uploadedDocs.set(id, filePath);
|
|
4419
|
+
} else {
|
|
4420
|
+
const result = await sdk.documentsNode.uploadLocalFile(auth, workspaceId, filePath);
|
|
4421
|
+
success(`Uploaded: ${result.fileName} (${result.doc_ext_ids.join(", ")})`);
|
|
4422
|
+
if (result.duplicates && result.duplicates.length > 0) {
|
|
4423
|
+
warn(` Duplicates: ${result.duplicates.join(", ")}`);
|
|
4424
|
+
}
|
|
4425
|
+
for (const id of result.doc_ext_ids) uploadedDocs.set(id, result.fileName);
|
|
4347
4426
|
}
|
|
4348
|
-
for (const id of result.doc_ext_ids) uploadedDocs.set(id, result.fileName);
|
|
4349
4427
|
}
|
|
4350
4428
|
const isInteractive = process.stdout.isTTY === true;
|
|
4351
|
-
const shouldWatch = opts.watch === true ||
|
|
4429
|
+
const shouldWatch = opts.watch === true || paths.length === 1 && isInteractive;
|
|
4352
4430
|
if (shouldWatch && uploadedDocs.size > 0) {
|
|
4353
4431
|
const pending = new Set(uploadedDocs.keys());
|
|
4354
4432
|
const failed = /* @__PURE__ */ new Map();
|
|
@@ -4493,12 +4571,12 @@ function registerAskCommand(program2) {
|
|
|
4493
4571
|
onToken: (content) => process.stdout.write(content),
|
|
4494
4572
|
onAgentStep: (data) => {
|
|
4495
4573
|
if (opts.verbose) {
|
|
4496
|
-
const
|
|
4497
|
-
console.error(
|
|
4498
|
-
[agent] ${
|
|
4574
|
+
const label2 = sdk.formatAgentStepLabel(data);
|
|
4575
|
+
if (label2) console.error(chalk2__default.default.dim(`
|
|
4576
|
+
[agent] ${label2}`));
|
|
4499
4577
|
}
|
|
4500
4578
|
},
|
|
4501
|
-
onError: (message) => console.error(
|
|
4579
|
+
onError: (message) => console.error(chalk2__default.default.red(`
|
|
4502
4580
|
Error: ${message}`))
|
|
4503
4581
|
});
|
|
4504
4582
|
process.stdout.write("\n");
|
|
@@ -4517,36 +4595,73 @@ Error: ${message}`))
|
|
|
4517
4595
|
);
|
|
4518
4596
|
}
|
|
4519
4597
|
function colorize2(level, text) {
|
|
4520
|
-
if (level === "success") return
|
|
4521
|
-
if (level === "error") return
|
|
4522
|
-
if (level === "warning") return
|
|
4598
|
+
if (level === "success") return chalk2__default.default.green(text);
|
|
4599
|
+
if (level === "error") return chalk2__default.default.red(text);
|
|
4600
|
+
if (level === "warning") return chalk2__default.default.yellow(text);
|
|
4523
4601
|
return text;
|
|
4524
4602
|
}
|
|
4525
4603
|
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(
|
|
4604
|
+
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
4605
|
(opts) => runAction(async () => {
|
|
4528
4606
|
const { config, accessToken, workspaceId } = await resolveWorkspace(opts.workspace);
|
|
4529
|
-
|
|
4607
|
+
const timeoutSec = opts.timeout ? parseInt(opts.timeout, 10) : void 0;
|
|
4608
|
+
const maxCount = opts.count ? parseInt(opts.count, 10) : void 0;
|
|
4609
|
+
const jsonMode = opts.json ?? false;
|
|
4610
|
+
if (!jsonMode) {
|
|
4611
|
+
const parts = [`Watching workspace ${workspaceId}...`];
|
|
4612
|
+
if (timeoutSec) parts.push(`(timeout: ${timeoutSec}s)`);
|
|
4613
|
+
if (maxCount) parts.push(`(max: ${maxCount} messages)`);
|
|
4614
|
+
parts.push("(Ctrl+C to stop)");
|
|
4615
|
+
console.log(parts.join(" "));
|
|
4616
|
+
}
|
|
4617
|
+
let messageCount = 0;
|
|
4530
4618
|
let onDone;
|
|
4531
4619
|
const done = new Promise((r) => {
|
|
4532
4620
|
onDone = r;
|
|
4533
4621
|
});
|
|
4534
|
-
await sdk.connectWebSocket({
|
|
4622
|
+
const conn = await sdk.connectWebSocket({
|
|
4535
4623
|
baseUrl: config.baseUrl,
|
|
4536
4624
|
accessToken,
|
|
4537
4625
|
onMessage: (msg) => {
|
|
4538
|
-
|
|
4539
|
-
|
|
4626
|
+
messageCount++;
|
|
4627
|
+
if (jsonMode) {
|
|
4628
|
+
console.log(JSON.stringify(msg));
|
|
4629
|
+
} else {
|
|
4630
|
+
const { text, level } = sdk.formatWsMessage(msg);
|
|
4631
|
+
console.log(colorize2(level, text));
|
|
4632
|
+
}
|
|
4633
|
+
if (maxCount && messageCount >= maxCount) {
|
|
4634
|
+
if (!jsonMode) console.log(chalk2__default.default.dim(`
|
|
4635
|
+
Reached ${maxCount} messages, closing.`));
|
|
4636
|
+
conn.close();
|
|
4637
|
+
}
|
|
4540
4638
|
},
|
|
4541
4639
|
onClose: (code, reason) => {
|
|
4542
|
-
|
|
4543
|
-
|
|
4640
|
+
if (!jsonMode) {
|
|
4641
|
+
console.log(
|
|
4642
|
+
chalk2__default.default.yellow(`
|
|
4544
4643
|
Connection closed (code ${code}${reason ? ": " + reason : ""})`)
|
|
4545
|
-
|
|
4644
|
+
);
|
|
4645
|
+
}
|
|
4546
4646
|
onDone();
|
|
4547
4647
|
}
|
|
4548
4648
|
});
|
|
4649
|
+
let timer;
|
|
4650
|
+
if (timeoutSec) {
|
|
4651
|
+
timer = setTimeout(() => {
|
|
4652
|
+
if (!jsonMode) console.log(chalk2__default.default.dim(`
|
|
4653
|
+
Timeout (${timeoutSec}s), closing.`));
|
|
4654
|
+
conn.close();
|
|
4655
|
+
}, timeoutSec * 1e3);
|
|
4656
|
+
}
|
|
4657
|
+
const sigintHandler = () => {
|
|
4658
|
+
if (timer) clearTimeout(timer);
|
|
4659
|
+
conn.close();
|
|
4660
|
+
};
|
|
4661
|
+
process.on("SIGINT", sigintHandler);
|
|
4549
4662
|
await done;
|
|
4663
|
+
if (timer) clearTimeout(timer);
|
|
4664
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
4550
4665
|
})()
|
|
4551
4666
|
);
|
|
4552
4667
|
}
|
|
@@ -5373,6 +5488,229 @@ Updated to ${latest}.`);
|
|
|
5373
5488
|
success("Auto-update enabled. ARBI CLI will update automatically on login.");
|
|
5374
5489
|
});
|
|
5375
5490
|
}
|
|
5491
|
+
function registerQuickstartCommand(program2) {
|
|
5492
|
+
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) => {
|
|
5493
|
+
console.log("\nWelcome to ARBI CLI setup!\n");
|
|
5494
|
+
const { config, source } = store.resolveConfigWithFallbacks();
|
|
5495
|
+
if (url) {
|
|
5496
|
+
const domain = new URL(url).hostname;
|
|
5497
|
+
config.baseUrl = url.replace(/\/$/, "");
|
|
5498
|
+
config.deploymentDomain = domain;
|
|
5499
|
+
store.saveConfig(config);
|
|
5500
|
+
}
|
|
5501
|
+
const useDetected = await promptConfirm(`Use server ${config.baseUrl}?`, true);
|
|
5502
|
+
if (!useDetected) {
|
|
5503
|
+
const customUrl = await promptInput("Server URL");
|
|
5504
|
+
try {
|
|
5505
|
+
const domain = new URL(customUrl).hostname;
|
|
5506
|
+
config.baseUrl = customUrl.replace(/\/$/, "");
|
|
5507
|
+
config.deploymentDomain = domain;
|
|
5508
|
+
store.saveConfig(config);
|
|
5509
|
+
} catch {
|
|
5510
|
+
error("Invalid URL");
|
|
5511
|
+
process.exit(1);
|
|
5512
|
+
}
|
|
5513
|
+
} else if (source !== "config") {
|
|
5514
|
+
store.saveConfig(config);
|
|
5515
|
+
}
|
|
5516
|
+
dim(`Server: ${config.baseUrl}`);
|
|
5517
|
+
const action = await promptSelect("Do you have an account?", [
|
|
5518
|
+
{ name: "Yes, log me in", value: "login" },
|
|
5519
|
+
{ name: "No, register a new account", value: "register" }
|
|
5520
|
+
]);
|
|
5521
|
+
const arbiClient = client.createArbiClient({
|
|
5522
|
+
baseUrl: config.baseUrl,
|
|
5523
|
+
deploymentDomain: config.deploymentDomain,
|
|
5524
|
+
credentials: "omit"
|
|
5525
|
+
});
|
|
5526
|
+
await arbiClient.crypto.initSodium();
|
|
5527
|
+
let email;
|
|
5528
|
+
let password2;
|
|
5529
|
+
if (action === "register") {
|
|
5530
|
+
email = await promptInput("Email");
|
|
5531
|
+
password2 = await promptPassword("Password");
|
|
5532
|
+
const confirmPw = await promptPassword("Confirm password");
|
|
5533
|
+
if (password2 !== confirmPw) {
|
|
5534
|
+
error("Passwords do not match.");
|
|
5535
|
+
process.exit(1);
|
|
5536
|
+
}
|
|
5537
|
+
const codeMethod = await promptSelect("Verification method", [
|
|
5538
|
+
{ name: "I have an invitation code", value: "code" },
|
|
5539
|
+
{ name: "Send me a verification email", value: "email" }
|
|
5540
|
+
]);
|
|
5541
|
+
let verificationCode;
|
|
5542
|
+
if (codeMethod === "code") {
|
|
5543
|
+
verificationCode = await promptInput("Invitation code");
|
|
5544
|
+
} else {
|
|
5545
|
+
console.log("Sending verification email...");
|
|
5546
|
+
const verifyResponse = await arbiClient.fetch.POST("/v1/user/verify-email", {
|
|
5547
|
+
body: { email }
|
|
5548
|
+
});
|
|
5549
|
+
if (verifyResponse.error) {
|
|
5550
|
+
error(`Failed to send verification email: ${JSON.stringify(verifyResponse.error)}`);
|
|
5551
|
+
process.exit(1);
|
|
5552
|
+
}
|
|
5553
|
+
success("Verification email sent. Check your inbox.");
|
|
5554
|
+
verificationCode = await promptInput("Verification code");
|
|
5555
|
+
}
|
|
5556
|
+
try {
|
|
5557
|
+
const firstName = await promptInput("First name", false) || "User";
|
|
5558
|
+
const lastName = await promptInput("Last name", false) || "";
|
|
5559
|
+
await arbiClient.auth.register({
|
|
5560
|
+
email,
|
|
5561
|
+
password: password2,
|
|
5562
|
+
verificationCode,
|
|
5563
|
+
firstName,
|
|
5564
|
+
lastName
|
|
5565
|
+
});
|
|
5566
|
+
success(`Registered as ${email}`);
|
|
5567
|
+
} catch (err) {
|
|
5568
|
+
error(`Registration failed: ${sdk.getErrorMessage(err)}`);
|
|
5569
|
+
process.exit(1);
|
|
5570
|
+
}
|
|
5571
|
+
} else {
|
|
5572
|
+
email = await promptInput("Email");
|
|
5573
|
+
password2 = await promptPassword("Password");
|
|
5574
|
+
}
|
|
5575
|
+
try {
|
|
5576
|
+
const { arbi } = await sdk.performPasswordLogin(config, email, password2, store);
|
|
5577
|
+
success(`Logged in as ${email}`);
|
|
5578
|
+
const { data: workspaces2 } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
5579
|
+
const wsList = workspaces2 || [];
|
|
5580
|
+
const memberWorkspaces = wsList.filter((ws) => ws.users?.some((u) => u.email === email));
|
|
5581
|
+
let workspaceId;
|
|
5582
|
+
let workspaceName;
|
|
5583
|
+
if (memberWorkspaces.length === 0) {
|
|
5584
|
+
console.log("Creating your first workspace...");
|
|
5585
|
+
const ws = await sdk.workspaces.createWorkspace(arbi, "My Workspace");
|
|
5586
|
+
workspaceId = ws.external_id;
|
|
5587
|
+
workspaceName = ws.name;
|
|
5588
|
+
} else {
|
|
5589
|
+
const choices = [
|
|
5590
|
+
...sdk.formatWorkspaceChoices(memberWorkspaces),
|
|
5591
|
+
{ name: "+ Create new workspace", value: "__new__", description: "" }
|
|
5592
|
+
];
|
|
5593
|
+
const selected = await promptSelect("Select workspace", choices);
|
|
5594
|
+
if (selected === "__new__") {
|
|
5595
|
+
const name = await promptInput("Workspace name", false) || "My Workspace";
|
|
5596
|
+
const ws = await sdk.workspaces.createWorkspace(arbi, name);
|
|
5597
|
+
workspaceId = ws.external_id;
|
|
5598
|
+
workspaceName = ws.name;
|
|
5599
|
+
} else {
|
|
5600
|
+
workspaceId = selected;
|
|
5601
|
+
workspaceName = memberWorkspaces.find((w) => w.external_id === selected)?.name || "";
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
updateConfig({ selectedWorkspaceId: workspaceId });
|
|
5605
|
+
console.log("");
|
|
5606
|
+
success("Setup complete!");
|
|
5607
|
+
console.log("");
|
|
5608
|
+
console.log(` Server: ${ref(config.baseUrl)}`);
|
|
5609
|
+
console.log(` Account: ${ref(email)}`);
|
|
5610
|
+
console.log(` Workspace: ${workspaceName} (${ref(workspaceId)})`);
|
|
5611
|
+
console.log("");
|
|
5612
|
+
dim('Try: arbi ask "hello"');
|
|
5613
|
+
} catch (err) {
|
|
5614
|
+
error(`Login failed: ${sdk.getErrorMessage(err)}`);
|
|
5615
|
+
process.exit(1);
|
|
5616
|
+
}
|
|
5617
|
+
});
|
|
5618
|
+
}
|
|
5619
|
+
var CENTRAL_API_URL2 = "https://central.arbi.work";
|
|
5620
|
+
var DEFAULT_PASSWORD = "agent-dev-1234";
|
|
5621
|
+
async function getVerificationCode2(email, apiKey) {
|
|
5622
|
+
const params = new URLSearchParams({ email });
|
|
5623
|
+
const res = await fetch(`${CENTRAL_API_URL2}/license-management/verify-ci?${params.toString()}`, {
|
|
5624
|
+
method: "GET",
|
|
5625
|
+
headers: { "x-api-key": apiKey }
|
|
5626
|
+
});
|
|
5627
|
+
if (!res.ok) {
|
|
5628
|
+
const body = await res.text().catch(() => "");
|
|
5629
|
+
throw new Error(`Failed to get verification code: ${res.status} ${body}`);
|
|
5630
|
+
}
|
|
5631
|
+
const data = await res.json();
|
|
5632
|
+
const words = data?.verification_words ?? data?.verification_code ?? null;
|
|
5633
|
+
if (!words) throw new Error("No verification code in response");
|
|
5634
|
+
return Array.isArray(words) ? words.join(" ") : String(words);
|
|
5635
|
+
}
|
|
5636
|
+
function registerAgentCreateCommand(program2) {
|
|
5637
|
+
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(
|
|
5638
|
+
async (url, opts) => {
|
|
5639
|
+
const { config, source } = store.resolveConfigWithFallbacks();
|
|
5640
|
+
if (url) {
|
|
5641
|
+
const domain = new URL(url).hostname;
|
|
5642
|
+
config.baseUrl = url.replace(/\/$/, "");
|
|
5643
|
+
config.deploymentDomain = domain;
|
|
5644
|
+
store.saveConfig(config);
|
|
5645
|
+
dim(`Server: ${config.baseUrl}`);
|
|
5646
|
+
} else {
|
|
5647
|
+
dim(`Server: ${config.baseUrl} (from ${source})`);
|
|
5648
|
+
}
|
|
5649
|
+
const supportApiKey = process.env.SUPPORT_API_KEY;
|
|
5650
|
+
if (!supportApiKey) {
|
|
5651
|
+
error(
|
|
5652
|
+
"SUPPORT_API_KEY is required.\nSet it with: export SUPPORT_API_KEY=<key>\nOr source from .env: source .env && arbi agent-create"
|
|
5653
|
+
);
|
|
5654
|
+
process.exit(1);
|
|
5655
|
+
}
|
|
5656
|
+
const timestamp2 = Date.now();
|
|
5657
|
+
let email = opts.email || `agent-${timestamp2}@${config.deploymentDomain}`;
|
|
5658
|
+
if (!email.includes("@")) {
|
|
5659
|
+
email = `${email}@${config.deploymentDomain}`;
|
|
5660
|
+
}
|
|
5661
|
+
dim(`Email: ${email}`);
|
|
5662
|
+
const arbiClient = client.createArbiClient({
|
|
5663
|
+
baseUrl: config.baseUrl,
|
|
5664
|
+
deploymentDomain: config.deploymentDomain,
|
|
5665
|
+
credentials: "omit"
|
|
5666
|
+
});
|
|
5667
|
+
await arbiClient.crypto.initSodium();
|
|
5668
|
+
const verifyResponse = await arbiClient.fetch.POST("/v1/user/verify-email", {
|
|
5669
|
+
body: { email }
|
|
5670
|
+
});
|
|
5671
|
+
if (verifyResponse.error) {
|
|
5672
|
+
error(`verify-email failed: ${JSON.stringify(verifyResponse.error)}`);
|
|
5673
|
+
process.exit(1);
|
|
5674
|
+
}
|
|
5675
|
+
let verificationCode;
|
|
5676
|
+
try {
|
|
5677
|
+
verificationCode = await getVerificationCode2(email, supportApiKey);
|
|
5678
|
+
} catch (err) {
|
|
5679
|
+
error(`Failed to get verification code: ${sdk.getErrorMessage(err)}`);
|
|
5680
|
+
process.exit(1);
|
|
5681
|
+
}
|
|
5682
|
+
try {
|
|
5683
|
+
await arbiClient.auth.register({
|
|
5684
|
+
email,
|
|
5685
|
+
password: opts.password,
|
|
5686
|
+
verificationCode,
|
|
5687
|
+
firstName: "Agent",
|
|
5688
|
+
lastName: `${timestamp2}`
|
|
5689
|
+
});
|
|
5690
|
+
} catch (err) {
|
|
5691
|
+
error(`Registration failed: ${sdk.getErrorMessage(err)}`);
|
|
5692
|
+
process.exit(1);
|
|
5693
|
+
}
|
|
5694
|
+
try {
|
|
5695
|
+
const { arbi } = await sdk.performPasswordLogin(config, email, opts.password, store);
|
|
5696
|
+
const ws = await sdk.workspaces.createWorkspace(arbi, opts.workspaceName);
|
|
5697
|
+
updateConfig({ selectedWorkspaceId: ws.external_id });
|
|
5698
|
+
console.log("");
|
|
5699
|
+
success("Agent account created!");
|
|
5700
|
+
console.log("");
|
|
5701
|
+
console.log(` Email: ${ref(email)}`);
|
|
5702
|
+
console.log(` Password: ${ref(opts.password)}`);
|
|
5703
|
+
console.log(` Workspace: ${ws.name} (${ref(ws.external_id)})`);
|
|
5704
|
+
console.log(` Server: ${ref(config.baseUrl)}`);
|
|
5705
|
+
console.log("");
|
|
5706
|
+
dim('Ready to use: arbi ask "hello"');
|
|
5707
|
+
} catch (err) {
|
|
5708
|
+
error(`Post-registration setup failed: ${sdk.getErrorMessage(err)}`);
|
|
5709
|
+
process.exit(1);
|
|
5710
|
+
}
|
|
5711
|
+
}
|
|
5712
|
+
);
|
|
5713
|
+
}
|
|
5376
5714
|
|
|
5377
5715
|
// src/index.ts
|
|
5378
5716
|
console.debug = () => {
|
|
@@ -5383,7 +5721,7 @@ console.info = (...args) => {
|
|
|
5383
5721
|
_origInfo(...args);
|
|
5384
5722
|
};
|
|
5385
5723
|
var program = new commander.Command();
|
|
5386
|
-
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.
|
|
5724
|
+
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.13");
|
|
5387
5725
|
registerConfigCommand(program);
|
|
5388
5726
|
registerLoginCommand(program);
|
|
5389
5727
|
registerRegisterCommand(program);
|
|
@@ -5405,6 +5743,8 @@ registerAgentconfigCommand(program);
|
|
|
5405
5743
|
registerHealthCommand(program);
|
|
5406
5744
|
registerTuiCommand(program);
|
|
5407
5745
|
registerUpdateCommand(program);
|
|
5746
|
+
registerQuickstartCommand(program);
|
|
5747
|
+
registerAgentCreateCommand(program);
|
|
5408
5748
|
program.parse();
|
|
5409
5749
|
//# sourceMappingURL=index.js.map
|
|
5410
5750
|
//# sourceMappingURL=index.js.map
|