@arbidocs/cli 0.3.40 β 0.3.42
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 +8 -0
- package/SKILL.md +25 -7
- package/dist/index.js +239 -35
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.3.42
|
|
4
|
+
|
|
5
|
+
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.40...HEAD)
|
|
6
|
+
|
|
7
|
+
### π Enhancements
|
|
8
|
+
|
|
9
|
+
- **cli:** Workspace improvements β --json, workspace current, delete + copy fixes ([#623](https://github.com/arbicity/ARBI-frontend/pull/623))
|
|
10
|
+
|
|
3
11
|
## v0.3.40
|
|
4
12
|
|
|
5
13
|
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.39...HEAD)
|
package/SKILL.md
CHANGED
|
@@ -32,12 +32,12 @@ Documents, conversations, and tags are scoped per workspace. An active workspace
|
|
|
32
32
|
Common moves:
|
|
33
33
|
|
|
34
34
|
- List: `arbi workspaces` (human) Β· `arbi workspaces --json` (script) Β· `arbi workspaces --ids`
|
|
35
|
-
- Active workspace ID: `arbi workspace current` (prints the ID, empty string if none)
|
|
36
|
-
- Pick/switch: `arbi workspace select <id>` β clears the chat session; uploaded docs in other workspaces are unaffected
|
|
37
|
-
- Create: `arbi workspace create "My WS"` β does NOT auto-select
|
|
38
|
-
- Rename / edit: `arbi workspace update '{"name":"New Name"}'`
|
|
39
|
-
- Delete: `arbi workspace delete [id]` β
|
|
40
|
-
- Share: `arbi workspace add-user <email> -r <role>` where role is `owner|collaborator|guest` (
|
|
35
|
+
- Active workspace ID: `arbi workspace current` (prints the ID, empty string if none) Β· `arbi workspace current --json` for full details
|
|
36
|
+
- Pick/switch: `arbi workspace select <id-or-name>` β accepts a workspace ID or a unique (case-insensitive) name; clears the chat session; uploaded docs in other workspaces are unaffected
|
|
37
|
+
- Create: `arbi workspace create "My WS"` β does NOT auto-select. Use `--select` to create + select in one go, `--json` for scripts
|
|
38
|
+
- Rename / edit: `arbi workspace update '{"name":"New Name"}'` (add `--json` for scripts)
|
|
39
|
+
- Delete: `arbi workspace delete [id-or-name]` β prompts for confirmation in interactive shells. In non-TTY shells you **must** pass `-y/--yes` (otherwise the command refuses to delete). If you delete the active workspace, the selection is cleared. `--json` outputs `{id, deleted}`
|
|
40
|
+
- Share: `arbi workspace add-user <email> -r <role>` where role is `owner|collaborator|guest` (plan-limited β free tier has 0 collaborator slots)
|
|
41
41
|
- List members: `arbi workspace users [--json]`
|
|
42
42
|
- Remove member: `arbi workspace remove-user <user-id>`
|
|
43
43
|
- Copy docs between workspaces: `arbi workspace copy <target-ws-id> <doc-id>...` β only copies documents that have finished indexing; partial/failed copies exit non-zero
|
|
@@ -45,8 +45,10 @@ Common moves:
|
|
|
45
45
|
Scripting notes:
|
|
46
46
|
|
|
47
47
|
- The table output of `arbi workspaces` is NOT reliably parseable (names contain spaces, status cells may contain glyphs). Use `--json` or `--ids`.
|
|
48
|
+
- Switch-by-name in one line: `arbi workspace select "My WS"`. If the name is ambiguous, the CLI lists the matches and exits non-zero β use the ID.
|
|
48
49
|
- Sessions persist between CLI invocations via the config file (default `~/.arbi/`, override with `ARBI_CONFIG_DIR`).
|
|
49
50
|
- Per-agent isolation: run agents with their own `ARBI_CONFIG_DIR=<path>` (or `ARBI_ID=<name>`) to avoid stomping each other's active workspace.
|
|
51
|
+
- Agent accounts typically have 0 collaborator slots, so `workspace add-user` errors with "Collaborator limit reached" unless the plan is upgraded.
|
|
50
52
|
|
|
51
53
|
## Tips
|
|
52
54
|
|
|
@@ -54,7 +56,7 @@ Scripting notes:
|
|
|
54
56
|
- If a command fails with "fetch failed", check connectivity with `arbi health`.
|
|
55
57
|
- Use `arbi ask -n` to start a fresh conversation (forget prior context).
|
|
56
58
|
- Use `arbi ask -v` for verbose output showing retrieval steps.
|
|
57
|
-
- Use `arbi status --json` and `arbi workspace current` to read CLI state from scripts.
|
|
59
|
+
- Use `arbi status --json` and `arbi workspace current` to read CLI state from scripts. `arbi workspaces --json` lists every workspace with `is_selected` marked.
|
|
58
60
|
|
|
59
61
|
## For Automations / AI Agents
|
|
60
62
|
|
|
@@ -76,3 +78,19 @@ Scripting notes:
|
|
|
76
78
|
- **No color leakage**: chalk auto-disables ANSI codes when stdout is not a TTY, so `arbi docs --json | jq`, `arbi workspaces --json | jq`, etc. work cleanly. Status messages and spinners go to stderr; stdout is safe to pipe.
|
|
77
79
|
- **Typo suggestions**: `arbi updat` β `error: unknown command 'updat' (Did you mean update?)` (exit 1). Works for top-level commands and nested subcommands.
|
|
78
80
|
- **Completion**: `arbi completion install` (no `bash`/`zsh` arg β auto-detected from `$SHELL`).
|
|
81
|
+
|
|
82
|
+
## Document Lifecycle (for agents)
|
|
83
|
+
|
|
84
|
+
All document list/search/meta commands support machine-readable output. Prefer `--json`.
|
|
85
|
+
|
|
86
|
+
- **Upload**: `arbi add <paths...> --json --no-watch` β prints a single JSON summary line with `docIds` and `skippedDetails`. Progress and reconnect noise are routed to stderr; stdout stays clean when `--json` is set.
|
|
87
|
+
- **List**: `arbi docs --json` returns an array (or `[]` when empty). `--ids` prints one doc id per line. `--csv` prints a CSV with header. All three work on an empty workspace without erroring.
|
|
88
|
+
- **Filter**: `arbi docs --status completed,failed`, `--folder <pattern>`, `--ext pdf,docx`, `--query <text>`. Combine with `--limit <n>` to stop early.
|
|
89
|
+
- **Lite mode**: `arbi docs --lite --json` skips per-doc decryption for speed, but `doctags` and `doc_metadata` come back empty/null. Use full mode (omit `--lite`) if you need those.
|
|
90
|
+
- **Per-doc**: `arbi doc get <id...>` returns full JSON (no flag needed). `arbi doc delete <id...>` and `arbi doc update <id> '<json>'` take IDs directly.
|
|
91
|
+
- **Upload by URL**: `arbi doc upload-url <url> --json`.
|
|
92
|
+
- **Download**: `arbi download <id> -o <path>` writes the file; `-o -` streams raw bytes to stdout; `--json` emits a `{doc_id, path, bytes, filename}` metadata line after writing.
|
|
93
|
+
- **Tags**: `arbi tags list --json`, `arbi tags create <name> -t <type>`, `arbi tags delete <id>`.
|
|
94
|
+
- **Doctags** (tagβdoc link): `arbi doctags create <tag-id> <doc-id...>` / `arbi doctags delete <tag-id> <doc-id...>`.
|
|
95
|
+
- **Retrieve only**: `arbi find <query> --json` returns raw retrieval results without running the LLM.
|
|
96
|
+
- **Exit codes**: 0 on success (including clean skips), 1 on error. Errors print to stderr.
|
package/dist/index.js
CHANGED
|
@@ -3641,7 +3641,7 @@ function getLatestVersion(skipCache = false) {
|
|
|
3641
3641
|
}
|
|
3642
3642
|
}
|
|
3643
3643
|
function getCurrentVersion() {
|
|
3644
|
-
return "0.3.
|
|
3644
|
+
return "0.3.42";
|
|
3645
3645
|
}
|
|
3646
3646
|
function readChangelog(fromVersion, toVersion) {
|
|
3647
3647
|
try {
|
|
@@ -3694,17 +3694,17 @@ function showChangelog(fromVersion, toVersion) {
|
|
|
3694
3694
|
async function checkForUpdates(autoUpdate) {
|
|
3695
3695
|
try {
|
|
3696
3696
|
const latest = getLatestVersion();
|
|
3697
|
-
if (!latest || latest === "0.3.
|
|
3697
|
+
if (!latest || latest === "0.3.42") return;
|
|
3698
3698
|
if (autoUpdate) {
|
|
3699
3699
|
warn(`
|
|
3700
|
-
Your arbi version is out of date (${"0.3.
|
|
3700
|
+
Your arbi version is out of date (${"0.3.42"} \u2192 ${latest}). Updating...`);
|
|
3701
3701
|
child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
|
|
3702
|
-
showChangelog("0.3.
|
|
3702
|
+
showChangelog("0.3.42", latest);
|
|
3703
3703
|
console.log(`Updated to ${latest}.`);
|
|
3704
3704
|
} else {
|
|
3705
3705
|
warn(
|
|
3706
3706
|
`
|
|
3707
|
-
Your arbi version is out of date (${"0.3.
|
|
3707
|
+
Your arbi version is out of date (${"0.3.42"} \u2192 ${latest}).
|
|
3708
3708
|
Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
3709
3709
|
);
|
|
3710
3710
|
}
|
|
@@ -3714,9 +3714,9 @@ Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
|
3714
3714
|
function hintUpdateOnError() {
|
|
3715
3715
|
try {
|
|
3716
3716
|
const cached = readCache();
|
|
3717
|
-
if (cached && cached.latest !== "0.3.
|
|
3717
|
+
if (cached && cached.latest !== "0.3.42") {
|
|
3718
3718
|
warn(
|
|
3719
|
-
`Your arbi version is out of date (${"0.3.
|
|
3719
|
+
`Your arbi version is out of date (${"0.3.42"} \u2192 ${cached.latest}). Run "arbi update".`
|
|
3720
3720
|
);
|
|
3721
3721
|
}
|
|
3722
3722
|
} catch {
|
|
@@ -4417,12 +4417,49 @@ function registerStatusCommand(program2) {
|
|
|
4417
4417
|
}
|
|
4418
4418
|
});
|
|
4419
4419
|
}
|
|
4420
|
+
function resolveWorkspaceSelector(list, selector) {
|
|
4421
|
+
const byId = list.find((w) => w.external_id === selector);
|
|
4422
|
+
if (byId) return { ok: true, id: byId.external_id, ws: byId };
|
|
4423
|
+
const lower = selector.toLowerCase();
|
|
4424
|
+
const byName = list.filter((w) => (w.name ?? "").toLowerCase() === lower);
|
|
4425
|
+
if (byName.length === 1) return { ok: true, id: byName[0].external_id, ws: byName[0] };
|
|
4426
|
+
if (byName.length > 1) return { ok: false, reason: "ambiguous", matches: byName };
|
|
4427
|
+
return { ok: false, reason: "not-found" };
|
|
4428
|
+
}
|
|
4429
|
+
function printResolveError(list, selector, res) {
|
|
4430
|
+
if (res.ok) return;
|
|
4431
|
+
if (res.reason === "ambiguous") {
|
|
4432
|
+
error(`Workspace name "${selector}" is ambiguous \u2014 multiple matches:`);
|
|
4433
|
+
for (const w of res.matches ?? []) error(` ${w.external_id} ${w.name}`);
|
|
4434
|
+
error("Use the workspace ID instead.");
|
|
4435
|
+
return;
|
|
4436
|
+
}
|
|
4437
|
+
error(`Workspace ${selector} not found.`);
|
|
4438
|
+
error("Available workspaces:");
|
|
4439
|
+
for (const w of list) error(` ${w.external_id} ${w.name}`);
|
|
4440
|
+
}
|
|
4420
4441
|
function registerWorkspacesCommand(program2) {
|
|
4421
|
-
program2.command("workspaces").description("List workspaces").action(
|
|
4422
|
-
runAction(async () => {
|
|
4442
|
+
program2.command("workspaces").description("List workspaces").option("--json", "Output as JSON").option("--ids", "Output only workspace IDs (one per line)").action(
|
|
4443
|
+
(opts) => runAction(async () => {
|
|
4423
4444
|
const { arbi } = await resolveAuth();
|
|
4424
4445
|
const data = await sdk.workspaces.listWorkspaces(arbi);
|
|
4425
4446
|
updateCompletionCache(data);
|
|
4447
|
+
if (opts.ids) {
|
|
4448
|
+
for (const w of data) console.log(w.external_id);
|
|
4449
|
+
return;
|
|
4450
|
+
}
|
|
4451
|
+
if (opts.json) {
|
|
4452
|
+
const selectedId = getConfig()?.selectedWorkspaceId ?? null;
|
|
4453
|
+
const out = data.map((w) => ({
|
|
4454
|
+
id: w.external_id,
|
|
4455
|
+
name: w.name,
|
|
4456
|
+
docs: w.shared_document_count + w.private_document_count,
|
|
4457
|
+
role: w.users?.[0]?.role ?? null,
|
|
4458
|
+
is_selected: w.external_id === selectedId
|
|
4459
|
+
}));
|
|
4460
|
+
console.log(JSON.stringify(out, null, 2));
|
|
4461
|
+
return;
|
|
4462
|
+
}
|
|
4426
4463
|
if (data.length === 0) {
|
|
4427
4464
|
console.log("No workspaces found.");
|
|
4428
4465
|
return;
|
|
@@ -4444,11 +4481,51 @@ function registerWorkspacesCommand(program2) {
|
|
|
4444
4481
|
],
|
|
4445
4482
|
data
|
|
4446
4483
|
);
|
|
4447
|
-
})
|
|
4484
|
+
})()
|
|
4448
4485
|
);
|
|
4449
4486
|
const workspace = program2.command("workspace").description("Workspace management");
|
|
4450
|
-
workspace.command("
|
|
4451
|
-
(
|
|
4487
|
+
workspace.command("current").description("Print the currently selected workspace ID (empty string if none)").option("--json", "Output full details as JSON").action(
|
|
4488
|
+
(opts) => runAction(async () => {
|
|
4489
|
+
const selectedId = getConfig()?.selectedWorkspaceId ?? "";
|
|
4490
|
+
if (!opts.json) {
|
|
4491
|
+
console.log(selectedId);
|
|
4492
|
+
return;
|
|
4493
|
+
}
|
|
4494
|
+
if (!selectedId) {
|
|
4495
|
+
console.log(JSON.stringify({ id: null, name: null, docs: 0, role: null }, null, 2));
|
|
4496
|
+
return;
|
|
4497
|
+
}
|
|
4498
|
+
const { arbi } = await resolveAuth();
|
|
4499
|
+
const data = await sdk.workspaces.listWorkspaces(arbi);
|
|
4500
|
+
const ws = data.find((w) => w.external_id === selectedId);
|
|
4501
|
+
if (!ws) {
|
|
4502
|
+
console.log(
|
|
4503
|
+
JSON.stringify(
|
|
4504
|
+
{ id: selectedId, name: null, docs: 0, role: null, stale: true },
|
|
4505
|
+
null,
|
|
4506
|
+
2
|
|
4507
|
+
)
|
|
4508
|
+
);
|
|
4509
|
+
return;
|
|
4510
|
+
}
|
|
4511
|
+
console.log(
|
|
4512
|
+
JSON.stringify(
|
|
4513
|
+
{
|
|
4514
|
+
id: ws.external_id,
|
|
4515
|
+
name: ws.name,
|
|
4516
|
+
docs: ws.shared_document_count + ws.private_document_count,
|
|
4517
|
+
role: ws.users?.[0]?.role ?? null
|
|
4518
|
+
},
|
|
4519
|
+
null,
|
|
4520
|
+
2
|
|
4521
|
+
)
|
|
4522
|
+
);
|
|
4523
|
+
})()
|
|
4524
|
+
);
|
|
4525
|
+
workspace.command("select [id-or-name]").description(
|
|
4526
|
+
"Select active workspace (accepts ID or unique name; interactive picker if nothing given)"
|
|
4527
|
+
).action(
|
|
4528
|
+
(idOrName) => runAction(async () => {
|
|
4452
4529
|
const { arbi } = await resolveAuth();
|
|
4453
4530
|
const data = await sdk.workspaces.listWorkspaces(arbi);
|
|
4454
4531
|
updateCompletionCache(data);
|
|
@@ -4457,15 +4534,13 @@ function registerWorkspacesCommand(program2) {
|
|
|
4457
4534
|
return;
|
|
4458
4535
|
}
|
|
4459
4536
|
let selectedId;
|
|
4460
|
-
if (
|
|
4461
|
-
const
|
|
4462
|
-
if (!
|
|
4463
|
-
|
|
4464
|
-
error("Available workspaces:");
|
|
4465
|
-
for (const w of data) error(` ${w.external_id} ${w.name}`);
|
|
4537
|
+
if (idOrName) {
|
|
4538
|
+
const res = resolveWorkspaceSelector(data, idOrName);
|
|
4539
|
+
if (!res.ok) {
|
|
4540
|
+
printResolveError(data, idOrName, res);
|
|
4466
4541
|
process.exit(1);
|
|
4467
4542
|
}
|
|
4468
|
-
selectedId = id;
|
|
4543
|
+
selectedId = res.id;
|
|
4469
4544
|
} else {
|
|
4470
4545
|
const choices = sdk.formatWorkspaceChoices(data);
|
|
4471
4546
|
selectedId = await promptSelect("Select workspace", choices);
|
|
@@ -4476,7 +4551,7 @@ function registerWorkspacesCommand(program2) {
|
|
|
4476
4551
|
success(`Selected: ${ws.name} (${ref(selectedId)})`);
|
|
4477
4552
|
})()
|
|
4478
4553
|
);
|
|
4479
|
-
workspace.command("create <name>").description("Create a new workspace").option("-d, --description <text>", "Workspace description").option("--public", "Make workspace public", false).action(
|
|
4554
|
+
workspace.command("create <name>").description("Create a new workspace").option("-d, --description <text>", "Workspace description").option("--public", "Make workspace public", false).option("--select", "Set the new workspace as the active selection", false).option("--json", "Output the new workspace as JSON").action(
|
|
4480
4555
|
(name, opts) => runAction(async () => {
|
|
4481
4556
|
const { arbi, loginResult } = await resolveAuth();
|
|
4482
4557
|
const userProjects = await sdk.projects.listProjects(arbi);
|
|
@@ -4491,37 +4566,114 @@ function registerWorkspacesCommand(program2) {
|
|
|
4491
4566
|
opts.description,
|
|
4492
4567
|
opts.public ?? false
|
|
4493
4568
|
);
|
|
4569
|
+
if (opts.select) {
|
|
4570
|
+
updateConfig({ selectedWorkspaceId: data.external_id });
|
|
4571
|
+
clearChatSession();
|
|
4572
|
+
}
|
|
4573
|
+
if (opts.json) {
|
|
4574
|
+
console.log(
|
|
4575
|
+
JSON.stringify(
|
|
4576
|
+
{
|
|
4577
|
+
id: data.external_id,
|
|
4578
|
+
name: data.name,
|
|
4579
|
+
selected: opts.select ?? false
|
|
4580
|
+
},
|
|
4581
|
+
null,
|
|
4582
|
+
2
|
|
4583
|
+
)
|
|
4584
|
+
);
|
|
4585
|
+
return;
|
|
4586
|
+
}
|
|
4494
4587
|
success(`Created: ${data.name} (${ref(data.external_id)})`);
|
|
4588
|
+
if (opts.select) success(`Selected: ${data.name} (${ref(data.external_id)})`);
|
|
4495
4589
|
})()
|
|
4496
4590
|
);
|
|
4497
|
-
workspace.command("delete [id]").description("Delete a workspace (defaults to selected workspace)").action(
|
|
4498
|
-
(
|
|
4591
|
+
workspace.command("delete [id-or-name]").description("Delete a workspace (defaults to selected workspace)").option("-y, --yes", "Skip confirmation prompt (required in non-interactive shells)", false).option("--json", "Output the result as JSON").action(
|
|
4592
|
+
(idOrName, opts) => runAction(async () => {
|
|
4499
4593
|
const { arbi } = await resolveAuth();
|
|
4500
|
-
const
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4594
|
+
const config = getConfig();
|
|
4595
|
+
let targetId;
|
|
4596
|
+
let targetName;
|
|
4597
|
+
if (idOrName) {
|
|
4598
|
+
const data = await sdk.workspaces.listWorkspaces(arbi);
|
|
4599
|
+
const res = resolveWorkspaceSelector(data, idOrName);
|
|
4600
|
+
if (!res.ok) {
|
|
4601
|
+
printResolveError(data, idOrName, res);
|
|
4602
|
+
process.exit(1);
|
|
4603
|
+
}
|
|
4604
|
+
targetId = res.id;
|
|
4605
|
+
targetName = res.ws.name;
|
|
4606
|
+
} else {
|
|
4607
|
+
targetId = config?.selectedWorkspaceId;
|
|
4608
|
+
if (!targetId) {
|
|
4609
|
+
error("No workspace ID given and no workspace selected. Run: arbi workspace select");
|
|
4610
|
+
process.exit(1);
|
|
4611
|
+
}
|
|
4612
|
+
}
|
|
4613
|
+
const isInteractive = process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
4614
|
+
if (!opts.yes) {
|
|
4615
|
+
if (!isInteractive) {
|
|
4616
|
+
error(
|
|
4617
|
+
`Refusing to delete ${targetId} without confirmation. Re-run with --yes (non-interactive shell).`
|
|
4618
|
+
);
|
|
4619
|
+
process.exit(1);
|
|
4620
|
+
}
|
|
4621
|
+
const label2 = targetName ? `"${targetName}" (${targetId})` : targetId;
|
|
4622
|
+
const confirmed = await promptConfirm(
|
|
4623
|
+
`Delete workspace ${label2}? This removes all documents, conversations, and tags in it.`,
|
|
4624
|
+
false
|
|
4625
|
+
);
|
|
4626
|
+
if (!confirmed) {
|
|
4627
|
+
console.log("Cancelled.");
|
|
4628
|
+
return;
|
|
4629
|
+
}
|
|
4504
4630
|
}
|
|
4505
4631
|
await sdk.workspaces.deleteWorkspaces(arbi, [targetId]);
|
|
4632
|
+
if (config?.selectedWorkspaceId === targetId) {
|
|
4633
|
+
updateConfig({ selectedWorkspaceId: void 0 });
|
|
4634
|
+
}
|
|
4506
4635
|
const session = getChatSession();
|
|
4507
4636
|
if (session.workspaceId === targetId) {
|
|
4508
4637
|
clearChatSession();
|
|
4509
4638
|
}
|
|
4639
|
+
if (opts.json) {
|
|
4640
|
+
console.log(JSON.stringify({ id: targetId, deleted: true }, null, 2));
|
|
4641
|
+
return;
|
|
4642
|
+
}
|
|
4510
4643
|
success(`Deleted workspace ${targetId}`);
|
|
4511
4644
|
})()
|
|
4512
4645
|
);
|
|
4513
|
-
workspace.command("update <json>").description("Update workspace properties (pass JSON)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
|
|
4646
|
+
workspace.command("update <json>").description("Update workspace properties (pass JSON)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("--json", "Output the updated workspace as JSON").action(
|
|
4514
4647
|
(json, opts) => runAction(async () => {
|
|
4515
4648
|
const body = parseJsonArg(json, `arbi workspace update '{"name": "New Name"}'`);
|
|
4516
4649
|
const { arbi } = await resolveWorkspace(opts.workspace);
|
|
4517
4650
|
const data = await sdk.workspaces.updateWorkspace(arbi, body);
|
|
4651
|
+
if (opts.json) {
|
|
4652
|
+
console.log(JSON.stringify({ id: data.external_id, name: data.name }, null, 2));
|
|
4653
|
+
return;
|
|
4654
|
+
}
|
|
4518
4655
|
success(`Updated: ${data.name} (${ref(data.external_id)})`);
|
|
4519
4656
|
})()
|
|
4520
4657
|
);
|
|
4521
|
-
workspace.command("users").description("List users in the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
|
|
4658
|
+
workspace.command("users").description("List users in the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("--json", "Output as JSON").action(
|
|
4522
4659
|
(opts) => runAction(async () => {
|
|
4523
4660
|
const { arbi } = await resolveWorkspace(opts.workspace);
|
|
4524
4661
|
const data = await sdk.workspaces.listWorkspaceUsers(arbi);
|
|
4662
|
+
if (opts.json) {
|
|
4663
|
+
const out = data.map((r) => {
|
|
4664
|
+
const u = r.user ?? {};
|
|
4665
|
+
return {
|
|
4666
|
+
user_id: u.external_id ?? null,
|
|
4667
|
+
email: u.email ?? null,
|
|
4668
|
+
name: [u.given_name, u.family_name].filter(Boolean).join(" ") || null,
|
|
4669
|
+
role: r.role,
|
|
4670
|
+
document_count: r.document_count,
|
|
4671
|
+
conversation_count: r.conversation_count
|
|
4672
|
+
};
|
|
4673
|
+
});
|
|
4674
|
+
console.log(JSON.stringify(out, null, 2));
|
|
4675
|
+
return;
|
|
4676
|
+
}
|
|
4525
4677
|
if (data.length === 0) {
|
|
4526
4678
|
console.log("No users found.");
|
|
4527
4679
|
return;
|
|
@@ -4598,7 +4750,18 @@ function registerWorkspacesCommand(program2) {
|
|
|
4598
4750
|
signingPrivateKeyBase64
|
|
4599
4751
|
);
|
|
4600
4752
|
const data = await sdk.workspaces.copyDocuments(arbi, targetId, docIds, targetKey);
|
|
4601
|
-
|
|
4753
|
+
const copied = data.documents_copied ?? 0;
|
|
4754
|
+
const requested = docIds.length;
|
|
4755
|
+
if (copied === 0) {
|
|
4756
|
+
error(`Copied 0 of ${requested} document(s). ${data.detail ?? ""}`.trim());
|
|
4757
|
+
error("Hint: documents must be fully indexed before they can be copied.");
|
|
4758
|
+
process.exit(1);
|
|
4759
|
+
}
|
|
4760
|
+
if (copied < requested) {
|
|
4761
|
+
error(`Copied ${copied} of ${requested} document(s). ${data.detail ?? ""}`.trim());
|
|
4762
|
+
return;
|
|
4763
|
+
}
|
|
4764
|
+
success(`Copied ${copied} document(s) to ${targetId}`);
|
|
4602
4765
|
})()
|
|
4603
4766
|
);
|
|
4604
4767
|
}
|
|
@@ -4756,7 +4919,18 @@ function registerDocsCommand(program2) {
|
|
|
4756
4919
|
if (hardLimit !== void 0 && totalFetched >= hardLimit) break;
|
|
4757
4920
|
}
|
|
4758
4921
|
if (totalFetched === 0 && data.length === 0) {
|
|
4759
|
-
|
|
4922
|
+
if (opts.json) {
|
|
4923
|
+
if (opts.output) fs5.writeFileSync(opts.output, "[]\n");
|
|
4924
|
+
else console.log("[]");
|
|
4925
|
+
} else if (opts.ids) {
|
|
4926
|
+
if (opts.output) fs5.writeFileSync(opts.output, "");
|
|
4927
|
+
} else if (opts.csv) {
|
|
4928
|
+
if (opts.output) fs5.writeFileSync(opts.output, csvHeader + "\n");
|
|
4929
|
+
} else if (opts.count) {
|
|
4930
|
+
console.log("0");
|
|
4931
|
+
} else {
|
|
4932
|
+
console.log("No documents found.");
|
|
4933
|
+
}
|
|
4760
4934
|
return;
|
|
4761
4935
|
}
|
|
4762
4936
|
if (!bufferAll && (opts.ids || opts.csv)) {
|
|
@@ -4967,10 +5141,19 @@ function registerDocsCommand(program2) {
|
|
|
4967
5141
|
}
|
|
4968
5142
|
})()
|
|
4969
5143
|
);
|
|
4970
|
-
doc.command("upload-url <urls...>").description("Upload documents from URLs").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("--shared", "Make documents shared", false).action(
|
|
5144
|
+
doc.command("upload-url <urls...>").description("Upload documents from URLs").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("--shared", "Make documents shared", false).option("--json", "Output results as JSON").action(
|
|
4971
5145
|
(urls, opts) => runAction(async () => {
|
|
4972
5146
|
const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
|
|
4973
5147
|
const data = await sdk.documents.uploadUrl(arbi, urls, workspaceId, opts.shared ?? false);
|
|
5148
|
+
if (opts.json) {
|
|
5149
|
+
console.log(
|
|
5150
|
+
JSON.stringify({
|
|
5151
|
+
docIds: data.doc_ext_ids ?? [],
|
|
5152
|
+
skipped: data.skipped ?? []
|
|
5153
|
+
})
|
|
5154
|
+
);
|
|
5155
|
+
return;
|
|
5156
|
+
}
|
|
4974
5157
|
success(`Uploaded: ${(data.doc_ext_ids ?? []).join(", ")}`);
|
|
4975
5158
|
if (data.skipped && data.skipped.length > 0) {
|
|
4976
5159
|
warn(
|
|
@@ -5705,7 +5888,7 @@ Connection closed. ${pending.size} document(s) still processing.`);
|
|
|
5705
5888
|
}
|
|
5706
5889
|
});
|
|
5707
5890
|
await done;
|
|
5708
|
-
} else if (uploadedDocs.size > 0 && !willWatch) {
|
|
5891
|
+
} else if (uploadedDocs.size > 0 && !willWatch && !opts.json) {
|
|
5709
5892
|
dim(
|
|
5710
5893
|
'Tip: Use -W/--watch to monitor processing progress, or run "arbi docs" to check status.'
|
|
5711
5894
|
);
|
|
@@ -6209,7 +6392,13 @@ Connection closed. ${pending.size} document(s) still processing.`);
|
|
|
6209
6392
|
}
|
|
6210
6393
|
}
|
|
6211
6394
|
function registerDownloadCommand(program2) {
|
|
6212
|
-
program2.command("download [doc-id]").description("Download a document (interactive picker if no ID given)").option(
|
|
6395
|
+
program2.command("download [doc-id]").description("Download a document (interactive picker if no ID given)").option(
|
|
6396
|
+
"-o, --output <path>",
|
|
6397
|
+
'Output file path. Use "-" to stream raw bytes to stdout (for piping).'
|
|
6398
|
+
).option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option(
|
|
6399
|
+
"--json",
|
|
6400
|
+
'Emit a JSON metadata line to stdout after writing the file (doc_id, path, bytes, filename). Implies a file write \u2014 use "-o -" or pipe stdout to get bytes without JSON.'
|
|
6401
|
+
).action(
|
|
6213
6402
|
(docId, opts) => runAction(async () => {
|
|
6214
6403
|
const { arbi, config, accessToken } = await resolveWorkspace(opts.workspace);
|
|
6215
6404
|
if (!docId) {
|
|
@@ -6235,9 +6424,24 @@ function registerDownloadCommand(program2) {
|
|
|
6235
6424
|
const match = disposition.match(/filename[*]?=(?:UTF-8''|"?)([^";]+)/i);
|
|
6236
6425
|
if (match) filename = decodeURIComponent(match[1].replace(/"/g, ""));
|
|
6237
6426
|
}
|
|
6238
|
-
const outputPath = opts.output || path5__default.default.join(process.cwd(), filename);
|
|
6239
6427
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
6428
|
+
if (opts.output === "-") {
|
|
6429
|
+
process.stdout.write(buffer);
|
|
6430
|
+
return;
|
|
6431
|
+
}
|
|
6432
|
+
const outputPath = opts.output || path5__default.default.join(process.cwd(), filename);
|
|
6240
6433
|
fs5__default.default.writeFileSync(outputPath, buffer);
|
|
6434
|
+
if (opts.json) {
|
|
6435
|
+
console.log(
|
|
6436
|
+
JSON.stringify({
|
|
6437
|
+
doc_id: docId,
|
|
6438
|
+
path: outputPath,
|
|
6439
|
+
bytes: buffer.length,
|
|
6440
|
+
filename: path5__default.default.basename(outputPath)
|
|
6441
|
+
})
|
|
6442
|
+
);
|
|
6443
|
+
return;
|
|
6444
|
+
}
|
|
6241
6445
|
success(
|
|
6242
6446
|
`Downloaded: ${path5__default.default.basename(outputPath)} (${(buffer.length / (1024 * 1024)).toFixed(1)} MB)`
|
|
6243
6447
|
);
|
|
@@ -8258,7 +8462,7 @@ console.info = (...args) => {
|
|
|
8258
8462
|
_origInfo(...args);
|
|
8259
8463
|
};
|
|
8260
8464
|
var program = new commander.Command();
|
|
8261
|
-
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.
|
|
8465
|
+
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.42");
|
|
8262
8466
|
registerConfigCommand(program);
|
|
8263
8467
|
registerLoginCommand(program);
|
|
8264
8468
|
registerRegisterCommand(program);
|