@arbidocs/cli 0.3.33 → 0.3.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
  'use strict';
3
3
 
4
4
  var commander = require('commander');
5
- var fs4 = require('fs');
6
- var path4 = require('path');
5
+ var fs5 = require('fs');
6
+ var path5 = require('path');
7
7
  var os = require('os');
8
8
  var chalk2 = require('chalk');
9
9
  var sdk = require('@arbidocs/sdk');
@@ -16,24 +16,24 @@ var module$1 = require('module');
16
16
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
17
17
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
18
18
 
19
- var fs4__default = /*#__PURE__*/_interopDefault(fs4);
20
- var path4__default = /*#__PURE__*/_interopDefault(path4);
19
+ var fs5__default = /*#__PURE__*/_interopDefault(fs5);
20
+ var path5__default = /*#__PURE__*/_interopDefault(path5);
21
21
  var os__default = /*#__PURE__*/_interopDefault(os);
22
22
  var chalk2__default = /*#__PURE__*/_interopDefault(chalk2);
23
23
 
24
24
  function getCacheFile() {
25
- const configDir = process.env.ARBI_CONFIG_DIR ?? path4__default.default.join(os__default.default.homedir(), ".arbi");
26
- return path4__default.default.join(configDir, "completions.json");
25
+ const configDir = process.env.ARBI_CONFIG_DIR ?? path5__default.default.join(os__default.default.homedir(), ".arbi");
26
+ return path5__default.default.join(configDir, "completions.json");
27
27
  }
