@arbidocs/cli 0.4.49 → 0.4.51
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 +21 -0
- package/SKILL.md +2 -1
- package/dist/index.js +244 -150
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
var prompts = require('@inquirer/prompts');
|
|
5
5
|
var commander = require('commander');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
6
|
+
var fs7 = require('fs');
|
|
7
|
+
var path6 = require('path');
|
|
8
8
|
var os2 = require('os');
|
|
9
9
|
var chalk2 = require('chalk');
|
|
10
10
|
var sdk = require('@arbidocs/sdk');
|
|
@@ -17,8 +17,8 @@ var module$1 = require('module');
|
|
|
17
17
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
18
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
19
|
|
|
20
|
-
var
|
|
21
|
-
var
|
|
20
|
+
var fs7__default = /*#__PURE__*/_interopDefault(fs7);
|
|
21
|
+
var path6__default = /*#__PURE__*/_interopDefault(path6);
|
|
22
22
|
var os2__default = /*#__PURE__*/_interopDefault(os2);
|
|
23
23
|
var chalk2__default = /*#__PURE__*/_interopDefault(chalk2);
|
|
24
24
|
|
|
@@ -85,18 +85,18 @@ var init_prompts = __esm({
|
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
87
|
function getCacheFile() {
|
|
88
|
-
const configDir = process.env.ARBI_CONFIG_DIR ??
|
|
89
|
-
return
|
|
88
|
+
const configDir = process.env.ARBI_CONFIG_DIR ?? path6__default.default.join(os2__default.default.homedir(), ".arbi");
|
|
89
|
+
return path6__default.default.join(configDir, "completions.json");
|
|
90
90
|
}
|
|
91
91
|
function ensureDir(filePath) {
|
|
92
|
-
const dir =
|
|
93
|
-
if (!
|
|
94
|
-
|
|
92
|
+
const dir = path6__default.default.dirname(filePath);
|
|
93
|
+
if (!fs7__default.default.existsSync(dir)) {
|
|
94
|
+
fs7__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
function getCachedWorkspaceIds() {
|
|
98
98
|
try {
|
|
99
|
-
const content =
|
|
99
|
+
const content = fs7__default.default.readFileSync(getCacheFile(), "utf-8");
|
|
100
100
|
const cache = JSON.parse(content);
|
|
101
101
|
return cache.workspaces.map((w) => w.id);
|
|
102
102
|
} catch {
|
|
@@ -105,7 +105,7 @@ function getCachedWorkspaceIds() {
|
|
|
105
105
|
}
|
|
106
106
|
function getCachedWorkspaceName(id) {
|
|
107
107
|
try {
|
|
108
|
-
const content =
|
|
108
|
+
const content = fs7__default.default.readFileSync(getCacheFile(), "utf-8");
|
|
109
109
|
const cache = JSON.parse(content);
|
|
110
110
|
const hit = cache.workspaces.find((w) => w.id === id);
|
|
111
111
|
return hit?.name?.trim() ? hit.name : null;
|
|
@@ -120,7 +120,7 @@ function updateCompletionCache(workspaces4) {
|
|
|
120
120
|
};
|
|
121
121
|
const filePath = getCacheFile();
|
|
122
122
|
ensureDir(filePath);
|
|
123
|
-
|
|
123
|
+
fs7__default.default.writeFileSync(filePath, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// src/completion.ts
|
|
@@ -267,12 +267,12 @@ var ALIAS_LINE = 'alias A="arbi ask"';
|
|
|
267
267
|
var ALIAS_MARKER = "# arbi-cli alias";
|
|
268
268
|
function getShellRcPath() {
|
|
269
269
|
const shell = process.env.SHELL || "";
|
|
270
|
-
if (shell.includes("zsh")) return
|
|
271
|
-
return
|
|
270
|
+
if (shell.includes("zsh")) return path6.join(os2.homedir(), ".zshrc");
|
|
271
|
+
return path6.join(os2.homedir(), ".bashrc");
|
|
272
272
|
}
|
|
273
273
|
function isAliasInstalled(rcPath) {
|
|
274
|
-
if (!
|
|
275
|
-
const content =
|
|
274
|
+
if (!fs7.existsSync(rcPath)) return false;
|
|
275
|
+
const content = fs7.readFileSync(rcPath, "utf-8");
|
|
276
276
|
return content.includes(ALIAS_LINE) || content.includes(ALIAS_MARKER);
|
|
277
277
|
}
|
|
278
278
|
function registerConfigCommand(program2) {
|
|
@@ -366,7 +366,7 @@ function registerConfigCommand(program2) {
|
|
|
366
366
|
dim("Usage: A what is the meaning of life");
|
|
367
367
|
return;
|
|
368
368
|
}
|
|
369
|
-
|
|
369
|
+
fs7.appendFileSync(rcPath, `
|
|
370
370
|
${ALIAS_MARKER}
|
|
371
371
|
${ALIAS_LINE}
|
|
372
372
|
`);
|
|
@@ -3657,11 +3657,11 @@ Object.defineProperties(globalVar, {
|
|
|
3657
3657
|
IDBVersionChangeEvent: createPropertyDescriptor(FDBVersionChangeEvent_default)
|
|
3658
3658
|
});
|
|
3659
3659
|
init_prompts();
|
|
3660
|
-
var CACHE_FILE =
|
|
3660
|
+
var CACHE_FILE = path6__default.default.join(os2__default.default.homedir(), ".arbi", "version-cache.json");
|
|
3661
3661
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
3662
3662
|
function readCache() {
|
|
3663
3663
|
try {
|
|
3664
|
-
const data = JSON.parse(
|
|
3664
|
+
const data = JSON.parse(fs7__default.default.readFileSync(CACHE_FILE, "utf8"));
|
|
3665
3665
|
if (data.latest && data.checkedAt && Date.now() - data.checkedAt < CACHE_TTL_MS) {
|
|
3666
3666
|
return data;
|
|
3667
3667
|
}
|
|
@@ -3671,9 +3671,9 @@ function readCache() {
|
|
|
3671
3671
|
}
|
|
3672
3672
|
function writeCache(latest) {
|
|
3673
3673
|
try {
|
|
3674
|
-
const dir =
|
|
3675
|
-
if (!
|
|
3676
|
-
|
|
3674
|
+
const dir = path6__default.default.dirname(CACHE_FILE);
|
|
3675
|
+
if (!fs7__default.default.existsSync(dir)) fs7__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3676
|
+
fs7__default.default.writeFileSync(CACHE_FILE, JSON.stringify({ latest, checkedAt: Date.now() }) + "\n");
|
|
3677
3677
|
} catch {
|
|
3678
3678
|
}
|
|
3679
3679
|
}
|
|
@@ -3694,13 +3694,13 @@ function getLatestVersion(skipCache = false) {
|
|
|
3694
3694
|
}
|
|
3695
3695
|
}
|
|
3696
3696
|
function getCurrentVersion() {
|
|
3697
|
-
return "0.4.
|
|
3697
|
+
return "0.4.51";
|
|
3698
3698
|
}
|
|
3699
3699
|
function readChangelog(fromVersion, toVersion) {
|
|
3700
3700
|
try {
|
|
3701
3701
|
const globalRoot = child_process.execSync("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
3702
|
-
const changelogPath =
|
|
3703
|
-
const text =
|
|
3702
|
+
const changelogPath = path6__default.default.join(globalRoot, "@arbidocs", "cli", "CHANGELOG.md");
|
|
3703
|
+
const text = fs7__default.default.readFileSync(changelogPath, "utf8");
|
|
3704
3704
|
return extractSections(text, fromVersion, toVersion);
|
|
3705
3705
|
} catch {
|
|
3706
3706
|
return null;
|
|
@@ -3747,30 +3747,30 @@ function showChangelog(fromVersion, toVersion) {
|
|
|
3747
3747
|
async function checkForUpdates(autoUpdate) {
|
|
3748
3748
|
try {
|
|
3749
3749
|
const latest = getLatestVersion();
|
|
3750
|
-
if (!latest || latest === "0.4.
|
|
3750
|
+
if (!latest || latest === "0.4.51") return;
|
|
3751
3751
|
if (autoUpdate) {
|
|
3752
3752
|
warn(`
|
|
3753
|
-
Your arbi version is out of date (${"0.4.
|
|
3753
|
+
Your arbi version is out of date (${"0.4.51"} \u2192 ${latest}). Updating...`);
|
|
3754
3754
|
child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
|
|
3755
|
-
showChangelog("0.4.
|
|
3755
|
+
showChangelog("0.4.51", latest);
|
|
3756
3756
|
console.log(`Updated to ${latest}.`);
|
|
3757
3757
|
} else {
|
|
3758
3758
|
warn(
|
|
3759
3759
|
`
|
|
3760
|
-
Your arbi version is out of date (${"0.4.
|
|
3760
|
+
Your arbi version is out of date (${"0.4.51"} \u2192 ${latest}).
|
|
3761
3761
|
Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
3762
3762
|
);
|
|
3763
3763
|
}
|
|
3764
3764
|
} catch {
|
|
3765
3765
|
}
|
|
3766
3766
|
}
|
|
3767
|
-
var NAG_FILE =
|
|
3767
|
+
var NAG_FILE = path6__default.default.join(os2__default.default.homedir(), ".arbi", "last-update-hint.json");
|
|
3768
3768
|
var NAG_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
3769
3769
|
function shouldShowNag(latest) {
|
|
3770
3770
|
if (process.env.ARBI_JSON === "1") return false;
|
|
3771
3771
|
if (process.argv.includes("--json")) return false;
|
|
3772
3772
|
try {
|
|
3773
|
-
const data = JSON.parse(
|
|
3773
|
+
const data = JSON.parse(fs7__default.default.readFileSync(NAG_FILE, "utf8"));
|
|
3774
3774
|
if (data.latest === latest && typeof data.shownAt === "number" && Date.now() - data.shownAt < NAG_INTERVAL_MS) {
|
|
3775
3775
|
return false;
|
|
3776
3776
|
}
|
|
@@ -3780,19 +3780,19 @@ function shouldShowNag(latest) {
|
|
|
3780
3780
|
}
|
|
3781
3781
|
function markNagShown(latest) {
|
|
3782
3782
|
try {
|
|
3783
|
-
const dir =
|
|
3784
|
-
if (!
|
|
3785
|
-
|
|
3783
|
+
const dir = path6__default.default.dirname(NAG_FILE);
|
|
3784
|
+
if (!fs7__default.default.existsSync(dir)) fs7__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3785
|
+
fs7__default.default.writeFileSync(NAG_FILE, JSON.stringify({ latest, shownAt: Date.now() }) + "\n");
|
|
3786
3786
|
} catch {
|
|
3787
3787
|
}
|
|
3788
3788
|
}
|
|
3789
3789
|
function hintUpdateOnError() {
|
|
3790
3790
|
try {
|
|
3791
3791
|
const cached = readCache();
|
|
3792
|
-
if (!cached || cached.latest === "0.4.
|
|
3792
|
+
if (!cached || cached.latest === "0.4.51") return;
|
|
3793
3793
|
if (!shouldShowNag(cached.latest)) return;
|
|
3794
3794
|
warn(
|
|
3795
|
-
`Your arbi version is out of date (${"0.4.
|
|
3795
|
+
`Your arbi version is out of date (${"0.4.51"} \u2192 ${cached.latest}). Run "arbi update".`
|
|
3796
3796
|
);
|
|
3797
3797
|
markNagShown(cached.latest);
|
|
3798
3798
|
} catch {
|
|
@@ -3801,18 +3801,18 @@ function hintUpdateOnError() {
|
|
|
3801
3801
|
var MAX_TASKS = 50;
|
|
3802
3802
|
var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
3803
3803
|
function getTasksFile() {
|
|
3804
|
-
const configDir = process.env.ARBI_CONFIG_DIR ??
|
|
3805
|
-
return
|
|
3804
|
+
const configDir = process.env.ARBI_CONFIG_DIR ?? path6__default.default.join(os2__default.default.homedir(), ".arbi");
|
|
3805
|
+
return path6__default.default.join(configDir, "tasks.json");
|
|
3806
3806
|
}
|
|
3807
3807
|
function ensureDir2(filePath) {
|
|
3808
|
-
const dir =
|
|
3809
|
-
if (!
|
|
3810
|
-
|
|
3808
|
+
const dir = path6__default.default.dirname(filePath);
|
|
3809
|
+
if (!fs7__default.default.existsSync(dir)) {
|
|
3810
|
+
fs7__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3811
3811
|
}
|
|
3812
3812
|
}
|
|
3813
3813
|
function readTasks() {
|
|
3814
3814
|
try {
|
|
3815
|
-
const content =
|
|
3815
|
+
const content = fs7__default.default.readFileSync(getTasksFile(), "utf-8");
|
|
3816
3816
|
return JSON.parse(content);
|
|
3817
3817
|
} catch {
|
|
3818
3818
|
return [];
|
|
@@ -3821,7 +3821,7 @@ function readTasks() {
|
|
|
3821
3821
|
function writeTasks(tasks) {
|
|
3822
3822
|
const filePath = getTasksFile();
|
|
3823
3823
|
ensureDir2(filePath);
|
|
3824
|
-
|
|
3824
|
+
fs7__default.default.writeFileSync(filePath, JSON.stringify(tasks, null, 2) + "\n", { mode: 384 });
|
|
3825
3825
|
}
|
|
3826
3826
|
function getTasks() {
|
|
3827
3827
|
const now = Date.now();
|
|
@@ -4178,39 +4178,39 @@ function checkAgentDependency(backend) {
|
|
|
4178
4178
|
dim(`${binary} ${match?.[1] ?? version} \u2713`);
|
|
4179
4179
|
}
|
|
4180
4180
|
function loadSkillContent() {
|
|
4181
|
-
const cliRoot =
|
|
4181
|
+
const cliRoot = path6.resolve(path6.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)))), "..");
|
|
4182
4182
|
try {
|
|
4183
|
-
return
|
|
4183
|
+
return fs7.readFileSync(path6.join(cliRoot, "SKILL.md"), "utf-8");
|
|
4184
4184
|
} catch {
|
|
4185
4185
|
return void 0;
|
|
4186
4186
|
}
|
|
4187
4187
|
}
|
|
4188
4188
|
function installSkill(backend) {
|
|
4189
|
-
const cliRoot =
|
|
4189
|
+
const cliRoot = path6.resolve(path6.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)))), "..");
|
|
4190
4190
|
let skillContent;
|
|
4191
4191
|
try {
|
|
4192
|
-
skillContent =
|
|
4192
|
+
skillContent = fs7.readFileSync(path6.join(cliRoot, "SKILL.md"), "utf-8");
|
|
4193
4193
|
} catch {
|
|
4194
4194
|
return;
|
|
4195
4195
|
}
|
|
4196
4196
|
if (backend === "claude") {
|
|
4197
|
-
const dir =
|
|
4198
|
-
const target =
|
|
4197
|
+
const dir = path6.join(os2.homedir(), ".claude", "commands", "arbi");
|
|
4198
|
+
const target = path6.join(dir, "SKILL.md");
|
|
4199
4199
|
try {
|
|
4200
|
-
|
|
4201
|
-
if (!
|
|
4202
|
-
|
|
4200
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
4201
|
+
if (!fs7.existsSync(target) || fs7.readFileSync(target, "utf-8") !== skillContent) {
|
|
4202
|
+
fs7.writeFileSync(target, skillContent, "utf-8");
|
|
4203
4203
|
dim(`Installed ARBI skill \u2192 ${target}`);
|
|
4204
4204
|
}
|
|
4205
4205
|
} catch {
|
|
4206
4206
|
}
|
|
4207
4207
|
} else if (backend === "openclaw") {
|
|
4208
|
-
const workspace =
|
|
4209
|
-
const bootstrap =
|
|
4208
|
+
const workspace = path6.join(os2.homedir(), ".arbi", "openclaw-workspace");
|
|
4209
|
+
const bootstrap = path6.join(workspace, "BOOTSTRAP.md");
|
|
4210
4210
|
try {
|
|
4211
|
-
|
|
4212
|
-
if (!
|
|
4213
|
-
|
|
4211
|
+
fs7.mkdirSync(workspace, { recursive: true });
|
|
4212
|
+
if (!fs7.existsSync(bootstrap) || fs7.readFileSync(bootstrap, "utf-8") !== skillContent) {
|
|
4213
|
+
fs7.writeFileSync(bootstrap, skillContent, "utf-8");
|
|
4214
4214
|
dim(`Installed ARBI skill \u2192 ${bootstrap}`);
|
|
4215
4215
|
}
|
|
4216
4216
|
} catch {
|
|
@@ -4850,6 +4850,53 @@ function registerStatusCommand(program2) {
|
|
|
4850
4850
|
});
|
|
4851
4851
|
}
|
|
4852
4852
|
init_prompts();
|
|
4853
|
+
var IMAGE_TYPES = {
|
|
4854
|
+
".png": "image/png",
|
|
4855
|
+
".jpg": "image/jpeg",
|
|
4856
|
+
".jpeg": "image/jpeg",
|
|
4857
|
+
".gif": "image/gif",
|
|
4858
|
+
".webp": "image/webp"
|
|
4859
|
+
};
|
|
4860
|
+
function typeFromName(name) {
|
|
4861
|
+
return IMAGE_TYPES[path6__default.default.extname(name).toLowerCase()] ?? sdk.documents.mimeFromName(name) ?? "application/octet-stream";
|
|
4862
|
+
}
|
|
4863
|
+
function collectPaths(value, previous) {
|
|
4864
|
+
return [...previous ?? [], value];
|
|
4865
|
+
}
|
|
4866
|
+
function readAttachmentFiles(paths) {
|
|
4867
|
+
const stats = paths.map((p) => {
|
|
4868
|
+
const resolved = path6__default.default.resolve(p);
|
|
4869
|
+
if (!fs7__default.default.existsSync(resolved) || !fs7__default.default.statSync(resolved).isFile()) {
|
|
4870
|
+
throw new Error(`File not found: ${p}`);
|
|
4871
|
+
}
|
|
4872
|
+
return { resolved, name: path6__default.default.basename(resolved), size: fs7__default.default.statSync(resolved).size };
|
|
4873
|
+
});
|
|
4874
|
+
sdk.dm.checkDmAttachmentLimits(stats);
|
|
4875
|
+
return stats.map(({ resolved, name }) => ({
|
|
4876
|
+
name,
|
|
4877
|
+
type: typeFromName(name),
|
|
4878
|
+
bytes: new Uint8Array(fs7__default.default.readFileSync(resolved))
|
|
4879
|
+
}));
|
|
4880
|
+
}
|
|
4881
|
+
function findAttachment(row, attachmentId) {
|
|
4882
|
+
const found = row.attachmentFiles?.find((f) => f.id === attachmentId);
|
|
4883
|
+
if (!found) throw new Error(`No attachment ${attachmentId} on message ${String(row.external_id)}`);
|
|
4884
|
+
return found;
|
|
4885
|
+
}
|
|
4886
|
+
function attachmentOutputPath(file, output) {
|
|
4887
|
+
if (output) return output;
|
|
4888
|
+
const base = path6__default.default.basename(file.name);
|
|
4889
|
+
return base && base !== "." && base !== ".." ? base : file.id;
|
|
4890
|
+
}
|
|
4891
|
+
function publicAttachmentFiles(files) {
|
|
4892
|
+
return (files ?? []).map(({ id, name, type, size }) => ({ id, name, type, size }));
|
|
4893
|
+
}
|
|
4894
|
+
function attachmentLabel(files) {
|
|
4895
|
+
const n = files?.length ?? 0;
|
|
4896
|
+
return n ? `[${n} file${n === 1 ? "" : "s"}] ` : "";
|
|
4897
|
+
}
|
|
4898
|
+
|
|
4899
|
+
// src/commands/dm.ts
|
|
4853
4900
|
async function resolveRecipient(arbi, ref2) {
|
|
4854
4901
|
return sdk.dm.resolveRecipient(arbi, ref2);
|
|
4855
4902
|
}
|
|
@@ -4899,7 +4946,17 @@ function registerDmCommand(program2) {
|
|
|
4899
4946
|
const filtered = dms.filter((r) => rowMatchesFilters(r, filterOpts));
|
|
4900
4947
|
const limited = typeof opts.limit === "number" && opts.limit > 0 ? filtered.slice(0, opts.limit) : filtered;
|
|
4901
4948
|
if (opts.json) {
|
|
4902
|
-
printJson(
|
|
4949
|
+
printJson(
|
|
4950
|
+
limited.map(({ attachmentFiles, ...r }) => ({
|
|
4951
|
+
...r,
|
|
4952
|
+
...attachmentFiles ? {
|
|
4953
|
+
attachment_files: publicAttachmentFiles(
|
|
4954
|
+
attachmentFiles
|
|
4955
|
+
)
|
|
4956
|
+
} : {},
|
|
4957
|
+
encrypted_in_transit: true
|
|
4958
|
+
}))
|
|
4959
|
+
);
|
|
4903
4960
|
return;
|
|
4904
4961
|
}
|
|
4905
4962
|
if (limited.length === 0) {
|
|
@@ -4931,15 +4988,23 @@ function registerDmCommand(program2) {
|
|
|
4931
4988
|
{
|
|
4932
4989
|
header: "CONTENT",
|
|
4933
4990
|
width: 50,
|
|
4934
|
-
value: (r) => truncate(
|
|
4991
|
+
value: (r) => truncate(
|
|
4992
|
+
attachmentLabel(r.attachmentFiles) + (r.content ?? ""),
|
|
4993
|
+
49
|
|
4994
|
+
)
|
|
4935
4995
|
}
|
|
4936
4996
|
],
|
|
4937
4997
|
limited
|
|
4938
4998
|
);
|
|
4939
4999
|
})()
|
|
4940
5000
|
);
|
|
4941
|
-
dm.command("send [recipient] [content...]").description("Send an E2E encrypted DM (interactive if no args)").
|
|
4942
|
-
|
|
5001
|
+
dm.command("send [recipient] [content...]").description("Send an E2E encrypted DM (interactive if no args)").option(
|
|
5002
|
+
"-a, --attach <path>",
|
|
5003
|
+
"Attach a file, encrypted end to end (repeatable; up to 10 files of 15 MB each)",
|
|
5004
|
+
collectPaths
|
|
5005
|
+
).action(
|
|
5006
|
+
(recipient, contentParts, opts) => runAction(async () => {
|
|
5007
|
+
const attachmentInputs = readAttachmentFiles(opts?.attach ?? []);
|
|
4943
5008
|
const { arbi, crypto } = await resolveDmCrypto();
|
|
4944
5009
|
if (!recipient) {
|
|
4945
5010
|
requireInteractive(
|
|
@@ -4964,7 +5029,8 @@ function registerDmCommand(program2) {
|
|
|
4964
5029
|
);
|
|
4965
5030
|
}
|
|
4966
5031
|
let content = contentParts?.length ? contentParts.join(" ") : void 0;
|
|
4967
|
-
if (!content)
|
|
5032
|
+
if (!content && attachmentInputs.length) content = "";
|
|
5033
|
+
if (content === void 0) {
|
|
4968
5034
|
requireInteractive(
|
|
4969
5035
|
'Pass the message as a positional argument: arbi dm send <email> "your message"'
|
|
4970
5036
|
);
|
|
@@ -4986,6 +5052,7 @@ Try: arbi contacts add ${recipient.includes("@") ? recipient : "<their-email>"}`
|
|
|
4986
5052
|
);
|
|
4987
5053
|
process.exit(3);
|
|
4988
5054
|
}
|
|
5055
|
+
const attachments = await sdk.dm.uploadDmAttachments(arbi, attachmentInputs);
|
|
4989
5056
|
const data = await sdk.dm.sendEncryptedDM(
|
|
4990
5057
|
arbi,
|
|
4991
5058
|
[
|
|
@@ -4995,17 +5062,44 @@ Try: arbi contacts add ${recipient.includes("@") ? recipient : "<their-email>"}`
|
|
|
4995
5062
|
recipient_encryption_public_key: recipientPubKey
|
|
4996
5063
|
}
|
|
4997
5064
|
],
|
|
4998
|
-
crypto
|
|
5065
|
+
crypto,
|
|
5066
|
+
{ attachments }
|
|
4999
5067
|
);
|
|
5000
5068
|
for (const n of data) {
|
|
5001
5069
|
success(`Sent (encrypted): ${n.external_id} \u2192 ${n.recipient.email}`);
|
|
5002
5070
|
}
|
|
5071
|
+
for (const f of attachments) {
|
|
5072
|
+
success(`Attached (encrypted): ${f.id} ${f.name} (${f.size} bytes)`);
|
|
5073
|
+
}
|
|
5003
5074
|
})()
|
|
5004
5075
|
);
|
|
5005
|
-
dm.command("read [ids...]").description(
|
|
5076
|
+
dm.command("read [ids...]").description(
|
|
5077
|
+
"Mark messages as read (interactive picker if no IDs given), or save an attachment with --attachment"
|
|
5078
|
+
).option("--all", "Mark every unread message as read (no picker)").option(
|
|
5079
|
+
"--attachment <att-id>",
|
|
5080
|
+
"Save this attachment of the message (ids from `arbi dm list --json`) instead"
|
|
5081
|
+
).option("-o, --output <path>", "Where to save the attachment (default: its file name)").action(
|
|
5006
5082
|
(ids, opts) => runAction(async () => {
|
|
5007
5083
|
const { arbi, crypto } = await resolveDmCrypto();
|
|
5008
5084
|
let msgIds = ids && ids.length > 0 ? ids : void 0;
|
|
5085
|
+
if (typeof opts?.attachment === "string") {
|
|
5086
|
+
if (msgIds?.length !== 1) {
|
|
5087
|
+
throw new Error("Name exactly one message: arbi dm read <ntf-id> --attachment <att-id>");
|
|
5088
|
+
}
|
|
5089
|
+
const rows = await sdk.dm.listDecryptedDMs(arbi, crypto);
|
|
5090
|
+
const row = rows.find((m) => m.external_id === msgIds[0]);
|
|
5091
|
+
if (!row) throw new Error(`No message ${msgIds[0]}`);
|
|
5092
|
+
if (row.attachmentsError) throw new Error(row.attachmentsError);
|
|
5093
|
+
const file = findAttachment(row, opts.attachment);
|
|
5094
|
+
const bytes = await sdk.dm.downloadDmAttachment(arbi, file);
|
|
5095
|
+
const target = attachmentOutputPath(
|
|
5096
|
+
file,
|
|
5097
|
+
typeof opts.output === "string" ? opts.output : void 0
|
|
5098
|
+
);
|
|
5099
|
+
fs7__default.default.writeFileSync(target, bytes);
|
|
5100
|
+
success(`Saved ${target} (${bytes.length} bytes, decrypted)`);
|
|
5101
|
+
return;
|
|
5102
|
+
}
|
|
5009
5103
|
if (!msgIds && opts?.all) {
|
|
5010
5104
|
const data2 = await sdk.dm.listDecryptedDMs(arbi, crypto);
|
|
5011
5105
|
msgIds = data2.filter((m) => !m.read).map((m) => m.external_id);
|
|
@@ -5758,12 +5852,12 @@ function registerDocsCommand(program2) {
|
|
|
5758
5852
|
null,
|
|
5759
5853
|
opts.output ? 2 : 0
|
|
5760
5854
|
);
|
|
5761
|
-
if (opts.output)
|
|
5855
|
+
if (opts.output) fs7.writeFileSync(opts.output, emptyPayload + "\n");
|
|
5762
5856
|
else console.log(emptyPayload);
|
|
5763
5857
|
} else if (opts.ids) {
|
|
5764
|
-
if (opts.output)
|
|
5858
|
+
if (opts.output) fs7.writeFileSync(opts.output, "");
|
|
5765
5859
|
} else if (opts.csv) {
|
|
5766
|
-
if (opts.output)
|
|
5860
|
+
if (opts.output) fs7.writeFileSync(opts.output, csvHeader + "\n");
|
|
5767
5861
|
} else if (opts.count) {
|
|
5768
5862
|
const wsLabel2 = workspaceName ? `${workspaceName} (${workspaceId})` : workspaceId;
|
|
5769
5863
|
console.log(chalk2__default.default.dim(`Workspace: ${wsLabel2}`));
|
|
@@ -5828,7 +5922,7 @@ function registerDocsCommand(program2) {
|
|
|
5828
5922
|
}
|
|
5829
5923
|
const writeOut = (payload, defaultExt) => {
|
|
5830
5924
|
if (opts.output) {
|
|
5831
|
-
|
|
5925
|
+
fs7.writeFileSync(opts.output, payload.endsWith("\n") ? payload : payload + "\n");
|
|
5832
5926
|
success(`Wrote ${data.length} rows to ${opts.output} (${defaultExt})`);
|
|
5833
5927
|
} else {
|
|
5834
5928
|
console.log(payload.endsWith("\n") ? payload.slice(0, -1) : payload);
|
|
@@ -6427,12 +6521,12 @@ function printSummary(summary) {
|
|
|
6427
6521
|
}
|
|
6428
6522
|
function countSupportedFiles(dirPath) {
|
|
6429
6523
|
let count = 0;
|
|
6430
|
-
for (const entry of
|
|
6524
|
+
for (const entry of fs7__default.default.readdirSync(dirPath, { withFileTypes: true })) {
|
|
6431
6525
|
const full = `${dirPath}/${entry.name}`;
|
|
6432
6526
|
if (entry.isDirectory()) {
|
|
6433
6527
|
count += countSupportedFiles(full);
|
|
6434
6528
|
} else if (entry.isFile()) {
|
|
6435
|
-
const ext =
|
|
6529
|
+
const ext = path6__default.default.extname(entry.name).toLowerCase();
|
|
6436
6530
|
if (sdk.documents.SUPPORTED_EXTENSIONS.has(ext)) count++;
|
|
6437
6531
|
}
|
|
6438
6532
|
}
|
|
@@ -6460,17 +6554,17 @@ function mergeBatchResult(summary, uploadedDocs, result, sourceLabel, opts) {
|
|
|
6460
6554
|
function classifyDirectInputs(inputPaths) {
|
|
6461
6555
|
const out = [];
|
|
6462
6556
|
for (const p of inputPaths) {
|
|
6463
|
-
if (!
|
|
6557
|
+
if (!fs7__default.default.existsSync(p)) {
|
|
6464
6558
|
error(`Path not found: ${p}`);
|
|
6465
6559
|
process.exit(1);
|
|
6466
6560
|
}
|
|
6467
|
-
const resolved =
|
|
6468
|
-
const stat =
|
|
6561
|
+
const resolved = path6__default.default.resolve(p);
|
|
6562
|
+
const stat = fs7__default.default.statSync(resolved);
|
|
6469
6563
|
if (stat.isDirectory()) {
|
|
6470
6564
|
out.push({ kind: "dir", absolutePath: resolved, originalPath: p });
|
|
6471
6565
|
continue;
|
|
6472
6566
|
}
|
|
6473
|
-
const ext =
|
|
6567
|
+
const ext = path6__default.default.extname(resolved).toLowerCase();
|
|
6474
6568
|
if (ext === ".zip") {
|
|
6475
6569
|
out.push({ kind: "zip", absolutePath: resolved, originalPath: p });
|
|
6476
6570
|
continue;
|
|
@@ -6508,7 +6602,7 @@ async function runDirectUploadMode(inputPaths, opts) {
|
|
|
6508
6602
|
console.log(` ${inp.originalPath}: zip archive (contents would be extracted + uploaded)`);
|
|
6509
6603
|
} else {
|
|
6510
6604
|
console.log(
|
|
6511
|
-
` ${inp.originalPath}: ${
|
|
6605
|
+
` ${inp.originalPath}: ${path6__default.default.extname(inp.absolutePath).slice(1)} archive (contents would be extracted + uploaded)`
|
|
6512
6606
|
);
|
|
6513
6607
|
}
|
|
6514
6608
|
}
|
|
@@ -6617,7 +6711,7 @@ async function runDirectUploadMode(inputPaths, opts) {
|
|
|
6617
6711
|
summary.docIds.push(...result.doc_ext_ids);
|
|
6618
6712
|
summary.skippedDetails.push(...result.skipped);
|
|
6619
6713
|
for (let i = 0; i < result.doc_ext_ids.length && i < plainFiles.length; i++) {
|
|
6620
|
-
uploadedDocs.set(result.doc_ext_ids[i],
|
|
6714
|
+
uploadedDocs.set(result.doc_ext_ids[i], path6__default.default.basename(plainFiles[i]));
|
|
6621
6715
|
}
|
|
6622
6716
|
if (!opts.json) {
|
|
6623
6717
|
success(
|
|
@@ -6717,7 +6811,7 @@ function registerUploadCommand(program2) {
|
|
|
6717
6811
|
process.exit(1);
|
|
6718
6812
|
}
|
|
6719
6813
|
for (const p of inputPaths) {
|
|
6720
|
-
if (!
|
|
6814
|
+
if (!fs7__default.default.existsSync(p)) {
|
|
6721
6815
|
error(`Path not found: ${p}`);
|
|
6722
6816
|
process.exit(1);
|
|
6723
6817
|
}
|
|
@@ -6759,7 +6853,7 @@ function registerUploadCommand(program2) {
|
|
|
6759
6853
|
}
|
|
6760
6854
|
};
|
|
6761
6855
|
for (const filePath of inputPaths) {
|
|
6762
|
-
const stat =
|
|
6856
|
+
const stat = fs7__default.default.statSync(filePath);
|
|
6763
6857
|
if (stat.isDirectory()) {
|
|
6764
6858
|
if (opts.dryRun) {
|
|
6765
6859
|
const count = countSupportedFiles2(filePath);
|
|
@@ -6953,7 +7047,7 @@ function updateSummary(summary, result) {
|
|
|
6953
7047
|
}
|
|
6954
7048
|
function countSupportedFiles2(dirPath) {
|
|
6955
7049
|
let count = 0;
|
|
6956
|
-
for (const entry of
|
|
7050
|
+
for (const entry of fs7__default.default.readdirSync(dirPath, { withFileTypes: true })) {
|
|
6957
7051
|
const fullPath = `${dirPath}/${entry.name}`;
|
|
6958
7052
|
if (entry.isDirectory()) {
|
|
6959
7053
|
count += countSupportedFiles2(fullPath);
|
|
@@ -6971,8 +7065,8 @@ function countSupportedFiles2(dirPath) {
|
|
|
6971
7065
|
}
|
|
6972
7066
|
function readLogState(logPath) {
|
|
6973
7067
|
const state = /* @__PURE__ */ new Map();
|
|
6974
|
-
if (!
|
|
6975
|
-
const text =
|
|
7068
|
+
if (!fs7__default.default.existsSync(logPath)) return state;
|
|
7069
|
+
const text = fs7__default.default.readFileSync(logPath, "utf8");
|
|
6976
7070
|
for (const line of text.split("\n")) {
|
|
6977
7071
|
const trimmed = line.trim();
|
|
6978
7072
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -6988,7 +7082,7 @@ function readLogState(logPath) {
|
|
|
6988
7082
|
return state;
|
|
6989
7083
|
}
|
|
6990
7084
|
function readTextManifest(manifestPath) {
|
|
6991
|
-
const text =
|
|
7085
|
+
const text = fs7__default.default.readFileSync(manifestPath, "utf8");
|
|
6992
7086
|
const out = [];
|
|
6993
7087
|
for (const raw of text.split("\n")) {
|
|
6994
7088
|
const line = raw.replace(/\r$/, "").trim();
|
|
@@ -7060,8 +7154,8 @@ function writeCsvAtomic(filePath, header, rows) {
|
|
|
7060
7154
|
lines.push(padded.map(csvField).join(","));
|
|
7061
7155
|
}
|
|
7062
7156
|
const tmp = filePath + ".tmp";
|
|
7063
|
-
|
|
7064
|
-
|
|
7157
|
+
fs7__default.default.writeFileSync(tmp, lines.join("\n") + "\n");
|
|
7158
|
+
fs7__default.default.renameSync(tmp, filePath);
|
|
7065
7159
|
}
|
|
7066
7160
|
function findColumn(header, candidates) {
|
|
7067
7161
|
const normalized = header.map((h) => h.trim().toLowerCase());
|
|
@@ -7072,7 +7166,7 @@ function findColumn(header, candidates) {
|
|
|
7072
7166
|
return -1;
|
|
7073
7167
|
}
|
|
7074
7168
|
function loadCsvManifest(csvPath, rootDir) {
|
|
7075
|
-
const text =
|
|
7169
|
+
const text = fs7__default.default.readFileSync(csvPath, "utf8");
|
|
7076
7170
|
const all = parseCsv(text);
|
|
7077
7171
|
if (all.length === 0) {
|
|
7078
7172
|
error(`Empty CSV: ${csvPath}`);
|
|
@@ -7103,7 +7197,7 @@ function loadCsvManifest(csvPath, rootDir) {
|
|
|
7103
7197
|
for (const row of rows) {
|
|
7104
7198
|
while (row.length < header.length) row.push("");
|
|
7105
7199
|
}
|
|
7106
|
-
const root = rootDir ?
|
|
7200
|
+
const root = rootDir ? path6__default.default.resolve(rootDir) : process.cwd();
|
|
7107
7201
|
const paths = [];
|
|
7108
7202
|
const pathToRow = /* @__PURE__ */ new Map();
|
|
7109
7203
|
for (let i = 0; i < rows.length; i++) {
|
|
@@ -7111,8 +7205,8 @@ function loadCsvManifest(csvPath, rootDir) {
|
|
|
7111
7205
|
const name = (row[nameCol] ?? "").trim();
|
|
7112
7206
|
if (!name) continue;
|
|
7113
7207
|
const folder = (row[folderCol] ?? "").trim();
|
|
7114
|
-
const rel = folder ?
|
|
7115
|
-
const abs =
|
|
7208
|
+
const rel = folder ? path6__default.default.join(folder, name) : name;
|
|
7209
|
+
const abs = path6__default.default.resolve(root, rel);
|
|
7116
7210
|
paths.push(abs);
|
|
7117
7211
|
pathToRow.set(abs, i);
|
|
7118
7212
|
}
|
|
@@ -7136,11 +7230,11 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7136
7230
|
const rawPaths = [];
|
|
7137
7231
|
let csv = null;
|
|
7138
7232
|
if (opts.manifest) {
|
|
7139
|
-
if (!
|
|
7233
|
+
if (!fs7__default.default.existsSync(opts.manifest)) {
|
|
7140
7234
|
error(`Manifest not found: ${opts.manifest}`);
|
|
7141
7235
|
process.exit(1);
|
|
7142
7236
|
}
|
|
7143
|
-
const ext =
|
|
7237
|
+
const ext = path6__default.default.extname(opts.manifest).toLowerCase();
|
|
7144
7238
|
if (ext === ".csv" || ext === ".tsv") {
|
|
7145
7239
|
csv = loadCsvManifest(opts.manifest, opts.root);
|
|
7146
7240
|
rawPaths.push(...csv.paths);
|
|
@@ -7149,15 +7243,15 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7149
7243
|
}
|
|
7150
7244
|
}
|
|
7151
7245
|
for (const p of inputPaths) {
|
|
7152
|
-
if (!
|
|
7246
|
+
if (!fs7__default.default.existsSync(p)) {
|
|
7153
7247
|
error(`Path not found: ${p}`);
|
|
7154
7248
|
process.exit(1);
|
|
7155
7249
|
}
|
|
7156
|
-
const stat =
|
|
7250
|
+
const stat = fs7__default.default.statSync(p);
|
|
7157
7251
|
if (stat.isDirectory()) {
|
|
7158
7252
|
rawPaths.push(...sdk.documentsNode.walkSupportedFiles(p));
|
|
7159
7253
|
} else {
|
|
7160
|
-
rawPaths.push(
|
|
7254
|
+
rawPaths.push(path6__default.default.resolve(p));
|
|
7161
7255
|
}
|
|
7162
7256
|
}
|
|
7163
7257
|
if (rawPaths.length === 0) {
|
|
@@ -7195,7 +7289,7 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7195
7289
|
const humanOutput = !opts.json;
|
|
7196
7290
|
if (humanOutput) {
|
|
7197
7291
|
console.log(
|
|
7198
|
-
`Manifest: ${rawPaths.length} file(s)` + (csv ? ` from ${
|
|
7292
|
+
`Manifest: ${rawPaths.length} file(s)` + (csv ? ` from ${path6__default.default.basename(csv.filePath)}` : "") + (resumedCount ? ` (${resumedCount} already done, skipping)` : "") + (limit !== null && limitedOut > 0 ? ` (limit=${limit}, ${limitedOut} deferred to next run)` : "")
|
|
7199
7293
|
);
|
|
7200
7294
|
}
|
|
7201
7295
|
if (opts.dryRun) {
|
|
@@ -7224,9 +7318,9 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7224
7318
|
const auth = { baseUrl: config.baseUrl, accessToken };
|
|
7225
7319
|
let logFd = null;
|
|
7226
7320
|
if (opts.log) {
|
|
7227
|
-
const dir =
|
|
7228
|
-
|
|
7229
|
-
logFd =
|
|
7321
|
+
const dir = path6__default.default.dirname(path6__default.default.resolve(opts.log));
|
|
7322
|
+
fs7__default.default.mkdirSync(dir, { recursive: true });
|
|
7323
|
+
logFd = fs7__default.default.openSync(opts.log, "a");
|
|
7230
7324
|
const header = JSON.stringify({
|
|
7231
7325
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7232
7326
|
event: "run_start",
|
|
@@ -7236,8 +7330,8 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7236
7330
|
toUpload: pathsToUpload.length,
|
|
7237
7331
|
resumed: resumedCount
|
|
7238
7332
|
});
|
|
7239
|
-
|
|
7240
|
-
|
|
7333
|
+
fs7__default.default.writeSync(logFd, header + "\n");
|
|
7334
|
+
fs7__default.default.fsyncSync(logFd);
|
|
7241
7335
|
}
|
|
7242
7336
|
const uploadedDocs = /* @__PURE__ */ new Map();
|
|
7243
7337
|
const runStart = Date.now();
|
|
@@ -7254,8 +7348,8 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7254
7348
|
attempt: o.attempt,
|
|
7255
7349
|
...o.batchId ? { batchId: o.batchId } : {}
|
|
7256
7350
|
};
|
|
7257
|
-
|
|
7258
|
-
|
|
7351
|
+
fs7__default.default.writeSync(logFd, JSON.stringify(rec) + "\n");
|
|
7352
|
+
fs7__default.default.fsyncSync(logFd);
|
|
7259
7353
|
};
|
|
7260
7354
|
const total = pathsToUpload.length;
|
|
7261
7355
|
let done = 0;
|
|
@@ -7275,7 +7369,7 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7275
7369
|
};
|
|
7276
7370
|
const printInlineOutcome = (o) => {
|
|
7277
7371
|
if (!humanOutput) return;
|
|
7278
|
-
const name =
|
|
7372
|
+
const name = path6__default.default.basename(o.path);
|
|
7279
7373
|
if (o.status === "rejected") {
|
|
7280
7374
|
clearProgress();
|
|
7281
7375
|
warn(` \u2717 ${name}: ${o.reason}`);
|
|
@@ -7307,7 +7401,7 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7307
7401
|
switch (outcome.status) {
|
|
7308
7402
|
case "uploaded":
|
|
7309
7403
|
uploadedCount++;
|
|
7310
|
-
if (outcome.docId) uploadedDocs.set(outcome.docId,
|
|
7404
|
+
if (outcome.docId) uploadedDocs.set(outcome.docId, path6__default.default.basename(outcome.path));
|
|
7311
7405
|
break;
|
|
7312
7406
|
case "duplicate":
|
|
7313
7407
|
duplicateCount++;
|
|
@@ -7346,9 +7440,9 @@ async function runManifestMode(inputPaths, opts) {
|
|
|
7346
7440
|
...result.summary,
|
|
7347
7441
|
elapsedMs: Date.now() - runStart
|
|
7348
7442
|
});
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7443
|
+
fs7__default.default.writeSync(logFd, footer + "\n");
|
|
7444
|
+
fs7__default.default.fsyncSync(logFd);
|
|
7445
|
+
fs7__default.default.closeSync(logFd);
|
|
7352
7446
|
}
|
|
7353
7447
|
clearProgress();
|
|
7354
7448
|
if (opts.json) {
|
|
@@ -7473,21 +7567,21 @@ function registerDownloadCommand(program2) {
|
|
|
7473
7567
|
process.stdout.write(buffer);
|
|
7474
7568
|
return;
|
|
7475
7569
|
}
|
|
7476
|
-
const outputPath = opts.output ||
|
|
7477
|
-
|
|
7570
|
+
const outputPath = opts.output || path6__default.default.join(process.cwd(), filename);
|
|
7571
|
+
fs7__default.default.writeFileSync(outputPath, buffer);
|
|
7478
7572
|
if (opts.json) {
|
|
7479
7573
|
console.log(
|
|
7480
7574
|
JSON.stringify({
|
|
7481
7575
|
doc_id: docId,
|
|
7482
7576
|
path: outputPath,
|
|
7483
7577
|
bytes: buffer.length,
|
|
7484
|
-
filename:
|
|
7578
|
+
filename: path6__default.default.basename(outputPath)
|
|
7485
7579
|
})
|
|
7486
7580
|
);
|
|
7487
7581
|
return;
|
|
7488
7582
|
}
|
|
7489
7583
|
success(
|
|
7490
|
-
`Downloaded: ${
|
|
7584
|
+
`Downloaded: ${path6__default.default.basename(outputPath)} (${(buffer.length / (1024 * 1024)).toFixed(1)} MB)`
|
|
7491
7585
|
);
|
|
7492
7586
|
})()
|
|
7493
7587
|
);
|
|
@@ -8650,12 +8744,12 @@ function registerConversationsCommand(program2) {
|
|
|
8650
8744
|
conv.command("import <path>").description(
|
|
8651
8745
|
"Import a conversation export (ChatGPT, OpenClaw, or Claude Code) into the active workspace"
|
|
8652
8746
|
).option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-s, --source <source>", "Export format: auto, chatgpt, openclaw, claude_code", "auto").option("--json", "Output as JSON").action(
|
|
8653
|
-
(
|
|
8747
|
+
(path8, opts) => runAction(async () => {
|
|
8654
8748
|
const { loginResult, config } = await resolveWorkspace(opts.workspace);
|
|
8655
|
-
const filePath =
|
|
8749
|
+
const filePath = path6.resolve(path8);
|
|
8656
8750
|
let bytes;
|
|
8657
8751
|
try {
|
|
8658
|
-
bytes =
|
|
8752
|
+
bytes = fs7.readFileSync(filePath);
|
|
8659
8753
|
} catch {
|
|
8660
8754
|
error(`Cannot read file: ${filePath}`);
|
|
8661
8755
|
process.exit(3);
|
|
@@ -8667,7 +8761,7 @@ function registerConversationsCommand(program2) {
|
|
|
8667
8761
|
accessToken: loginResult.accessToken
|
|
8668
8762
|
},
|
|
8669
8763
|
blob,
|
|
8670
|
-
|
|
8764
|
+
path6.basename(filePath),
|
|
8671
8765
|
opts.source ?? "auto"
|
|
8672
8766
|
);
|
|
8673
8767
|
if (opts.json) {
|
|
@@ -9806,7 +9900,7 @@ function registerWorkflowCommand(program2) {
|
|
|
9806
9900
|
workflow.command("update <id>").description("Update any saved automation settings from a JSON file").requiredOption("--file <path>", "JSON UpdateWorkflowRequest file").option("--json", "Output as JSON").action(
|
|
9807
9901
|
(id, opts) => runAction(async () => {
|
|
9808
9902
|
const { arbi } = await resolveAuth();
|
|
9809
|
-
const body = JSON.parse(
|
|
9903
|
+
const body = JSON.parse(fs7.readFileSync(opts.file, "utf8"));
|
|
9810
9904
|
const data = await sdk.workflows.updateWorkflow(arbi, id, body);
|
|
9811
9905
|
if (opts.json) printJson(data);
|
|
9812
9906
|
else success(`Updated automation ${ref(id)}`);
|
|
@@ -9843,15 +9937,15 @@ compdef _arbi_completions arbi
|
|
|
9843
9937
|
${MARKER_END}`;
|
|
9844
9938
|
function getShellRcPath2() {
|
|
9845
9939
|
const shell = process.env.SHELL || "";
|
|
9846
|
-
if (shell.includes("zsh")) return
|
|
9847
|
-
return
|
|
9940
|
+
if (shell.includes("zsh")) return path6.join(os2.homedir(), ".zshrc");
|
|
9941
|
+
return path6.join(os2.homedir(), ".bashrc");
|
|
9848
9942
|
}
|
|
9849
9943
|
function isZsh() {
|
|
9850
9944
|
return (process.env.SHELL || "").includes("zsh");
|
|
9851
9945
|
}
|
|
9852
9946
|
function isCompletionInstalled(rcPath) {
|
|
9853
|
-
if (!
|
|
9854
|
-
const content =
|
|
9947
|
+
if (!fs7.existsSync(rcPath)) return false;
|
|
9948
|
+
const content = fs7.readFileSync(rcPath, "utf-8");
|
|
9855
9949
|
return content.includes(MARKER_START);
|
|
9856
9950
|
}
|
|
9857
9951
|
function removeCompletionBlock(content) {
|
|
@@ -9872,7 +9966,7 @@ function registerCompletionCommand(program2) {
|
|
|
9872
9966
|
return;
|
|
9873
9967
|
}
|
|
9874
9968
|
const snippet = isZsh() ? ZSH_COMPLETION : BASH_COMPLETION;
|
|
9875
|
-
|
|
9969
|
+
fs7.appendFileSync(rcPath, snippet + "\n");
|
|
9876
9970
|
success(`Installed tab completion in ${rcPath}`);
|
|
9877
9971
|
dim("");
|
|
9878
9972
|
dim(`Run: source ${rcPath}`);
|
|
@@ -9884,9 +9978,9 @@ function registerCompletionCommand(program2) {
|
|
|
9884
9978
|
dim("Completion is not installed.");
|
|
9885
9979
|
return;
|
|
9886
9980
|
}
|
|
9887
|
-
const content =
|
|
9981
|
+
const content = fs7.readFileSync(rcPath, "utf-8");
|
|
9888
9982
|
const cleaned = removeCompletionBlock(content);
|
|
9889
|
-
|
|
9983
|
+
fs7.writeFileSync(rcPath, cleaned);
|
|
9890
9984
|
success(`Removed tab completion from ${rcPath}`);
|
|
9891
9985
|
dim(`Run: source ${rcPath}`);
|
|
9892
9986
|
});
|
|
@@ -9902,7 +9996,7 @@ function registerCompletionCommand(program2) {
|
|
|
9902
9996
|
function resolvePath(p) {
|
|
9903
9997
|
const raw = p ?? ".";
|
|
9904
9998
|
const expanded = raw.startsWith("~") ? raw.replace("~", os2.homedir()) : raw;
|
|
9905
|
-
return
|
|
9999
|
+
return path6.resolve(expanded);
|
|
9906
10000
|
}
|
|
9907
10001
|
function formatSize2(bytes) {
|
|
9908
10002
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -9912,7 +10006,7 @@ function formatSize2(bytes) {
|
|
|
9912
10006
|
}
|
|
9913
10007
|
function entryToRow(dir, name) {
|
|
9914
10008
|
try {
|
|
9915
|
-
const stat =
|
|
10009
|
+
const stat = fs7.statSync(path6.join(dir, name));
|
|
9916
10010
|
if (stat.isDirectory()) return { name, type: "dir", size: null };
|
|
9917
10011
|
if (stat.isSymbolicLink()) return { name, type: "symlink", size: stat.size };
|
|
9918
10012
|
if (stat.isFile()) return { name, type: "file", size: stat.size };
|
|
@@ -9923,11 +10017,11 @@ function entryToRow(dir, name) {
|
|
|
9923
10017
|
}
|
|
9924
10018
|
function registerLocalCommand(program2) {
|
|
9925
10019
|
const local = program2.command("local").description("Local filesystem operations");
|
|
9926
|
-
local.command("ls [path]").description("List files in a directory").option("-l, --long", "Show file sizes and types (ignored when --json is set)").option("-a, --all", "Include dotfiles").option("--json", "Output as JSON array of {name, type, size}").action((
|
|
9927
|
-
const dir = resolvePath(
|
|
10020
|
+
local.command("ls [path]").description("List files in a directory").option("-l, --long", "Show file sizes and types (ignored when --json is set)").option("-a, --all", "Include dotfiles").option("--json", "Output as JSON array of {name, type, size}").action((path8, opts) => {
|
|
10021
|
+
const dir = resolvePath(path8);
|
|
9928
10022
|
let entries;
|
|
9929
10023
|
try {
|
|
9930
|
-
entries =
|
|
10024
|
+
entries = fs7.readdirSync(dir);
|
|
9931
10025
|
} catch {
|
|
9932
10026
|
console.error(`Cannot read directory: ${dir}`);
|
|
9933
10027
|
process.exit(1);
|
|
@@ -9950,7 +10044,7 @@ function registerLocalCommand(program2) {
|
|
|
9950
10044
|
});
|
|
9951
10045
|
local.command("find <pattern>").description('Find files matching a glob (e.g. "**/*.pdf")').option("-d, --dir <path>", "Directory to search in", ".").option("--json", "Output as JSON array of matched paths").action((pattern, opts) => {
|
|
9952
10046
|
const dir = resolvePath(opts.dir);
|
|
9953
|
-
const results =
|
|
10047
|
+
const results = fs7.globSync(pattern, { cwd: dir });
|
|
9954
10048
|
if (opts.json) {
|
|
9955
10049
|
if (results.length === 0) {
|
|
9956
10050
|
process.stderr.write(`No files matching "${pattern}" in ${dir}
|
|
@@ -9975,7 +10069,7 @@ function registerLocalCommand(program2) {
|
|
|
9975
10069
|
const filePath = resolvePath(file);
|
|
9976
10070
|
let content;
|
|
9977
10071
|
try {
|
|
9978
|
-
content =
|
|
10072
|
+
content = fs7.readFileSync(filePath, "utf-8");
|
|
9979
10073
|
} catch {
|
|
9980
10074
|
console.error(`Cannot read file: ${filePath}`);
|
|
9981
10075
|
process.exit(1);
|
|
@@ -9990,31 +10084,31 @@ function registerLocalCommand(program2) {
|
|
|
9990
10084
|
}
|
|
9991
10085
|
console.log(content);
|
|
9992
10086
|
});
|
|
9993
|
-
local.command("tree [path]").description("Show directory tree").option("-d, --depth <n>", "Maximum depth", "3").option("--json", "Output as nested {name, type, children} tree").action((
|
|
9994
|
-
const dir = resolvePath(
|
|
10087
|
+
local.command("tree [path]").description("Show directory tree").option("-d, --depth <n>", "Maximum depth", "3").option("--json", "Output as nested {name, type, children} tree").action((path8, opts) => {
|
|
10088
|
+
const dir = resolvePath(path8);
|
|
9995
10089
|
const maxDepth = parseInt(opts?.depth ?? "3", 10);
|
|
9996
10090
|
if (opts?.json) {
|
|
9997
10091
|
printJson(buildTree(dir, maxDepth, 0));
|
|
9998
10092
|
return;
|
|
9999
10093
|
}
|
|
10000
|
-
console.log(
|
|
10094
|
+
console.log(path6.basename(dir) + "/");
|
|
10001
10095
|
printTree(dir, "", maxDepth, 0);
|
|
10002
10096
|
});
|
|
10003
10097
|
}
|
|
10004
10098
|
function buildTree(dir, maxDepth, depth) {
|
|
10005
|
-
const node = { name:
|
|
10099
|
+
const node = { name: path6.basename(dir), type: "dir", children: [] };
|
|
10006
10100
|
if (depth >= maxDepth) return node;
|
|
10007
10101
|
let entries;
|
|
10008
10102
|
try {
|
|
10009
|
-
entries =
|
|
10103
|
+
entries = fs7.readdirSync(dir).filter((e) => !e.startsWith(".")).sort();
|
|
10010
10104
|
} catch {
|
|
10011
10105
|
return node;
|
|
10012
10106
|
}
|
|
10013
10107
|
for (const entry of entries) {
|
|
10014
|
-
const full =
|
|
10108
|
+
const full = path6.join(dir, entry);
|
|
10015
10109
|
let isDir = false;
|
|
10016
10110
|
try {
|
|
10017
|
-
isDir =
|
|
10111
|
+
isDir = fs7.statSync(full).isDirectory();
|
|
10018
10112
|
} catch {
|
|
10019
10113
|
node.children.push({ name: entry, type: "other" });
|
|
10020
10114
|
continue;
|
|
@@ -10031,7 +10125,7 @@ function printTree(dir, prefix, maxDepth, depth) {
|
|
|
10031
10125
|
if (depth >= maxDepth) return;
|
|
10032
10126
|
let entries;
|
|
10033
10127
|
try {
|
|
10034
|
-
entries =
|
|
10128
|
+
entries = fs7.readdirSync(dir).filter((e) => !e.startsWith(".")).sort();
|
|
10035
10129
|
} catch {
|
|
10036
10130
|
return;
|
|
10037
10131
|
}
|
|
@@ -10039,10 +10133,10 @@ function printTree(dir, prefix, maxDepth, depth) {
|
|
|
10039
10133
|
const entry = entries[i];
|
|
10040
10134
|
const isLast = i === entries.length - 1;
|
|
10041
10135
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
10042
|
-
const full =
|
|
10136
|
+
const full = path6.join(dir, entry);
|
|
10043
10137
|
let isDir = false;
|
|
10044
10138
|
try {
|
|
10045
|
-
isDir =
|
|
10139
|
+
isDir = fs7.statSync(full).isDirectory();
|
|
10046
10140
|
} catch {
|
|
10047
10141
|
continue;
|
|
10048
10142
|
}
|
|
@@ -10123,7 +10217,7 @@ function parseAddress(value) {
|
|
|
10123
10217
|
function collect(value, previous = []) {
|
|
10124
10218
|
return [...previous, ...value.split(",").filter((v) => v.trim())];
|
|
10125
10219
|
}
|
|
10126
|
-
var readTextFile = (
|
|
10220
|
+
var readTextFile = (path8) => fs7__default.default.readFileSync(path8 === "-" ? 0 : path8, "utf8");
|
|
10127
10221
|
function buildCompose(options) {
|
|
10128
10222
|
const read = options.readText ?? readTextFile;
|
|
10129
10223
|
if (options.text !== void 0 && options.textFile) {
|
|
@@ -10245,7 +10339,7 @@ function registerMailCommand(program2) {
|
|
|
10245
10339
|
if (!meta) throw new Error(`No attachment ${opts.attachment} on this message`);
|
|
10246
10340
|
const bytes = await sdk.mail.downloadAttachment(fetch2, id, meta.id);
|
|
10247
10341
|
const target = opts.output ?? meta.name;
|
|
10248
|
-
|
|
10342
|
+
fs7__default.default.writeFileSync(target, bytes);
|
|
10249
10343
|
success(`Saved ${target} (${bytes.length} bytes)`);
|
|
10250
10344
|
return;
|
|
10251
10345
|
}
|
|
@@ -10529,12 +10623,12 @@ function registerFilesCommand(program2) {
|
|
|
10529
10623
|
})()
|
|
10530
10624
|
);
|
|
10531
10625
|
files.command("upload <path>").description("Upload a file (file ID is returned for use with arbi ask -b --attach)").option("--purpose <name>", "OpenAI purpose tag (default: assistants)", "assistants").action(
|
|
10532
|
-
(
|
|
10626
|
+
(path8, opts) => runAction(async () => {
|
|
10533
10627
|
const { loginResult, config } = await resolveWorkspace();
|
|
10534
|
-
const filePath =
|
|
10628
|
+
const filePath = path6.resolve(path8);
|
|
10535
10629
|
let bytes;
|
|
10536
10630
|
try {
|
|
10537
|
-
bytes =
|
|
10631
|
+
bytes = fs7.readFileSync(filePath);
|
|
10538
10632
|
} catch {
|
|
10539
10633
|
error(`Cannot read file: ${filePath}`);
|
|
10540
10634
|
process.exit(3);
|
|
@@ -10546,7 +10640,7 @@ function registerFilesCommand(program2) {
|
|
|
10546
10640
|
accessToken: loginResult.accessToken
|
|
10547
10641
|
},
|
|
10548
10642
|
blob,
|
|
10549
|
-
|
|
10643
|
+
path6.basename(filePath),
|
|
10550
10644
|
opts.purpose ?? "assistants"
|
|
10551
10645
|
);
|
|
10552
10646
|
success(`Uploaded: ${ref(data.id)} (${formatBytes(data.bytes ?? 0)})`);
|
|
@@ -10585,7 +10679,7 @@ function registerFilesCommand(program2) {
|
|
|
10585
10679
|
process.stdout.write(buf);
|
|
10586
10680
|
return;
|
|
10587
10681
|
}
|
|
10588
|
-
|
|
10682
|
+
fs7.writeFileSync(path6.resolve(opts.output), buf);
|
|
10589
10683
|
success(`Wrote ${formatBytes(buf.length)} \u2192 ${opts.output}`);
|
|
10590
10684
|
})()
|
|
10591
10685
|
);
|
|
@@ -10664,7 +10758,7 @@ function registerAuthCommand(program2) {
|
|
|
10664
10758
|
let picture = opts.picture;
|
|
10665
10759
|
if (picture && !/^https?:|^data:/.test(picture)) {
|
|
10666
10760
|
try {
|
|
10667
|
-
const bytes =
|
|
10761
|
+
const bytes = fs7.readFileSync(path6.resolve(picture));
|
|
10668
10762
|
const ext = picture.toLowerCase().split(".").pop();
|
|
10669
10763
|
const mime = ext === "png" ? "image/png" : ext === "gif" ? "image/gif" : "image/jpeg";
|
|
10670
10764
|
picture = `data:${mime};base64,${bytes.toString("base64")}`;
|
|
@@ -10754,13 +10848,13 @@ async function loadSkillSource(source) {
|
|
|
10754
10848
|
}
|
|
10755
10849
|
return await res.text();
|
|
10756
10850
|
}
|
|
10757
|
-
const stat =
|
|
10851
|
+
const stat = fs7.statSync(source);
|
|
10758
10852
|
if (stat.isDirectory()) {
|
|
10759
10853
|
throw new Error(
|
|
10760
10854
|
`${source} is a directory. Pass a single SKILL.md file, or use \`\`arbi upload --folder skills/<slug> --wp-type skill\`\` for multi-file skills.`
|
|
10761
10855
|
);
|
|
10762
10856
|
}
|
|
10763
|
-
return
|
|
10857
|
+
return fs7.readFileSync(source, "utf8");
|
|
10764
10858
|
}
|
|
10765
10859
|
function registerSkillsCommand(program2) {
|
|
10766
10860
|
const skills = program2.command("skills").description("Skills: list, show");
|
|
@@ -10878,7 +10972,7 @@ console.info = (...args) => {
|
|
|
10878
10972
|
_origInfo(...args);
|
|
10879
10973
|
};
|
|
10880
10974
|
var program = new commander.Command();
|
|
10881
|
-
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.4.
|
|
10975
|
+
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.4.51").showHelpAfterError(true).showSuggestionAfterError(true);
|
|
10882
10976
|
registerConfigCommand(program);
|
|
10883
10977
|
registerLoginCommand(program);
|
|
10884
10978
|
registerRegisterCommand(program);
|