@arbidocs/cli 0.1.3 → 0.3.0
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.cjs +84 -105
- package/dist/index.cjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
var commander = require('commander');
|
|
5
5
|
var core = require('@arbidocs/core');
|
|
6
|
-
var sdk = require('@arbidocs/sdk');
|
|
7
6
|
var prompts = require('@inquirer/prompts');
|
|
7
|
+
var sdk = require('@arbidocs/sdk');
|
|
8
8
|
var fs = require('fs');
|
|
9
|
-
var
|
|
9
|
+
var path = require('path');
|
|
10
10
|
var child_process = require('child_process');
|
|
11
11
|
var module$1 = require('module');
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
|
|
|
14
14
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
15
|
|
|
16
16
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
17
|
-
var
|
|
17
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
18
18
|
|
|
19
19
|
var store = new core.FileConfigStore();
|
|
20
20
|
function getConfig() {
|
|
@@ -37,9 +37,6 @@ function requireConfig() {
|
|
|
37
37
|
function getCredentials() {
|
|
38
38
|
return store.getCredentials();
|
|
39
39
|
}
|
|
40
|
-
function saveCredentials(creds) {
|
|
41
|
-
store.saveCredentials(creds);
|
|
42
|
-
}
|
|
43
40
|
function deleteCredentials() {
|
|
44
41
|
store.deleteCredentials();
|
|
45
42
|
}
|
|
@@ -3385,22 +3382,11 @@ async function promptConfirm(message, defaultValue = true) {
|
|
|
3385
3382
|
// src/commands/login.ts
|
|
3386
3383
|
function registerLoginCommand(program2) {
|
|
3387
3384
|
program2.command("login").description("Log in to ARBI").option("-e, --email <email>", "Email address (or ARBI_EMAIL env var)").option("-p, --password <password>", "Password (or ARBI_PASSWORD env var)").option("-w, --workspace <id>", "Workspace ID to select after login").action(async (opts) => {
|
|
3388
|
-
const config = requireConfig();
|
|
3385
|
+
const config = store.requireConfig();
|
|
3389
3386
|
const email = opts.email || process.env.ARBI_EMAIL || await promptInput("Email");
|
|
3390
3387
|
const pw = opts.password || process.env.ARBI_PASSWORD || await promptPassword("Password");
|
|
3391
|
-
const arbi = sdk.createArbiClient({
|
|
3392
|
-
baseUrl: config.baseUrl,
|
|
3393
|
-
deploymentDomain: config.deploymentDomain,
|
|
3394
|
-
credentials: "omit"
|
|
3395
|
-
});
|
|
3396
|
-
await arbi.crypto.initSodium();
|
|
3397
3388
|
try {
|
|
3398
|
-
const
|
|
3399
|
-
saveCredentials({
|
|
3400
|
-
email,
|
|
3401
|
-
signingPrivateKeyBase64: arbi.crypto.bytesToBase64(result.signingPrivateKey),
|
|
3402
|
-
serverSessionKeyBase64: arbi.crypto.bytesToBase64(result.serverSessionKey)
|
|
3403
|
-
});
|
|
3389
|
+
const { arbi } = await core.performPasswordLogin(config, email, pw, store);
|
|
3404
3390
|
const { data: workspaces2 } = await arbi.fetch.GET("/api/user/workspaces");
|
|
3405
3391
|
const wsList = workspaces2 || [];
|
|
3406
3392
|
console.log(`Logged in as ${email}`);
|
|
@@ -3423,21 +3409,13 @@ function registerLoginCommand(program2) {
|
|
|
3423
3409
|
console.log(`Workspace: ${wsList[0].name} (${wsList[0].external_id})`);
|
|
3424
3410
|
return;
|
|
3425
3411
|
}
|
|
3426
|
-
const choices =
|
|
3427
|
-
const totalDocs = ws2.shared_document_count + ws2.private_document_count;
|
|
3428
|
-
return {
|
|
3429
|
-
name: `${ws2.name} (${totalDocs} docs)`,
|
|
3430
|
-
value: ws2.external_id,
|
|
3431
|
-
description: ws2.external_id
|
|
3432
|
-
};
|
|
3433
|
-
});
|
|
3412
|
+
const choices = core.formatWorkspaceChoices(wsList);
|
|
3434
3413
|
const selected = await promptSelect("Select workspace", choices);
|
|
3435
3414
|
updateConfig({ selectedWorkspaceId: selected });
|
|
3436
3415
|
const ws = wsList.find((w) => w.external_id === selected);
|
|
3437
3416
|
console.log(`Workspace: ${ws.name} (${selected})`);
|
|
3438
3417
|
} catch (err) {
|
|
3439
|
-
|
|
3440
|
-
console.error(`Login failed: ${msg}`);
|
|
3418
|
+
console.error(`Login failed: ${core.getErrorMessage(err)}`);
|
|
3441
3419
|
process.exit(1);
|
|
3442
3420
|
}
|
|
3443
3421
|
});
|
|
@@ -3516,42 +3494,28 @@ async function interactiveRegister(config, opts) {
|
|
|
3516
3494
|
console.log(`
|
|
3517
3495
|
Registered successfully as ${email}`);
|
|
3518
3496
|
} catch (err) {
|
|
3519
|
-
|
|
3520
|
-
console.error(`Registration failed: ${msg}`);
|
|
3497
|
+
console.error(`Registration failed: ${core.getErrorMessage(err)}`);
|
|
3521
3498
|
process.exit(1);
|
|
3522
3499
|
}
|
|
3523
3500
|
const doLogin = await promptConfirm("Log in now?");
|
|
3524
3501
|
if (doLogin) {
|
|
3525
3502
|
try {
|
|
3526
|
-
const
|
|
3527
|
-
|
|
3528
|
-
email,
|
|
3529
|
-
signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),
|
|
3530
|
-
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey)
|
|
3531
|
-
});
|
|
3532
|
-
const { data: workspaces2 } = await arbi.fetch.GET("/api/user/workspaces");
|
|
3503
|
+
const { arbi: loggedInArbi } = await core.performPasswordLogin(config, email, password2, store);
|
|
3504
|
+
const { data: workspaces2 } = await loggedInArbi.fetch.GET("/api/user/workspaces");
|
|
3533
3505
|
const wsList = workspaces2 || [];
|
|
3534
3506
|
console.log(`Logged in as ${email}`);
|
|
3535
3507
|
if (wsList.length === 1) {
|
|
3536
3508
|
updateConfig({ selectedWorkspaceId: wsList[0].external_id });
|
|
3537
3509
|
console.log(`Workspace: ${wsList[0].name} (${wsList[0].external_id})`);
|
|
3538
3510
|
} else if (wsList.length > 1) {
|
|
3539
|
-
const choices =
|
|
3540
|
-
const totalDocs = ws2.shared_document_count + ws2.private_document_count;
|
|
3541
|
-
return {
|
|
3542
|
-
name: `${ws2.name} (${totalDocs} docs)`,
|
|
3543
|
-
value: ws2.external_id,
|
|
3544
|
-
description: ws2.external_id
|
|
3545
|
-
};
|
|
3546
|
-
});
|
|
3511
|
+
const choices = core.formatWorkspaceChoices(wsList);
|
|
3547
3512
|
const selected = await promptSelect("Select workspace", choices);
|
|
3548
3513
|
updateConfig({ selectedWorkspaceId: selected });
|
|
3549
3514
|
const ws = wsList.find((w) => w.external_id === selected);
|
|
3550
3515
|
console.log(`Workspace: ${ws.name} (${selected})`);
|
|
3551
3516
|
}
|
|
3552
3517
|
} catch (err) {
|
|
3553
|
-
|
|
3554
|
-
console.error(`Login failed: ${msg}`);
|
|
3518
|
+
console.error(`Login failed: ${core.getErrorMessage(err)}`);
|
|
3555
3519
|
console.error("You can log in later with: arbi login");
|
|
3556
3520
|
}
|
|
3557
3521
|
}
|
|
@@ -3596,8 +3560,7 @@ async function nonInteractiveRegister(config, opts) {
|
|
|
3596
3560
|
});
|
|
3597
3561
|
console.log(`Registered: ${email}`);
|
|
3598
3562
|
} catch (err) {
|
|
3599
|
-
|
|
3600
|
-
console.error(`Registration failed: ${msg}`);
|
|
3563
|
+
console.error(`Registration failed: ${core.getErrorMessage(err)}`);
|
|
3601
3564
|
process.exit(1);
|
|
3602
3565
|
}
|
|
3603
3566
|
}
|
|
@@ -3638,8 +3601,7 @@ function runAction(fn) {
|
|
|
3638
3601
|
try {
|
|
3639
3602
|
await fn();
|
|
3640
3603
|
} catch (err) {
|
|
3641
|
-
|
|
3642
|
-
console.error(`Error: ${msg}`);
|
|
3604
|
+
console.error(`Error: ${core.getErrorMessage(err)}`);
|
|
3643
3605
|
process.exit(1);
|
|
3644
3606
|
}
|
|
3645
3607
|
};
|
|
@@ -3735,14 +3697,7 @@ function registerWorkspacesCommand(program2) {
|
|
|
3735
3697
|
}
|
|
3736
3698
|
selectedId = id;
|
|
3737
3699
|
} else {
|
|
3738
|
-
const choices =
|
|
3739
|
-
const totalDocs = ws2.shared_document_count + ws2.private_document_count;
|
|
3740
|
-
return {
|
|
3741
|
-
name: `${ws2.name} (${totalDocs} docs)`,
|
|
3742
|
-
value: ws2.external_id,
|
|
3743
|
-
description: ws2.external_id
|
|
3744
|
-
};
|
|
3745
|
-
});
|
|
3700
|
+
const choices = core.formatWorkspaceChoices(data);
|
|
3746
3701
|
selectedId = await promptSelect("Select workspace", choices);
|
|
3747
3702
|
}
|
|
3748
3703
|
updateConfig({ selectedWorkspaceId: selectedId });
|
|
@@ -3848,11 +3803,23 @@ function registerWorkspacesCommand(program2) {
|
|
|
3848
3803
|
})()
|
|
3849
3804
|
);
|
|
3850
3805
|
}
|
|
3851
|
-
function
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3806
|
+
function statusSymbol(status) {
|
|
3807
|
+
switch (status) {
|
|
3808
|
+
case "completed":
|
|
3809
|
+
return "\u2713";
|
|
3810
|
+
// ✓
|
|
3811
|
+
case "failed":
|
|
3812
|
+
return "\u2717";
|
|
3813
|
+
// ✗
|
|
3814
|
+
case "skipped":
|
|
3815
|
+
return "\u2013";
|
|
3816
|
+
// –
|
|
3817
|
+
case "queued":
|
|
3818
|
+
return "\u25CB";
|
|
3819
|
+
// ○
|
|
3820
|
+
default:
|
|
3821
|
+
return "\u25CF";
|
|
3822
|
+
}
|
|
3856
3823
|
}
|
|
3857
3824
|
async function fetchDocChoices(arbi, workspaceId) {
|
|
3858
3825
|
const data = await core.documents.listDocuments(arbi, workspaceId);
|
|
@@ -3878,9 +3845,31 @@ function registerDocsCommand(program2) {
|
|
|
3878
3845
|
printTable(
|
|
3879
3846
|
[
|
|
3880
3847
|
{ header: "ID", width: 24, value: (r) => r.external_id },
|
|
3881
|
-
{ header: "
|
|
3882
|
-
{
|
|
3883
|
-
|
|
3848
|
+
{ header: "S", width: 2, value: (r) => statusSymbol(r.status) },
|
|
3849
|
+
{
|
|
3850
|
+
header: "TITLE",
|
|
3851
|
+
width: 34,
|
|
3852
|
+
value: (r) => {
|
|
3853
|
+
const meta = r.doc_metadata;
|
|
3854
|
+
return meta?.title ?? r.file_name ?? "Unnamed";
|
|
3855
|
+
}
|
|
3856
|
+
},
|
|
3857
|
+
{
|
|
3858
|
+
header: "DATE",
|
|
3859
|
+
width: 12,
|
|
3860
|
+
value: (r) => {
|
|
3861
|
+
const meta = r.doc_metadata;
|
|
3862
|
+
return meta?.doc_date ?? "-";
|
|
3863
|
+
}
|
|
3864
|
+
},
|
|
3865
|
+
{
|
|
3866
|
+
header: "SUMMARY",
|
|
3867
|
+
width: 50,
|
|
3868
|
+
value: (r) => {
|
|
3869
|
+
const meta = r.doc_metadata;
|
|
3870
|
+
return meta?.doc_subject ?? "-";
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3884
3873
|
],
|
|
3885
3874
|
data
|
|
3886
3875
|
);
|
|
@@ -3981,9 +3970,7 @@ function registerDocsCommand(program2) {
|
|
|
3981
3970
|
process.exit(1);
|
|
3982
3971
|
}
|
|
3983
3972
|
const data = await core.documents.getParsedContent(
|
|
3984
|
-
config.baseUrl,
|
|
3985
|
-
accessToken,
|
|
3986
|
-
workspaceKeyHeader,
|
|
3973
|
+
{ baseUrl: config.baseUrl, accessToken, workspaceKeyHeader },
|
|
3987
3974
|
docId,
|
|
3988
3975
|
stage
|
|
3989
3976
|
);
|
|
@@ -4004,22 +3991,14 @@ function registerUploadCommand(program2) {
|
|
|
4004
3991
|
opts.workspace
|
|
4005
3992
|
);
|
|
4006
3993
|
const uploadedDocs = /* @__PURE__ */ new Map();
|
|
3994
|
+
const auth = { baseUrl: config.baseUrl, accessToken, workspaceKeyHeader };
|
|
4007
3995
|
for (const filePath of files) {
|
|
4008
|
-
const
|
|
4009
|
-
|
|
4010
|
-
const result = await core.documents.uploadFile(
|
|
4011
|
-
config.baseUrl,
|
|
4012
|
-
accessToken,
|
|
4013
|
-
workspaceKeyHeader,
|
|
4014
|
-
workspaceId,
|
|
4015
|
-
new Blob([fileBuffer]),
|
|
4016
|
-
fileName
|
|
4017
|
-
);
|
|
4018
|
-
console.log(`Uploaded: ${fileName} (${result.doc_ext_ids.join(", ")})`);
|
|
3996
|
+
const result = await core.documents.uploadLocalFile(auth, workspaceId, filePath);
|
|
3997
|
+
console.log(`Uploaded: ${result.fileName} (${result.doc_ext_ids.join(", ")})`);
|
|
4019
3998
|
if (result.duplicates && result.duplicates.length > 0) {
|
|
4020
3999
|
console.log(` Duplicates: ${result.duplicates.join(", ")}`);
|
|
4021
4000
|
}
|
|
4022
|
-
for (const id of result.doc_ext_ids) uploadedDocs.set(id, fileName);
|
|
4001
|
+
for (const id of result.doc_ext_ids) uploadedDocs.set(id, result.fileName);
|
|
4023
4002
|
}
|
|
4024
4003
|
if (opts.watch && uploadedDocs.size > 0) {
|
|
4025
4004
|
const pending = new Set(uploadedDocs.keys());
|
|
@@ -4071,9 +4050,7 @@ function registerDownloadCommand(program2) {
|
|
|
4071
4050
|
docId = await promptSearch("Select document to download", choices);
|
|
4072
4051
|
}
|
|
4073
4052
|
const res = await core.documents.downloadDocument(
|
|
4074
|
-
config.baseUrl,
|
|
4075
|
-
accessToken,
|
|
4076
|
-
workspaceKeyHeader,
|
|
4053
|
+
{ baseUrl: config.baseUrl, accessToken, workspaceKeyHeader },
|
|
4077
4054
|
docId
|
|
4078
4055
|
);
|
|
4079
4056
|
let filename = `${docId}`;
|
|
@@ -4082,18 +4059,19 @@ function registerDownloadCommand(program2) {
|
|
|
4082
4059
|
const match = disposition.match(/filename[*]?=(?:UTF-8''|"?)([^";]+)/i);
|
|
4083
4060
|
if (match) filename = decodeURIComponent(match[1].replace(/"/g, ""));
|
|
4084
4061
|
}
|
|
4085
|
-
const outputPath = opts.output ||
|
|
4062
|
+
const outputPath = opts.output || path__default.default.join(process.cwd(), filename);
|
|
4086
4063
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
4087
4064
|
fs__default.default.writeFileSync(outputPath, buffer);
|
|
4088
4065
|
console.log(
|
|
4089
|
-
`Downloaded: ${
|
|
4066
|
+
`Downloaded: ${path__default.default.basename(outputPath)} (${(buffer.length / (1024 * 1024)).toFixed(1)} MB)`
|
|
4090
4067
|
);
|
|
4091
4068
|
})()
|
|
4092
4069
|
);
|
|
4093
4070
|
}
|
|
4094
4071
|
function registerAskCommand(program2) {
|
|
4095
|
-
program2.command("ask <question
|
|
4096
|
-
(
|
|
4072
|
+
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(
|
|
4073
|
+
(words, opts) => runAction(async () => {
|
|
4074
|
+
const question = words.join(" ");
|
|
4097
4075
|
const { arbi, accessToken, workspaceKeyHeader, workspaceId, config } = await resolveWorkspace(opts.workspace);
|
|
4098
4076
|
const session = getChatSession();
|
|
4099
4077
|
if (opts.new) {
|
|
@@ -4112,7 +4090,7 @@ function registerAskCommand(program2) {
|
|
|
4112
4090
|
parentMessageExtId: session.lastMessageExtId,
|
|
4113
4091
|
configExtId: opts.config
|
|
4114
4092
|
});
|
|
4115
|
-
const
|
|
4093
|
+
const result = await core.streamSSE(res, {
|
|
4116
4094
|
onToken: (content) => process.stdout.write(content),
|
|
4117
4095
|
onAgentStep: (data) => {
|
|
4118
4096
|
if (opts.verbose) {
|
|
@@ -4125,8 +4103,15 @@ function registerAskCommand(program2) {
|
|
|
4125
4103
|
Error: ${message}`)
|
|
4126
4104
|
});
|
|
4127
4105
|
process.stdout.write("\n");
|
|
4128
|
-
if (assistantMessageExtId) {
|
|
4129
|
-
|
|
4106
|
+
if (result.assistantMessageExtId) {
|
|
4107
|
+
const updates = {
|
|
4108
|
+
lastMessageExtId: result.assistantMessageExtId
|
|
4109
|
+
};
|
|
4110
|
+
const conversationExtId = result.userMessage?.conversation_ext_id ?? result.metadata?.conversation_ext_id;
|
|
4111
|
+
if (conversationExtId) {
|
|
4112
|
+
updates.conversationExtId = conversationExtId;
|
|
4113
|
+
}
|
|
4114
|
+
updateChatSession(updates);
|
|
4130
4115
|
}
|
|
4131
4116
|
})()
|
|
4132
4117
|
);
|
|
@@ -4181,10 +4166,7 @@ function registerContactsCommand(program2) {
|
|
|
4181
4166
|
{
|
|
4182
4167
|
header: "NAME",
|
|
4183
4168
|
width: 20,
|
|
4184
|
-
value: (r) =>
|
|
4185
|
-
const u = r.user;
|
|
4186
|
-
return u ? [u.given_name, u.family_name].filter(Boolean).join(" ") : "";
|
|
4187
|
-
}
|
|
4169
|
+
value: (r) => core.formatUserName(r.user)
|
|
4188
4170
|
},
|
|
4189
4171
|
{ header: "EMAIL", width: 30, value: (r) => r.email },
|
|
4190
4172
|
{ header: "STATUS", width: 18, value: (r) => r.status }
|
|
@@ -4220,8 +4202,7 @@ function registerContactsCommand(program2) {
|
|
|
4220
4202
|
contactIds = await promptCheckbox(
|
|
4221
4203
|
"Select contacts to remove",
|
|
4222
4204
|
data.map((c) => {
|
|
4223
|
-
const
|
|
4224
|
-
const name = u ? [u.given_name, u.family_name].filter(Boolean).join(" ") : "";
|
|
4205
|
+
const name = core.formatUserName(c.user);
|
|
4225
4206
|
return {
|
|
4226
4207
|
name: name ? `${name} (${c.email})` : c.email,
|
|
4227
4208
|
value: c.external_id
|
|
@@ -4257,9 +4238,7 @@ function registerDmCommand(program2) {
|
|
|
4257
4238
|
width: 22,
|
|
4258
4239
|
value: (r) => {
|
|
4259
4240
|
const s = r.sender;
|
|
4260
|
-
|
|
4261
|
-
const name = [s.given_name, s.family_name].filter(Boolean).join(" ");
|
|
4262
|
-
return name || s.email || "";
|
|
4241
|
+
return core.formatUserName(s) || s?.email || "";
|
|
4263
4242
|
}
|
|
4264
4243
|
},
|
|
4265
4244
|
{ header: "READ", width: 6, value: (r) => r.read ? "yes" : "no" },
|
|
@@ -4282,7 +4261,7 @@ function registerDmCommand(program2) {
|
|
|
4282
4261
|
"Send to",
|
|
4283
4262
|
contacts.map((c) => {
|
|
4284
4263
|
const u = c.user;
|
|
4285
|
-
const name =
|
|
4264
|
+
const name = core.formatUserName(u);
|
|
4286
4265
|
return {
|
|
4287
4266
|
name: name ? `${name} (${c.email})` : c.email,
|
|
4288
4267
|
value: u?.external_id ?? c.external_id,
|
|
@@ -4326,7 +4305,7 @@ function registerDmCommand(program2) {
|
|
|
4326
4305
|
"Select messages to mark as read",
|
|
4327
4306
|
unread.map((m) => {
|
|
4328
4307
|
const s = m.sender;
|
|
4329
|
-
const from =
|
|
4308
|
+
const from = core.formatUserName(s) || s?.email || "";
|
|
4330
4309
|
return {
|
|
4331
4310
|
name: `${from}: ${(m.content ?? "").slice(0, 50)}`,
|
|
4332
4311
|
value: m.external_id
|
|
@@ -4353,7 +4332,7 @@ function registerDmCommand(program2) {
|
|
|
4353
4332
|
"Select messages to delete",
|
|
4354
4333
|
data.map((m) => {
|
|
4355
4334
|
const s = m.sender;
|
|
4356
|
-
const from =
|
|
4335
|
+
const from = core.formatUserName(s) || s?.email || "";
|
|
4357
4336
|
return {
|
|
4358
4337
|
name: `${from}: ${(m.content ?? "").slice(0, 50)}`,
|
|
4359
4338
|
value: m.external_id
|