28
28
  function ensureDir(filePath) {
29
- const dir = path4__default.default.dirname(filePath);
30
- if (!fs4__default.default.existsSync(dir)) {
31
- fs4__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
29
+ const dir = path5__default.default.dirname(filePath);
30
+ if (!fs5__default.default.existsSync(dir)) {
31
+ fs5__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
32
32
  }
33
33
  }
34
34
  function getCachedWorkspaceIds() {
35
35
  try {
36
- const content = fs4__default.default.readFileSync(getCacheFile(), "utf-8");
36
+ const content = fs5__default.default.readFileSync(getCacheFile(), "utf-8");
37
37
  const cache = JSON.parse(content);
38
38
  return cache.workspaces.map((w) => w.id);
39
39
  } catch {
@@ -47,7 +47,7 @@ function updateCompletionCache(workspaces3) {
47
47
  };
48
48
  const filePath = getCacheFile();
49
49
  ensureDir(filePath);
50
- fs4__default.default.writeFileSync(filePath, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
50
+ fs5__default.default.writeFileSync(filePath, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
51
51
  }
52
52
 
53
53
  // src/completion.ts
@@ -194,12 +194,12 @@ var ALIAS_LINE = 'alias A="arbi ask"';
194
194
  var ALIAS_MARKER = "# arbi-cli alias";
195
195
  function getShellRcPath() {
196
196
  const shell = process.env.SHELL || "";
197
- if (shell.includes("zsh")) return path4.join(os.homedir(), ".zshrc");
198
- return path4.join(os.homedir(), ".bashrc");
197
+ if (shell.includes("zsh")) return path5.join(os.homedir(), ".zshrc");
198
+ return path5.join(os.homedir(), ".bashrc");
199
199
  }
200
200
  function isAliasInstalled(rcPath) {
201
- if (!fs4.existsSync(rcPath)) return false;
202
- const content = fs4.readFileSync(rcPath, "utf-8");
201
+ if (!fs5.existsSync(rcPath)) return false;
202
+ const content = fs5.readFileSync(rcPath, "utf-8");
203
203
  return content.includes(ALIAS_LINE) || content.includes(ALIAS_MARKER);
204
204
  }
205
205
  function registerConfigCommand(program2) {
@@ -278,7 +278,7 @@ function registerConfigCommand(program2) {
278
278
  dim("Usage: A what is the meaning of life");
279
279
  return;
280
280
  }
281
- fs4.appendFileSync(rcPath, `
281
+ fs5.appendFileSync(rcPath, `
282
282
  ${ALIAS_MARKER}
283
283
  ${ALIAS_LINE}
284
284
  `);
@@ -3600,11 +3600,11 @@ async function promptPassword(message) {
3600
3600
  async function promptConfirm(message, defaultValue = true) {
3601
3601
  return prompts.confirm({ message, default: defaultValue });
3602
3602
  }
3603
- var CACHE_FILE = path4__default.default.join(os__default.default.homedir(), ".arbi", "version-cache.json");
3603
+ var CACHE_FILE = path5__default.default.join(os__default.default.homedir(), ".arbi", "version-cache.json");
3604
3604
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
3605
3605
  function readCache() {
3606
3606
  try {
3607
- const data = JSON.parse(fs4__default.default.readFileSync(CACHE_FILE, "utf8"));
3607
+ const data = JSON.parse(fs5__default.default.readFileSync(CACHE_FILE, "utf8"));
3608
3608
  if (data.latest && data.checkedAt && Date.now() - data.checkedAt < CACHE_TTL_MS) {
3609
3609
  return data;
3610
3610
  }
@@ -3614,9 +3614,9 @@ function readCache() {
3614
3614
  }
3615
3615
  function writeCache(latest) {
3616
3616
  try {
3617
- const dir = path4__default.default.dirname(CACHE_FILE);
3618
- if (!fs4__default.default.existsSync(dir)) fs4__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
3619
- fs4__default.default.writeFileSync(CACHE_FILE, JSON.stringify({ latest, checkedAt: Date.now() }) + "\n");
3617
+ const dir = path5__default.default.dirname(CACHE_FILE);
3618
+ if (!fs5__default.default.existsSync(dir)) fs5__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
3619
+ fs5__default.default.writeFileSync(CACHE_FILE, JSON.stringify({ latest, checkedAt: Date.now() }) + "\n");
3620
3620
  } catch {
3621
3621
  }
3622
3622
  }
@@ -3637,13 +3637,13 @@ function getLatestVersion(skipCache = false) {
3637
3637
  }
3638
3638
  }
3639
3639
  function getCurrentVersion() {
3640
- return "0.3.33";
3640
+ return "0.3.34";
3641
3641
  }
3642
3642
  function readChangelog(fromVersion, toVersion) {
3643
3643
  try {
3644
3644
  const globalRoot = child_process.execSync("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
3645
- const changelogPath = path4__default.default.join(globalRoot, "@arbidocs", "cli", "CHANGELOG.md");
3646
- const text = fs4__default.default.readFileSync(changelogPath, "utf8");
3645
+ const changelogPath = path5__default.default.join(globalRoot, "@arbidocs", "cli", "CHANGELOG.md");
3646
+ const text = fs5__default.default.readFileSync(changelogPath, "utf8");
3647
3647
  return extractSections(text, fromVersion, toVersion);
3648
3648
  } catch {
3649
3649
  return null;
@@ -3690,17 +3690,17 @@ function showChangelog(fromVersion, toVersion) {
3690
3690
  async function checkForUpdates(autoUpdate) {
3691
3691
  try {
3692
3692
  const latest = getLatestVersion();
3693
- if (!latest || latest === "0.3.33") return;
3693
+ if (!latest || latest === "0.3.34") return;
3694
3694
  if (autoUpdate) {
3695
3695
  warn(`
3696
- Your arbi version is out of date (${"0.3.33"} \u2192 ${latest}). Updating...`);
3696
+ Your arbi version is out of date (${"0.3.34"} \u2192 ${latest}). Updating...`);
3697
3697
  child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
3698
- showChangelog("0.3.33", latest);
3698
+ showChangelog("0.3.34", latest);
3699
3699
  console.log(`Updated to ${latest}.`);
3700
3700
  } else {
3701
3701
  warn(
3702
3702
  `
3703
- Your arbi version is out of date (${"0.3.33"} \u2192 ${latest}).
3703
+ Your arbi version is out of date (${"0.3.34"} \u2192 ${latest}).
3704
3704
  Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3705
3705
  );
3706
3706
  }
@@ -3710,9 +3710,9 @@ Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
3710
3710
  function hintUpdateOnError() {
3711
3711
  try {
3712
3712
  const cached = readCache();
3713
- if (cached && cached.latest !== "0.3.33") {
3713
+ if (cached && cached.latest !== "0.3.34") {
3714
3714
  warn(
3715
- `Your arbi version is out of date (${"0.3.33"} \u2192 ${cached.latest}). Run "arbi update".`
3715
+ `Your arbi version is out of date (${"0.3.34"} \u2192 ${cached.latest}). Run "arbi update".`
3716
3716
  );
3717
3717
  }
3718
3718
  } catch {
@@ -3721,18 +3721,18 @@ function hintUpdateOnError() {
3721
3721
  var MAX_TASKS = 50;
3722
3722
  var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
3723
3723
  function getTasksFile() {
3724
- const configDir = process.env.ARBI_CONFIG_DIR ?? path4__default.default.join(os__default.default.homedir(), ".arbi");
3725
- return path4__default.default.join(configDir, "tasks.json");
3724
+ const configDir = process.env.ARBI_CONFIG_DIR ?? path5__default.default.join(os__default.default.homedir(), ".arbi");
3725
+ return path5__default.default.join(configDir, "tasks.json");
3726
3726
  }
3727
3727
  function ensureDir2(filePath) {
3728
- const dir = path4__default.default.dirname(filePath);
3729
- if (!fs4__default.default.existsSync(dir)) {
3730
- fs4__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
3728
+ const dir = path5__default.default.dirname(filePath);
3729
+ if (!fs5__default.default.existsSync(dir)) {
3730
+ fs5__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
3731
3731
  }
3732
3732
  }
3733
3733
  function readTasks() {
3734
3734
  try {
3735
- const content = fs4__default.default.readFileSync(getTasksFile(), "utf-8");
3735
+ const content = fs5__default.default.readFileSync(getTasksFile(), "utf-8");
3736
3736
  return JSON.parse(content);
3737
3737
  } catch {
3738
3738
  return [];
@@ -3741,7 +3741,7 @@ function readTasks() {
3741
3741
  function writeTasks(tasks) {
3742
3742
  const filePath = getTasksFile();
3743
3743
  ensureDir2(filePath);
3744
- fs4__default.default.writeFileSync(filePath, JSON.stringify(tasks, null, 2) + "\n", { mode: 384 });
3744
+ fs5__default.default.writeFileSync(filePath, JSON.stringify(tasks, null, 2) + "\n", { mode: 384 });
3745
3745
  }
3746
3746
  function getTasks() {
3747
3747
  const now = Date.now();
@@ -3975,39 +3975,39 @@ function checkAgentDependency(backend) {
3975
3975
  dim(`${binary} ${match?.[1] ?? version} \u2713`);
3976
3976
  }
3977
3977
  function loadSkillContent() {
3978
- const cliRoot = path4.resolve(path4.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)))), "..");
3978
+ const cliRoot = path5.resolve(path5.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)))), "..");
3979
3979
  try {
3980
- return fs4.readFileSync(path4.join(cliRoot, "SKILL.md"), "utf-8");
3980
+ return fs5.readFileSync(path5.join(cliRoot, "SKILL.md"), "utf-8");
3981
3981
  } catch {
3982
3982
  return void 0;
3983
3983
  }
3984
3984
  }
3985
3985
  function installSkill(backend) {
3986
- const cliRoot = path4.resolve(path4.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)))), "..");
3986
+ const cliRoot = path5.resolve(path5.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)))), "..");
3987
3987
  let skillContent;
3988
3988
  try {
3989
- skillContent = fs4.readFileSync(path4.join(cliRoot, "SKILL.md"), "utf-8");
3989
+ skillContent = fs5.readFileSync(path5.join(cliRoot, "SKILL.md"), "utf-8");
3990
3990
  } catch {
3991
3991
  return;
3992
3992
  }
3993
3993
  if (backend === "claude") {
3994
- const dir = path4.join(os.homedir(), ".claude", "commands", "arbi");
3995
- const target = path4.join(dir, "SKILL.md");
3994
+ const dir = path5.join(os.homedir(), ".claude", "commands", "arbi");
3995
+ const target = path5.join(dir, "SKILL.md");
3996
3996
  try {
3997
- fs4.mkdirSync(dir, { recursive: true });
3998
- if (!fs4.existsSync(target) || fs4.readFileSync(target, "utf-8") !== skillContent) {
3999
- fs4.writeFileSync(target, skillContent, "utf-8");
3997
+ fs5.mkdirSync(dir, { recursive: true });
3998
+ if (!fs5.existsSync(target) || fs5.readFileSync(target, "utf-8") !== skillContent) {
3999
+ fs5.writeFileSync(target, skillContent, "utf-8");
4000
4000
  dim(`Installed ARBI skill \u2192 ${target}`);
4001
4001
  }
4002
4002
  } catch {
4003
4003
  }
4004
4004
  } else if (backend === "openclaw") {
4005
- const workspace = path4.join(os.homedir(), ".arbi", "openclaw-workspace");
4006
- const bootstrap = path4.join(workspace, "BOOTSTRAP.md");
4005
+ const workspace = path5.join(os.homedir(), ".arbi", "openclaw-workspace");
4006
+ const bootstrap = path5.join(workspace, "BOOTSTRAP.md");
4007
4007
  try {
4008
- fs4.mkdirSync(workspace, { recursive: true });
4009
- if (!fs4.existsSync(bootstrap) || fs4.readFileSync(bootstrap, "utf-8") !== skillContent) {
4010
- fs4.writeFileSync(bootstrap, skillContent, "utf-8");
4008
+ fs5.mkdirSync(workspace, { recursive: true });
4009
+ if (!fs5.existsSync(bootstrap) || fs5.readFileSync(bootstrap, "utf-8") !== skillContent) {
4010
+ fs5.writeFileSync(bootstrap, skillContent, "utf-8");
4011
4011
  dim(`Installed ARBI skill \u2192 ${bootstrap}`);
4012
4012
  }
4013
4013
  } catch {
@@ -4656,7 +4656,7 @@ function filterDocs(data, opts) {
4656
4656
  }
4657
4657
  return result;
4658
4658
  }
4659
- async function fetchDocChoices(arbi, _workspaceId) {
4659
+ async function fetchDocChoices(arbi) {
4660
4660
  const data = await sdk.documents.listDocuments(arbi);
4661
4661
  if (data.length === 0) {
4662
4662
  console.log("No documents found.");
@@ -4728,7 +4728,7 @@ function registerDocsCommand(program2) {
4728
4728
  }
4729
4729
  const writeOut = (payload, defaultExt) => {
4730
4730
  if (opts.output) {
4731
- fs4.writeFileSync(opts.output, payload.endsWith("\n") ? payload : payload + "\n");
4731
+ fs5.writeFileSync(opts.output, payload.endsWith("\n") ? payload : payload + "\n");
4732
4732
  success(`Wrote ${data.length} rows to ${opts.output} (${defaultExt})`);
4733
4733
  } else {
4734
4734
  console.log(payload.endsWith("\n") ? payload.slice(0, -1) : payload);
@@ -4818,10 +4818,10 @@ function registerDocsCommand(program2) {
4818
4818
  const doc = program2.command("doc").description("Document management");
4819
4819
  doc.command("get [ids...]").description("Get document details (interactive picker if no IDs given)").action(
4820
4820
  (ids) => runAction(async () => {
4821
- const { arbi, workspaceId } = await resolveWorkspace();
4821
+ const { arbi } = await resolveWorkspace();
4822
4822
  let docIds = ids && ids.length > 0 ? ids : void 0;
4823
4823
  if (!docIds) {
4824
- const choices = await fetchDocChoices(arbi, workspaceId);
4824
+ const choices = await fetchDocChoices(arbi);
4825
4825
  const selected = await promptCheckbox("Select documents", choices);
4826
4826
  if (selected.length === 0) return;
4827
4827
  docIds = selected;
@@ -4849,10 +4849,10 @@ function registerDocsCommand(program2) {
4849
4849
  );
4850
4850
  doc.command("delete [ids...]").description("Delete documents (interactive picker if no IDs given)").action(
4851
4851
  (ids) => runAction(async () => {
4852
- const { arbi, workspaceId } = await resolveWorkspace();
4852
+ const { arbi } = await resolveWorkspace();
4853
4853
  let docIds = ids && ids.length > 0 ? ids : void 0;
4854
4854
  if (!docIds) {
4855
- const choices = await fetchDocChoices(arbi, workspaceId);
4855
+ const choices = await fetchDocChoices(arbi);
4856
4856
  const selected = await promptCheckbox("Select documents to delete", choices);
4857
4857
  if (selected.length === 0) return;
4858
4858
  docIds = selected;
@@ -4873,8 +4873,8 @@ function registerDocsCommand(program2) {
4873
4873
  );
4874
4874
  success(`Updated ${data.length} document(s).`);
4875
4875
  } else {
4876
- const { arbi, workspaceId } = await resolveWorkspace();
4877
- const choices = await fetchDocChoices(arbi, workspaceId);
4876
+ const { arbi } = await resolveWorkspace();
4877
+ const choices = await fetchDocChoices(arbi);
4878
4878
  const docId = await promptSearch("Select document to update", choices);
4879
4879
  const field = await promptSelect("Field to update", [
4880
4880
  { name: "Title", value: "title" },
@@ -5005,12 +5005,16 @@ function registerDocsCommand(program2) {
5005
5005
  const h = Math.floor(m / 60);
5006
5006
  return `${h}h${m % 60}m`;
5007
5007
  };
5008
+ const formatClock = (ts) => {
5009
+ const d = new Date(ts);
5010
+ const pad = (n) => n.toString().padStart(2, "0");
5011
+ return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
5012
+ };
5008
5013
  const printStatus = (prefix = "") => {
5009
- const elapsed = Date.now() - startMs;
5014
+ const now = Date.now();
5015
+ const elapsed = now - startMs;
5010
5016
  const rate = submitted > 0 ? submitted / elapsed * 1e3 : 0;
5011
- const remaining = total - submitted;
5012
- const etaMs = rate > 0 ? remaining / rate * 1e3 : 0;
5013
- const bar = `submitted=${submitted}/${total} ok=${succeeded} fail=${failed} rate=${rate.toFixed(1)}/s elapsed=${formatDuration(elapsed)}` + (rate > 0 && remaining > 0 ? ` eta=${formatDuration(etaMs)}` : "");
5017
+ const bar = `[${formatClock(now)}] ${submitted}/${total} patched=${succeeded} failed=${failed} rate=${rate.toFixed(1)}/s elapsed=${formatDuration(elapsed)}`;
5014
5018
  console.log(`${prefix}${bar}`);
5015
5019
  };
5016
5020
  let statusTimer;
@@ -5098,6 +5102,8 @@ function registerDocsCommand(program2) {
5098
5102
  })()
5099
5103
  );
5100
5104
  }
5105
+
5106
+ // src/commands/upload-shared.ts
5101
5107
  function printSummary(summary) {
5102
5108
  console.log("");
5103
5109
  console.log("Upload summary:");
@@ -5115,24 +5121,296 @@ function printSummary(summary) {
5115
5121
  }
5116
5122
  }
5117
5123
  }
5124
+ function countSupportedFiles(dirPath) {
5125
+ let count = 0;
5126
+ for (const entry of fs5__default.default.readdirSync(dirPath, { withFileTypes: true })) {
5127
+ const full = `${dirPath}/${entry.name}`;
5128
+ if (entry.isDirectory()) {
5129
+ count += countSupportedFiles(full);
5130
+ } else if (entry.isFile()) {
5131
+ const ext = path5__default.default.extname(entry.name).toLowerCase();
5132
+ if (sdk.documents.SUPPORTED_EXTENSIONS.has(ext)) count++;
5133
+ }
5134
+ }
5135
+ return count;
5136
+ }
5137
+ function mergeBatchResult(summary, uploadedDocs, result, sourceLabel, opts) {
5138
+ for (const [folder, info] of result.folders) {
5139
+ summary.folders += 1;
5140
+ summary.totalFiles += info.fileCount;
5141
+ if (!opts.json) {
5142
+ success(
5143
+ ` ${folder || "<root>"}: ${info.fileCount} file(s) \u2192 ${info.doc_ext_ids.length} uploaded`
5144
+ );
5145
+ if (info.skipped.length > 0) {
5146
+ warn(` Skipped: ${info.skipped.map((s) => `${s.file_name} (${s.reason})`).join(", ")}`);
5147
+ }
5148
+ }
5149
+ for (const docId of info.doc_ext_ids) uploadedDocs.set(docId, sourceLabel);
5150
+ }
5151
+ summary.uploaded += result.doc_ext_ids.length;
5152
+ summary.skipped += result.skipped.length;
5153
+ summary.docIds.push(...result.doc_ext_ids);
5154
+ summary.skippedDetails.push(...result.skipped);
5155
+ }
5156
+ function classifyDirectInputs(inputPaths) {
5157
+ const out = [];
5158
+ for (const p of inputPaths) {
5159
+ if (!fs5__default.default.existsSync(p)) {
5160
+ error(`Path not found: ${p}`);
5161
+ process.exit(1);
5162
+ }
5163
+ const resolved = path5__default.default.resolve(p);
5164
+ const stat = fs5__default.default.statSync(resolved);
5165
+ if (stat.isDirectory()) {
5166
+ out.push({ kind: "dir", absolutePath: resolved, originalPath: p });
5167
+ continue;
5168
+ }
5169
+ const ext = path5__default.default.extname(resolved).toLowerCase();
5170
+ if (ext === ".zip") {
5171
+ out.push({ kind: "zip", absolutePath: resolved, originalPath: p });
5172
+ continue;
5173
+ }
5174
+ if (sdk.documentsNode.ARCHIVE_EXTENSIONS.has(ext)) {
5175
+ out.push({ kind: "archive", absolutePath: resolved, originalPath: p });
5176
+ continue;
5177
+ }
5178
+ if (!sdk.documents.SUPPORTED_EXTENSIONS.has(ext)) {
5179
+ warn(`Skipping unsupported file: ${p}`);
5180
+ continue;
5181
+ }
5182
+ out.push({ kind: "file", absolutePath: resolved, originalPath: p });
5183
+ }
5184
+ return out;
5185
+ }
5186
+ async function runDirectUploadMode(inputPaths, opts) {
5187
+ const isInteractive = process.stdout.isTTY === true;
5188
+ const watchPref = getConfig()?.watch !== false;
5189
+ const willWatch = opts.watch === false ? false : opts.watch === true || watchPref && isInteractive;
5190
+ const inputs = classifyDirectInputs(inputPaths);
5191
+ if (inputs.length === 0) {
5192
+ warn("No supported files found to upload.");
5193
+ return;
5194
+ }
5195
+ if (opts.dryRun) {
5196
+ for (const inp of inputs) {
5197
+ if (inp.kind === "file") {
5198
+ const folder = opts.folder ?? "<workspace root>";
5199
+ console.log(` ${inp.originalPath} \u2192 ${folder}`);
5200
+ } else if (inp.kind === "dir") {
5201
+ const count = countSupportedFiles(inp.absolutePath);
5202
+ console.log(` ${inp.originalPath}: directory (${count} supported file(s))`);
5203
+ } else if (inp.kind === "zip") {
5204
+ console.log(` ${inp.originalPath}: zip archive (contents would be extracted + uploaded)`);
5205
+ } else {
5206
+ console.log(
5207
+ ` ${inp.originalPath}: ${path5__default.default.extname(inp.absolutePath).slice(1)} archive (contents would be extracted + uploaded)`
5208
+ );
5209
+ }
5210
+ }
5211
+ console.log(`Would upload ${inputs.length} input(s) via --s3.`);
5212
+ return;
5213
+ }
5214
+ const { arbi, config, accessToken, workspaceId } = await resolveWorkspace(opts.workspace, {
5215
+ skipNotifications: willWatch
5216
+ });
5217
+ const creds = store.requireCredentials();
5218
+ const workspaceKey = await sdk.getRawWorkspaceKey(arbi, workspaceId, creds.signingPrivateKeyBase64);
5219
+ const summary = {
5220
+ totalFiles: 0,
5221
+ uploaded: 0,
5222
+ skipped: 0,
5223
+ duplicates: 0,
5224
+ folders: 0,
5225
+ docIds: [],
5226
+ skippedDetails: []
5227
+ };
5228
+ const uploadedDocs = /* @__PURE__ */ new Map();
5229
+ const directoryOpts = {
5230
+ configExtId: opts.config,
5231
+ onBatchStart: (progress) => {
5232
+ if (!opts.json) {
5233
+ dim(
5234
+ ` [${progress.batch}/${progress.totalBatches}] Uploading ${progress.filesInBatch} file(s) from ${progress.folder} via direct-to-MinIO...`
5235
+ );
5236
+ }
5237
+ }
5238
+ };
5239
+ const plainFiles = [];
5240
+ for (const inp of inputs) {
5241
+ if (inp.kind === "file") {
5242
+ plainFiles.push(inp.absolutePath);
5243
+ continue;
5244
+ }
5245
+ if (inp.kind === "dir") {
5246
+ const result2 = await sdk.documentsNode.uploadLocalDirectoryDirect(
5247
+ arbi,
5248
+ workspaceKey,
5249
+ inp.absolutePath,
5250
+ directoryOpts
5251
+ );
5252
+ if (result2.doc_ext_ids.length === 0 && result2.skipped.length === 0) {
5253
+ warn(`No supported files found in directory: ${inp.originalPath}`);
5254
+ continue;
5255
+ }
5256
+ mergeBatchResult(summary, uploadedDocs, result2, inp.originalPath, opts);
5257
+ if (!opts.json) {
5258
+ success(
5259
+ `Uploaded directory: ${inp.originalPath} (${result2.doc_ext_ids.length} document(s) total)`
5260
+ );
5261
+ }
5262
+ continue;
5263
+ }
5264
+ if (inp.kind === "zip") {
5265
+ const result2 = await sdk.documentsNode.uploadLocalZipDirect(
5266
+ arbi,
5267
+ workspaceKey,
5268
+ inp.absolutePath,
5269
+ directoryOpts
5270
+ );
5271
+ if (result2.doc_ext_ids.length === 0 && result2.skipped.length === 0) {
5272
+ warn(`No supported files found in zip: ${inp.originalPath}`);
5273
+ continue;
5274
+ }
5275
+ mergeBatchResult(summary, uploadedDocs, result2, inp.originalPath, opts);
5276
+ if (!opts.json) {
5277
+ success(
5278
+ `Uploaded zip: ${inp.originalPath} (${result2.doc_ext_ids.length} document(s) total)`
5279
+ );
5280
+ }
5281
+ continue;
5282
+ }
5283
+ const result = await sdk.documentsNode.uploadLocalArchiveDirect(
5284
+ arbi,
5285
+ workspaceKey,
5286
+ inp.absolutePath,
5287
+ directoryOpts
5288
+ );
5289
+ if (result.doc_ext_ids.length === 0 && result.skipped.length === 0) {
5290
+ warn(`No supported files found in archive: ${inp.originalPath}`);
5291
+ continue;
5292
+ }
5293
+ mergeBatchResult(summary, uploadedDocs, result, inp.originalPath, opts);
5294
+ if (!opts.json) {
5295
+ success(
5296
+ `Uploaded archive: ${inp.originalPath} (${result.doc_ext_ids.length} document(s) total)`
5297
+ );
5298
+ }
5299
+ }
5300
+ if (plainFiles.length > 0) {
5301
+ if (!opts.json) {
5302
+ dim(
5303
+ ` Uploading ${plainFiles.length} file(s)${opts.folder ? ` \u2192 ${opts.folder}` : ""} via direct-to-MinIO...`
5304
+ );
5305
+ }
5306
+ const result = await sdk.documentsNode.uploadLocalFilesDirect(arbi, workspaceKey, plainFiles, {
5307
+ folder: opts.folder,
5308
+ configExtId: opts.config
5309
+ });
5310
+ summary.totalFiles += plainFiles.length;
5311
+ summary.uploaded += result.doc_ext_ids.length;
5312
+ summary.skipped += result.skipped.length;
5313
+ summary.docIds.push(...result.doc_ext_ids);
5314
+ summary.skippedDetails.push(...result.skipped);
5315
+ for (let i = 0; i < result.doc_ext_ids.length && i < plainFiles.length; i++) {
5316
+ uploadedDocs.set(result.doc_ext_ids[i], path5__default.default.basename(plainFiles[i]));
5317
+ }
5318
+ if (!opts.json) {
5319
+ success(
5320
+ ` ${opts.folder || "<root>"}: ${result.doc_ext_ids.length} uploaded, ${result.skipped.length} skipped`
5321
+ );
5322
+ }
5323
+ }
5324
+ if (opts.json) {
5325
+ console.log(JSON.stringify(summary));
5326
+ } else {
5327
+ printSummary(summary);
5328
+ }
5329
+ if (willWatch && uploadedDocs.size > 0) {
5330
+ const pending = new Set(uploadedDocs.keys());
5331
+ const failed = /* @__PURE__ */ new Map();
5332
+ console.log(`
5333
+ Watching ${pending.size} document(s)...`);
5334
+ let onDone;
5335
+ const done = new Promise((r) => {
5336
+ onDone = r;
5337
+ });
5338
+ const conn = await sdk.connectWebSocket({
5339
+ baseUrl: config.baseUrl,
5340
+ accessToken,
5341
+ onMessage: (msg) => {
5342
+ if (client.isMessageType(msg, "task_update")) {
5343
+ if (!pending.has(msg.doc_ext_id)) return;
5344
+ const docName = uploadedDocs.get(msg.doc_ext_id) || msg.file_name;
5345
+ const extra = msg;
5346
+ if (msg.status === "failed") {
5347
+ const reason = extra.error_reason || extra.status_details || extra.detail || "Unknown error";
5348
+ failed.set(msg.doc_ext_id, reason);
5349
+ console.log(` ${docName}: ${status(msg.status)} \u2014 ${reason}`);
5350
+ pending.delete(msg.doc_ext_id);
5351
+ } else {
5352
+ console.log(` ${docName}: ${status(msg.status)} (${msg.progress}%)`);
5353
+ if (sdk.DOC_TERMINAL_STATUSES.has(msg.status)) pending.delete(msg.doc_ext_id);
5354
+ }
5355
+ if (pending.size === 0) conn.close();
5356
+ }
5357
+ },
5358
+ onClose: () => {
5359
+ if (failed.size > 0) {
5360
+ error(`
5361
+ ${failed.size} document(s) failed to process:`);
5362
+ for (const [docId, reason] of failed) {
5363
+ error(` ${uploadedDocs.get(docId) || docId}: ${reason}`);
5364
+ }
5365
+ }
5366
+ if (pending.size > 0) {
5367
+ warn(`
5368
+ Connection closed. ${pending.size} document(s) still processing.`);
5369
+ dim('Run "arbi watch" to continue monitoring, or "arbi docs" to check status.');
5370
+ } else if (failed.size === 0 && uploadedDocs.size > 0) {
5371
+ success("\nAll documents processed successfully.");
5372
+ }
5373
+ onDone();
5374
+ }
5375
+ });
5376
+ await done;
5377
+ }
5378
+ }
5379
+
5380
+ // src/commands/upload.ts
5118
5381
  function registerUploadCommand(program2) {
5119
5382
  program2.command("add [paths...]").alias("upload").description("Add files, directories, or zip archives to the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-W, --watch", "Watch document processing progress after upload").option("--no-watch", "Skip watching document processing").option("--dry-run", "Show what would be uploaded without uploading").option("--json", "Output results as JSON").option("--config <id>", "Config ext_id to use (e.g. cfg-xxx for SKIP_DUPLICATES)").option("--manifest <file>", "Read newline-delimited paths from file (eDiscovery mode)").option("--log <file>", "Append per-file JSONL audit log (eDiscovery mode)").option("--resume", "Skip paths already completed in --log (requires --log)").option("--fail-fast", "Abort on first upload error").option("--root <dir>", "Root directory for backend folder paths (defaults to common parent)").option(
5120
5383
  "--limit <n>",
5121
5384
  "Max files to upload this run (applied after --resume filter, manifest mode only)"
5122
- ).action(
5385
+ ).option(
5386
+ "-s, --s3",
5387
+ "Upload via the direct-to-MinIO flow (SecretBox on the client, presigned PUT)"
5388
+ ).option("--folder <name>", "Backend folder for plain-file uploads (direct upload only)").action(
5123
5389
  (paths, opts) => runAction(async () => {
5124
5390
  const isManifestMode = Boolean(opts.manifest || opts.log || opts.resume);
5125
5391
  const inputPaths = paths ?? [];
5126
5392
  if (isManifestMode) {
5393
+ if (opts.s3) {
5394
+ error("--s3 is not supported with manifest mode yet.");
5395
+ process.exit(1);
5396
+ }
5127
5397
  await runManifestMode(inputPaths, opts);
5128
5398
  return;
5129
5399
  }
5400
+ if (opts.s3) {
5401
+ if (inputPaths.length === 0) {
5402
+ error("No paths provided.");
5403
+ process.exit(1);
5404
+ }
5405
+ await runDirectUploadMode(inputPaths, opts);
5406
+ return;
5407
+ }
5130
5408
  if (inputPaths.length === 0) {
5131
5409
  error("No paths provided. Pass file/dir args or use --manifest <file>.");
5132
5410
  process.exit(1);
5133
5411
  }
5134
5412
  for (const p of inputPaths) {
5135
- if (!fs4__default.default.existsSync(p)) {
5413
+ if (!fs5__default.default.existsSync(p)) {
5136
5414
  error(`Path not found: ${p}`);
5137
5415
  process.exit(1);
5138
5416
  }
@@ -5174,10 +5452,10 @@ function registerUploadCommand(program2) {
5174
5452
  }
5175
5453
  };
5176
5454
  for (const filePath of inputPaths) {
5177
- const stat = fs4__default.default.statSync(filePath);
5455
+ const stat = fs5__default.default.statSync(filePath);
5178
5456
  if (stat.isDirectory()) {
5179
5457
  if (opts.dryRun) {
5180
- const count = countSupportedFiles(filePath);
5458
+ const count = countSupportedFiles2(filePath);
5181
5459
  console.log(`${filePath}: ${count} supported file(s) would be uploaded`);
5182
5460
  summary.totalFiles += count;
5183
5461
  continue;
@@ -5378,12 +5656,12 @@ function updateSummary(summary, result) {
5378
5656
  summary.docIds.push(...result.doc_ext_ids);
5379
5657
  summary.skippedDetails.push(...result.skipped);
5380
5658
  }
5381
- function countSupportedFiles(dirPath) {
5659
+ function countSupportedFiles2(dirPath) {
5382
5660
  let count = 0;
5383
- for (const entry of fs4__default.default.readdirSync(dirPath, { withFileTypes: true })) {
5661
+ for (const entry of fs5__default.default.readdirSync(dirPath, { withFileTypes: true })) {
5384
5662
  const fullPath = `${dirPath}/${entry.name}`;
5385
5663
  if (entry.isDirectory()) {
5386
- count += countSupportedFiles(fullPath);
5664
+ count += countSupportedFiles2(fullPath);
5387
5665
  } else if (entry.isFile()) {
5388
5666
  const ext = entry.name.toLowerCase().lastIndexOf(".");
5389
5667
  if (ext >= 0) {
@@ -5398,8 +5676,8 @@ function countSupportedFiles(dirPath) {
5398
5676
  }
5399
5677
  function readLogState(logPath) {
5400
5678
  const state = /* @__PURE__ */ new Map();
5401
- if (!fs4__default.default.existsSync(logPath)) return state;
5402
- const text = fs4__default.default.readFileSync(logPath, "utf8");
5679
+ if (!fs5__default.default.existsSync(logPath)) return state;
5680
+ const text = fs5__default.default.readFileSync(logPath, "utf8");
5403
5681
  for (const line of text.split("\n")) {
5404
5682
  const trimmed = line.trim();
5405
5683
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -5415,7 +5693,7 @@ function readLogState(logPath) {
5415
5693
  return state;
5416
5694
  }
5417
5695
  function readTextManifest(manifestPath) {
5418
- const text = fs4__default.default.readFileSync(manifestPath, "utf8");
5696
+ const text = fs5__default.default.readFileSync(manifestPath, "utf8");
5419
5697
  const out = [];
5420
5698
  for (const raw of text.split("\n")) {
5421
5699
  const line = raw.replace(/\r$/, "").trim();
@@ -5487,8 +5765,8 @@ function writeCsvAtomic(filePath, header, rows) {
5487
5765
  lines.push(padded.map(csvField).join(","));
5488
5766
  }
5489
5767
  const tmp = filePath + ".tmp";
5490
- fs4__default.default.writeFileSync(tmp, lines.join("\n") + "\n");
5491
- fs4__default.default.renameSync(tmp, filePath);
5768
+ fs5__default.default.writeFileSync(tmp, lines.join("\n") + "\n");
5769
+ fs5__default.default.renameSync(tmp, filePath);
5492
5770
  }
5493
5771
  function findColumn(header, candidates) {
5494
5772
  const normalized = header.map((h) => h.trim().toLowerCase());
@@ -5499,7 +5777,7 @@ function findColumn(header, candidates) {
5499
5777
  return -1;
5500
5778
  }
5501
5779
  function loadCsvManifest(csvPath, rootDir) {
5502
- const text = fs4__default.default.readFileSync(csvPath, "utf8");
5780
+ const text = fs5__default.default.readFileSync(csvPath, "utf8");
5503
5781
  const all = parseCsv(text);
5504
5782
  if (all.length === 0) {
5505
5783
  error(`Empty CSV: ${csvPath}`);
@@ -5530,7 +5808,7 @@ function loadCsvManifest(csvPath, rootDir) {
5530
5808
  for (const row of rows) {
5531
5809
  while (row.length < header.length) row.push("");
5532
5810
  }
5533
- const root = rootDir ? path4__default.default.resolve(rootDir) : process.cwd();
5811
+ const root = rootDir ? path5__default.default.resolve(rootDir) : process.cwd();
5534
5812
  const paths = [];
5535
5813
  const pathToRow = /* @__PURE__ */ new Map();
5536
5814
  for (let i = 0; i < rows.length; i++) {
@@ -5538,8 +5816,8 @@ function loadCsvManifest(csvPath, rootDir) {
5538
5816
  const name = (row[nameCol] ?? "").trim();
5539
5817
  if (!name) continue;
5540
5818
  const folder = (row[folderCol] ?? "").trim();
5541
- const rel = folder ? path4__default.default.join(folder, name) : name;
5542
- const abs = path4__default.default.resolve(root, rel);
5819
+ const rel = folder ? path5__default.default.join(folder, name) : name;
5820
+ const abs = path5__default.default.resolve(root, rel);
5543
5821
  paths.push(abs);
5544
5822
  pathToRow.set(abs, i);
5545
5823
  }
@@ -5563,11 +5841,11 @@ async function runManifestMode(inputPaths, opts) {
5563
5841
  const rawPaths = [];
5564
5842
  let csv = null;
5565
5843
  if (opts.manifest) {
5566
- if (!fs4__default.default.existsSync(opts.manifest)) {
5844
+ if (!fs5__default.default.existsSync(opts.manifest)) {
5567
5845
  error(`Manifest not found: ${opts.manifest}`);
5568
5846
  process.exit(1);
5569
5847
  }
5570
- const ext = path4__default.default.extname(opts.manifest).toLowerCase();
5848
+ const ext = path5__default.default.extname(opts.manifest).toLowerCase();
5571
5849
  if (ext === ".csv" || ext === ".tsv") {
5572
5850
  csv = loadCsvManifest(opts.manifest, opts.root);
5573
5851
  rawPaths.push(...csv.paths);
@@ -5576,15 +5854,15 @@ async function runManifestMode(inputPaths, opts) {
5576
5854
  }
5577
5855
  }
5578
5856
  for (const p of inputPaths) {
5579
- if (!fs4__default.default.existsSync(p)) {
5857
+ if (!fs5__default.default.existsSync(p)) {
5580
5858
  error(`Path not found: ${p}`);
5581
5859
  process.exit(1);
5582
5860
  }
5583
- const stat = fs4__default.default.statSync(p);
5861
+ const stat = fs5__default.default.statSync(p);
5584
5862
  if (stat.isDirectory()) {
5585
5863
  rawPaths.push(...sdk.documentsNode.walkSupportedFiles(p));
5586
5864
  } else {
5587
- rawPaths.push(path4__default.default.resolve(p));
5865
+ rawPaths.push(path5__default.default.resolve(p));
5588
5866
  }
5589
5867
  }
5590
5868
  if (rawPaths.length === 0) {
@@ -5622,7 +5900,7 @@ async function runManifestMode(inputPaths, opts) {
5622
5900
  const humanOutput = !opts.json;
5623
5901
  if (humanOutput) {
5624
5902
  console.log(
5625
- `Manifest: ${rawPaths.length} file(s)` + (csv ? ` from ${path4__default.default.basename(csv.filePath)}` : "") + (resumedCount ? ` (${resumedCount} already done, skipping)` : "") + (limit !== null && limitedOut > 0 ? ` (limit=${limit}, ${limitedOut} deferred to next run)` : "")
5903
+ `Manifest: ${rawPaths.length} file(s)` + (csv ? ` from ${path5__default.default.basename(csv.filePath)}` : "") + (resumedCount ? ` (${resumedCount} already done, skipping)` : "") + (limit !== null && limitedOut > 0 ? ` (limit=${limit}, ${limitedOut} deferred to next run)` : "")
5626
5904
  );
5627
5905
  }
5628
5906
  if (opts.dryRun) {
@@ -5651,9 +5929,9 @@ async function runManifestMode(inputPaths, opts) {
5651
5929
  const auth = { baseUrl: config.baseUrl, accessToken };
5652
5930
  let logFd = null;
5653
5931
  if (opts.log) {
5654
- const dir = path4__default.default.dirname(path4__default.default.resolve(opts.log));
5655
- fs4__default.default.mkdirSync(dir, { recursive: true });
5656
- logFd = fs4__default.default.openSync(opts.log, "a");
5932
+ const dir = path5__default.default.dirname(path5__default.default.resolve(opts.log));
5933
+ fs5__default.default.mkdirSync(dir, { recursive: true });
5934
+ logFd = fs5__default.default.openSync(opts.log, "a");
5657
5935
  const header = JSON.stringify({
5658
5936
  ts: (/* @__PURE__ */ new Date()).toISOString(),
5659
5937
  event: "run_start",
@@ -5663,8 +5941,8 @@ async function runManifestMode(inputPaths, opts) {
5663
5941
  toUpload: pathsToUpload.length,
5664
5942
  resumed: resumedCount
5665
5943
  });
5666
- fs4__default.default.writeSync(logFd, header + "\n");
5667
- fs4__default.default.fsyncSync(logFd);
5944
+ fs5__default.default.writeSync(logFd, header + "\n");
5945
+ fs5__default.default.fsyncSync(logFd);
5668
5946
  }
5669
5947
  const uploadedDocs = /* @__PURE__ */ new Map();
5670
5948
  const runStart = Date.now();
@@ -5681,8 +5959,8 @@ async function runManifestMode(inputPaths, opts) {
5681
5959
  attempt: o.attempt,
5682
5960
  ...o.batchId ? { batchId: o.batchId } : {}
5683
5961
  };
5684
- fs4__default.default.writeSync(logFd, JSON.stringify(rec) + "\n");
5685
- fs4__default.default.fsyncSync(logFd);
5962
+ fs5__default.default.writeSync(logFd, JSON.stringify(rec) + "\n");
5963
+ fs5__default.default.fsyncSync(logFd);
5686
5964
  };
5687
5965
  const total = pathsToUpload.length;
5688
5966
  let done = 0;
@@ -5702,7 +5980,7 @@ async function runManifestMode(inputPaths, opts) {
5702
5980
  };
5703
5981
  const printInlineOutcome = (o) => {
5704
5982
  if (!humanOutput) return;
5705
- const name = path4__default.default.basename(o.path);
5983
+ const name = path5__default.default.basename(o.path);
5706
5984
  if (o.status === "rejected") {
5707
5985
  clearProgress();
5708
5986
  warn(` \u2717 ${name}: ${o.reason}`);
@@ -5734,7 +6012,7 @@ async function runManifestMode(inputPaths, opts) {
5734
6012
  switch (outcome.status) {
5735
6013
  case "uploaded":
5736
6014
  uploadedCount++;
5737
- if (outcome.docId) uploadedDocs.set(outcome.docId, path4__default.default.basename(outcome.path));
6015
+ if (outcome.docId) uploadedDocs.set(outcome.docId, path5__default.default.basename(outcome.path));
5738
6016
  break;
5739
6017
  case "duplicate":
5740
6018
  duplicateCount++;
@@ -5773,9 +6051,9 @@ async function runManifestMode(inputPaths, opts) {
5773
6051
  ...result.summary,
5774
6052
  elapsedMs: Date.now() - runStart
5775
6053
  });
5776
- fs4__default.default.writeSync(logFd, footer + "\n");
5777
- fs4__default.default.fsyncSync(logFd);
5778
- fs4__default.default.closeSync(logFd);
6054
+ fs5__default.default.writeSync(logFd, footer + "\n");
6055
+ fs5__default.default.fsyncSync(logFd);
6056
+ fs5__default.default.closeSync(logFd);
5779
6057
  }
5780
6058
  clearProgress();
5781
6059
  if (opts.json) {
@@ -5864,7 +6142,7 @@ Connection closed. ${pending.size} document(s) still processing.`);
5864
6142
  function registerDownloadCommand(program2) {
5865
6143
  program2.command("download [doc-id]").description("Download a document (interactive picker if no ID given)").option("-o, --output <path>", "Output file path").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
5866
6144
  (docId, opts) => runAction(async () => {
5867
- const { arbi, config, accessToken, workspaceId } = await resolveWorkspace(opts.workspace);
6145
+ const { arbi, config, accessToken } = await resolveWorkspace(opts.workspace);
5868
6146
  if (!docId) {
5869
6147
  const data = await sdk.documents.listDocuments(arbi);
5870
6148
  if (data.length === 0) {
@@ -5888,11 +6166,11 @@ function registerDownloadCommand(program2) {
5888
6166
  const match = disposition.match(/filename[*]?=(?:UTF-8''|"?)([^";]+)/i);
5889
6167
  if (match) filename = decodeURIComponent(match[1].replace(/"/g, ""));
5890
6168
  }
5891
- const outputPath = opts.output || path4__default.default.join(process.cwd(), filename);
6169
+ const outputPath = opts.output || path5__default.default.join(process.cwd(), filename);
5892
6170
  const buffer = Buffer.from(await res.arrayBuffer());
5893
- fs4__default.default.writeFileSync(outputPath, buffer);
6171
+ fs5__default.default.writeFileSync(outputPath, buffer);
5894
6172
  success(
5895
- `Downloaded: ${path4__default.default.basename(outputPath)} (${(buffer.length / (1024 * 1024)).toFixed(1)} MB)`
6173
+ `Downloaded: ${path5__default.default.basename(outputPath)} (${(buffer.length / (1024 * 1024)).toFixed(1)} MB)`
5896
6174
  );
5897
6175
  })()
5898
6176
  );
@@ -6557,7 +6835,7 @@ function registerDmCommand(program2) {
6557
6835
  await dm.commands.find((c) => c.name() === "list").parseAsync([], { from: "user" });
6558
6836
  });
6559
6837
  }
6560
- async function fetchTagChoices(arbi, workspaceId) {
6838
+ async function fetchTagChoices(arbi) {
6561
6839
  const data = await sdk.tags.listTags(arbi);
6562
6840
  if (data.length === 0) {
6563
6841
  console.log("No tags found.");
@@ -6576,7 +6854,7 @@ function registerTagsCommand(program2) {
6576
6854
  const tags = program2.command("tags").description("Manage tags");
6577
6855
  tags.command("list").description("List tags in the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
6578
6856
  (opts) => runAction(async () => {
6579
- const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
6857
+ const { arbi } = await resolveWorkspace(opts.workspace);
6580
6858
  const data = await sdk.tags.listTags(arbi);
6581
6859
  if (data.length === 0) {
6582
6860
  console.log("No tags found.");
@@ -6604,7 +6882,7 @@ function registerTagsCommand(program2) {
6604
6882
  "checkbox"
6605
6883
  ).option("-i, --instruction <text>", "Tag instruction").option("--shared", "Make tag shared", false).action(
6606
6884
  (name, opts) => runAction(async () => {
6607
- const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
6885
+ const { arbi } = await resolveWorkspace(opts.workspace);
6608
6886
  const interactive = !name;
6609
6887
  if (!name) {
6610
6888
  name = await promptInput("Tag name");
@@ -6635,9 +6913,9 @@ function registerTagsCommand(program2) {
6635
6913
  );
6636
6914
  tags.command("delete [id]").description("Delete a tag (interactive picker if no ID given)").action(
6637
6915
  (id) => runAction(async () => {
6638
- const { arbi, workspaceId } = await resolveWorkspace();
6916
+ const { arbi } = await resolveWorkspace();
6639
6917
  if (!id) {
6640
- const { choices } = await fetchTagChoices(arbi, workspaceId);
6918
+ const { choices } = await fetchTagChoices(arbi);
6641
6919
  id = await promptSelect("Select tag to delete", choices);
6642
6920
  }
6643
6921
  const data = await sdk.tags.deleteTag(arbi, id);
@@ -6646,9 +6924,9 @@ function registerTagsCommand(program2) {
6646
6924
  );
6647
6925
  tags.command("update [id] [json]").description("Update a tag (interactive picker + form if no args)").action(
6648
6926
  (id, json) => runAction(async () => {
6649
- const { arbi, workspaceId } = await resolveWorkspace();
6927
+ const { arbi } = await resolveWorkspace();
6650
6928
  if (!id) {
6651
- const { choices } = await fetchTagChoices(arbi, workspaceId);
6929
+ const { choices } = await fetchTagChoices(arbi);
6652
6930
  id = await promptSelect("Select tag to update", choices);
6653
6931
  }
6654
6932
  let body;
@@ -6781,7 +7059,7 @@ function registerConversationsCommand(program2) {
6781
7059
  const conv = program2.command("conversations").description("Manage conversations");
6782
7060
  conv.command("list").description("List conversations in the active workspace").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").action(
6783
7061
  (opts) => runAction(async () => {
6784
- const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
7062
+ const { arbi } = await resolveWorkspace(opts.workspace);
6785
7063
  const data = await sdk.conversations.listConversations(arbi);
6786
7064
  if (data.length === 0) {
6787
7065
  console.log("No conversations found.");
@@ -7683,15 +7961,15 @@ compdef _arbi_completions arbi
7683
7961
  ${MARKER_END}`;
7684
7962
  function getShellRcPath2() {
7685
7963
  const shell = process.env.SHELL || "";
7686
- if (shell.includes("zsh")) return path4.join(os.homedir(), ".zshrc");
7687
- return path4.join(os.homedir(), ".bashrc");
7964
+ if (shell.includes("zsh")) return path5.join(os.homedir(), ".zshrc");
7965
+ return path5.join(os.homedir(), ".bashrc");
7688
7966
  }
7689
7967
  function isZsh() {
7690
7968
  return (process.env.SHELL || "").includes("zsh");
7691
7969
  }
7692
7970
  function isCompletionInstalled(rcPath) {
7693
- if (!fs4.existsSync(rcPath)) return false;
7694
- const content = fs4.readFileSync(rcPath, "utf-8");
7971
+ if (!fs5.existsSync(rcPath)) return false;
7972
+ const content = fs5.readFileSync(rcPath, "utf-8");
7695
7973
  return content.includes(MARKER_START);
7696
7974
  }
7697
7975
  function removeCompletionBlock(content) {
@@ -7712,7 +7990,7 @@ function registerCompletionCommand(program2) {
7712
7990
  return;
7713
7991
  }
7714
7992
  const snippet = isZsh() ? ZSH_COMPLETION : BASH_COMPLETION;
7715
- fs4.appendFileSync(rcPath, snippet + "\n");
7993
+ fs5.appendFileSync(rcPath, snippet + "\n");
7716
7994
  success(`Installed tab completion in ${rcPath}`);
7717
7995
  dim("");
7718
7996
  dim(`Run: source ${rcPath}`);
@@ -7724,9 +8002,9 @@ function registerCompletionCommand(program2) {
7724
8002
  dim("Completion is not installed.");
7725
8003
  return;
7726
8004
  }
7727
- const content = fs4.readFileSync(rcPath, "utf-8");
8005
+ const content = fs5.readFileSync(rcPath, "utf-8");
7728
8006
  const cleaned = removeCompletionBlock(content);
7729
- fs4.writeFileSync(rcPath, cleaned);
8007
+ fs5.writeFileSync(rcPath, cleaned);
7730
8008
  success(`Removed tab completion from ${rcPath}`);
7731
8009
  dim(`Run: source ${rcPath}`);
7732
8010
  });
@@ -7742,7 +8020,7 @@ function registerCompletionCommand(program2) {
7742
8020
  function resolvePath(p) {
7743
8021
  const raw = p ?? ".";
7744
8022
  const expanded = raw.startsWith("~") ? raw.replace("~", os.homedir()) : raw;
7745
- return path4.resolve(expanded);
8023
+ return path5.resolve(expanded);
7746
8024
  }
7747
8025
  function formatSize2(bytes) {
7748
8026
  if (bytes < 1024) return `${bytes}B`;
@@ -7752,11 +8030,11 @@ function formatSize2(bytes) {
7752
8030
  }
7753
8031
  function registerLocalCommand(program2) {
7754
8032
  const local = program2.command("local").description("Local filesystem operations");
7755
- local.command("ls [path]").description("List files in a directory").option("-l, --long", "Show file sizes and types").action((path6, opts) => {
7756
- const dir = resolvePath(path6);
8033
+ local.command("ls [path]").description("List files in a directory").option("-l, --long", "Show file sizes and types").action((path7, opts) => {
8034
+ const dir = resolvePath(path7);
7757
8035
  let entries;
7758
8036
  try {
7759
- entries = fs4.readdirSync(dir);
8037
+ entries = fs5.readdirSync(dir);
7760
8038
  } catch {
7761
8039
  console.error(`Cannot read directory: ${dir}`);
7762
8040
  process.exit(1);
@@ -7764,7 +8042,7 @@ function registerLocalCommand(program2) {
7764
8042
  for (const entry of entries.filter((e) => !e.startsWith(".")).sort()) {
7765
8043
  if (opts?.long) {
7766
8044
  try {
7767
- const stat = fs4.statSync(path4.join(dir, entry));
8045
+ const stat = fs5.statSync(path5.join(dir, entry));
7768
8046
  const type = stat.isDirectory() ? "dir" : "file";
7769
8047
  const size = stat.isFile() ? formatSize2(stat.size) : "-";
7770
8048
  console.log(`${type.padEnd(5)} ${size.padStart(10)} ${entry}`);
@@ -7778,7 +8056,7 @@ function registerLocalCommand(program2) {
7778
8056
  });
7779
8057
  local.command("find <pattern>").description('Find files matching a glob (e.g. "**/*.pdf")').option("-d, --dir <path>", "Directory to search in", ".").action((pattern, opts) => {
7780
8058
  const dir = resolvePath(opts.dir);
7781
- const results = fs4.globSync(pattern, { cwd: dir });
8059
+ const results = fs5.globSync(pattern, { cwd: dir });
7782
8060
  if (results.length === 0) {
7783
8061
  console.log(`No files matching "${pattern}" in ${dir}`);
7784
8062
  return;
@@ -7791,7 +8069,7 @@ function registerLocalCommand(program2) {
7791
8069
  const filePath = resolvePath(file);
7792
8070
  let content;
7793
8071
  try {
7794
- content = fs4.readFileSync(filePath, "utf-8");
8072
+ content = fs5.readFileSync(filePath, "utf-8");
7795
8073
  } catch {
7796
8074
  console.error(`Cannot read file: ${filePath}`);
7797
8075
  process.exit(1);
@@ -7803,10 +8081,10 @@ function registerLocalCommand(program2) {
7803
8081
  console.log(content);
7804
8082
  }
7805
8083
  });
7806
- local.command("tree [path]").description("Show directory tree").option("-d, --depth <n>", "Maximum depth", "3").action((path6, opts) => {
7807
- const dir = resolvePath(path6);
8084
+ local.command("tree [path]").description("Show directory tree").option("-d, --depth <n>", "Maximum depth", "3").action((path7, opts) => {
8085
+ const dir = resolvePath(path7);
7808
8086
  const maxDepth = parseInt(opts?.depth ?? "3", 10);
7809
- console.log(path4.basename(dir) + "/");
8087
+ console.log(path5.basename(dir) + "/");
7810
8088
  printTree(dir, "", maxDepth, 0);
7811
8089
  });
7812
8090
  }
@@ -7814,7 +8092,7 @@ function printTree(dir, prefix, maxDepth, depth) {
7814
8092
  if (depth >= maxDepth) return;
7815
8093
  let entries;
7816
8094
  try {
7817
- entries = fs4.readdirSync(dir).filter((e) => !e.startsWith(".")).sort();
8095
+ entries = fs5.readdirSync(dir).filter((e) => !e.startsWith(".")).sort();
7818
8096
  } catch {
7819
8097
  return;
7820
8098
  }
@@ -7822,10 +8100,10 @@ function printTree(dir, prefix, maxDepth, depth) {
7822
8100
  const entry = entries[i];
7823
8101
  const isLast = i === entries.length - 1;
7824
8102
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
7825
- const full = path4.join(dir, entry);
8103
+ const full = path5.join(dir, entry);
7826
8104
  let isDir = false;
7827
8105
  try {
7828
- isDir = fs4.statSync(full).isDirectory();
8106
+ isDir = fs5.statSync(full).isDirectory();
7829
8107
  } catch {
7830
8108
  continue;
7831
8109
  }
@@ -7880,7 +8158,7 @@ console.info = (...args) => {
7880
8158
  _origInfo(...args);
7881
8159
  };
7882
8160
  var program = new commander.Command();
7883
- program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.33");
8161
+ program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.34");
7884
8162
  registerConfigCommand(program);
7885
8163
  registerLoginCommand(program);
7886
8164
  registerRegisterCommand(program);