@arbidocs/cli 0.3.65 → 0.3.67
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 +40 -0
- package/dist/index.js +206 -27
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.3.67
|
|
4
|
+
|
|
5
|
+
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.66...HEAD)
|
|
6
|
+
|
|
7
|
+
### 🚀 Enhancements
|
|
8
|
+
|
|
9
|
+
- **tui:** SOTA amendments — citations, events, tool blocks, view/sources/history ([#774](https://github.com/arbicity/ARBI-frontend/pull/774))
|
|
10
|
+
- **sdk,cli,tui:** Consume GET /v1/assistant/skills for slash autocomplete ([#776](https://github.com/arbicity/ARBI-frontend/pull/776))
|
|
11
|
+
- **tui,cli:** Unified slash dispatcher + autocomplete merges static commands and skills ([#777](https://github.com/arbicity/ARBI-frontend/pull/777))
|
|
12
|
+
- **sdk,tui,cli,react:** Skill iteration loop — edit/install/pre-flight + React slash menu ([#778](https://github.com/arbicity/ARBI-frontend/pull/778))
|
|
13
|
+
|
|
14
|
+
## v0.3.66
|
|
15
|
+
|
|
16
|
+
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.65...HEAD)
|
|
17
|
+
|
|
18
|
+
### 🚀 Enhancements
|
|
19
|
+
|
|
20
|
+
- **artifact:** Always-editable .md tab + mount-time normalisation absorption ([#754](https://github.com/arbicity/ARBI-frontend/pull/754))
|
|
21
|
+
- **dm:** WhatsApp-style chat bubbles, conversation header, date separators ([#762](https://github.com/arbicity/ARBI-frontend/pull/762))
|
|
22
|
+
|
|
23
|
+
### 🩹 Fixes
|
|
24
|
+
|
|
25
|
+
- **pdf:** Polyfill the bleeding-edge TC39 APIs pdfjs 5.x relies on ([#755](https://github.com/arbicity/ARBI-frontend/pull/755))
|
|
26
|
+
- **grid:** Filter task_update transactions to rows the grid actually has ([#756](https://github.com/arbicity/ARBI-frontend/pull/756))
|
|
27
|
+
- **auth:** Gate protected queries on token+user, not token alone ([#757](https://github.com/arbicity/ARBI-frontend/pull/757))
|
|
28
|
+
- **mcp:** Read 'sk' JWT claim, not 'session_key', in openAllWorkspacesForSession ([#758](https://github.com/arbicity/ARBI-frontend/pull/758))
|
|
29
|
+
- **docviewer:** Treat *.md uploads as markdown docs; restore Edit/Cancel toggle ([#760](https://github.com/arbicity/ARBI-frontend/pull/760))
|
|
30
|
+
- **ui:** Restore logout modal with active sessions list ([#768](https://github.com/arbicity/ARBI-frontend/pull/768))
|
|
31
|
+
- **sdk,cli:** Keep PA-agent CLI on the same session across workspace touches ([#769](https://github.com/arbicity/ARBI-frontend/pull/769))
|
|
32
|
+
- **sdk:** Restore userExtId and always call /open in session fast-path ([#771](https://github.com/arbicity/ARBI-frontend/pull/771))
|
|
33
|
+
|
|
34
|
+
### 💅 Refactors
|
|
35
|
+
|
|
36
|
+
- Remove obsolete isDelegatedSession state ([#765](https://github.com/arbicity/ARBI-frontend/pull/765), [#766](https://github.com/arbicity/ARBI-frontend/pull/766))
|
|
37
|
+
|
|
38
|
+
### 🏡 Chore
|
|
39
|
+
|
|
40
|
+
- **lint:** Zero warnings — drop unused userSettings hook in Dashboard, extract UserSettings experimental section ([#753](https://github.com/arbicity/ARBI-frontend/pull/753))
|
|
41
|
+
- **ci:** Run SDK unit tests on every PR ([#770](https://github.com/arbicity/ARBI-frontend/pull/770))
|
|
42
|
+
|
|
3
43
|
## v0.3.65
|
|
4
44
|
|
|
5
45
|
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.3.64...HEAD)
|
package/dist/index.js
CHANGED
|
@@ -113,9 +113,9 @@ function getCachedWorkspaceName(id) {
|
|
|
113
113
|
return null;
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
-
function updateCompletionCache(
|
|
116
|
+
function updateCompletionCache(workspaces4) {
|
|
117
117
|
const cache = {
|
|
118
|
-
workspaces:
|
|
118
|
+
workspaces: workspaces4.filter((w) => w.external_id).map((w) => ({ id: w.external_id, name: w.name ?? "" })),
|
|
119
119
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
120
120
|
};
|
|
121
121
|
const filePath = getCacheFile();
|
|
@@ -3694,7 +3694,7 @@ function getLatestVersion(skipCache = false) {
|
|
|
3694
3694
|
}
|
|
3695
3695
|
}
|
|
3696
3696
|
function getCurrentVersion() {
|
|
3697
|
-
return "0.3.
|
|
3697
|
+
return "0.3.67";
|
|
3698
3698
|
}
|
|
3699
3699
|
function readChangelog(fromVersion, toVersion) {
|
|
3700
3700
|
try {
|
|
@@ -3747,17 +3747,17 @@ function showChangelog(fromVersion, toVersion) {
|
|
|
3747
3747
|
async function checkForUpdates(autoUpdate) {
|
|
3748
3748
|
try {
|
|
3749
3749
|
const latest = getLatestVersion();
|
|
3750
|
-
if (!latest || latest === "0.3.
|
|
3750
|
+
if (!latest || latest === "0.3.67") return;
|
|
3751
3751
|
if (autoUpdate) {
|
|
3752
3752
|
warn(`
|
|
3753
|
-
Your arbi version is out of date (${"0.3.
|
|
3753
|
+
Your arbi version is out of date (${"0.3.67"} \u2192 ${latest}). Updating...`);
|
|
3754
3754
|
child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
|
|
3755
|
-
showChangelog("0.3.
|
|
3755
|
+
showChangelog("0.3.67", 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.3.
|
|
3760
|
+
Your arbi version is out of date (${"0.3.67"} \u2192 ${latest}).
|
|
3761
3761
|
Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
3762
3762
|
);
|
|
3763
3763
|
}
|
|
@@ -3789,10 +3789,10 @@ function markNagShown(latest) {
|
|
|
3789
3789
|
function hintUpdateOnError() {
|
|
3790
3790
|
try {
|
|
3791
3791
|
const cached = readCache();
|
|
3792
|
-
if (!cached || cached.latest === "0.3.
|
|
3792
|
+
if (!cached || cached.latest === "0.3.67") return;
|
|
3793
3793
|
if (!shouldShowNag(cached.latest)) return;
|
|
3794
3794
|
warn(
|
|
3795
|
-
`Your arbi version is out of date (${"0.3.
|
|
3795
|
+
`Your arbi version is out of date (${"0.3.67"} \u2192 ${cached.latest}). Run "arbi update".`
|
|
3796
3796
|
);
|
|
3797
3797
|
markNagShown(cached.latest);
|
|
3798
3798
|
} catch {
|
|
@@ -4353,8 +4353,8 @@ Open this URL in your browser:
|
|
|
4353
4353
|
})();
|
|
4354
4354
|
if (!opts.json) success(`Logged in as ${email}`);
|
|
4355
4355
|
clearChatSession();
|
|
4356
|
-
const { data:
|
|
4357
|
-
const wsList =
|
|
4356
|
+
const { data: workspaces4 } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
4357
|
+
const wsList = workspaces4 || [];
|
|
4358
4358
|
updateCompletionCache(wsList);
|
|
4359
4359
|
const memberWorkspaces = wsList.filter(
|
|
4360
4360
|
(ws) => ws.users?.some((u) => u.user.email === email)
|
|
@@ -4688,8 +4688,8 @@ async function loginAfterRegister(config, email, password2, { json = false } = {
|
|
|
4688
4688
|
try {
|
|
4689
4689
|
const { arbi, loginResult } = await sdk.performPasswordLogin(config, email, password2, store);
|
|
4690
4690
|
if (!json) success(`Logged in as ${email}`);
|
|
4691
|
-
const { data:
|
|
4692
|
-
const wsList =
|
|
4691
|
+
const { data: workspaces4 } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
4692
|
+
const wsList = workspaces4 || [];
|
|
4693
4693
|
updateCompletionCache(wsList);
|
|
4694
4694
|
const memberWorkspaces = wsList.filter((ws) => ws.users?.some((u) => u.user.email === email));
|
|
4695
4695
|
let selectedWorkspace;
|
|
@@ -4842,8 +4842,12 @@ function registerWorkspacesCommand(program2) {
|
|
|
4842
4842
|
}
|
|
4843
4843
|
if (opts.json) {
|
|
4844
4844
|
const selectedId2 = getConfig()?.selectedWorkspaceId ?? null;
|
|
4845
|
+
const myEmail = store.requireCredentials().email;
|
|
4845
4846
|
const out = data.map((w) => {
|
|
4846
|
-
const
|
|
4847
|
+
const myRow = w.users?.find(
|
|
4848
|
+
(u) => u?.user?.email === myEmail
|
|
4849
|
+
);
|
|
4850
|
+
const role = myRow?.role ?? null;
|
|
4847
4851
|
return {
|
|
4848
4852
|
id: w.external_id,
|
|
4849
4853
|
name: w.name,
|
|
@@ -4884,10 +4888,16 @@ function registerWorkspacesCommand(program2) {
|
|
|
4884
4888
|
{
|
|
4885
4889
|
header: "ROLE",
|
|
4886
4890
|
width: 12,
|
|
4887
|
-
// `common` (italics dimmed) for memberless rows the caller
|
|
4888
|
-
// see only because it's a deployment-wide workspace.
|
|
4889
|
-
//
|
|
4890
|
-
|
|
4891
|
+
// `common` (italics dimmed) for memberless rows the caller
|
|
4892
|
+
// can see only because it's a deployment-wide workspace.
|
|
4893
|
+
// Match by the caller's email so we render *our* role, not
|
|
4894
|
+
// whichever membership happens to come first in the array.
|
|
4895
|
+
value: (r) => {
|
|
4896
|
+
const myRow = r.users?.find(
|
|
4897
|
+
(u) => u?.user?.email === store.requireCredentials().email
|
|
4898
|
+
);
|
|
4899
|
+
return myRow?.role ?? "common";
|
|
4900
|
+
}
|
|
4891
4901
|
}
|
|
4892
4902
|
],
|
|
4893
4903
|
data
|
|
@@ -5359,7 +5369,13 @@ function registerDocsCommand(program2) {
|
|
|
5359
5369
|
"Write output to a file instead of stdout. Extension determines the format when combined with --ids/--json/--csv (default: csv with doc_id, file_name, folder, status)"
|
|
5360
5370
|
).action(
|
|
5361
5371
|
(opts) => runAction(async () => {
|
|
5362
|
-
const { arbi } = await resolveWorkspace(opts.workspace);
|
|
5372
|
+
const { arbi, workspaceId } = await resolveWorkspace(opts.workspace);
|
|
5373
|
+
let workspaceName = null;
|
|
5374
|
+
try {
|
|
5375
|
+
const list = await sdk.workspaces.listWorkspaces(arbi);
|
|
5376
|
+
workspaceName = list.find((w) => w.external_id === workspaceId)?.name ?? null;
|
|
5377
|
+
} catch {
|
|
5378
|
+
}
|
|
5363
5379
|
const fields = opts.lite ? "lite" : void 0;
|
|
5364
5380
|
const hardLimit = opts.limit ? parseInt(opts.limit, 10) : void 0;
|
|
5365
5381
|
const needsSort = !!(opts.sort && opts.sort !== "status");
|
|
@@ -5416,15 +5432,27 @@ function registerDocsCommand(program2) {
|
|
|
5416
5432
|
}
|
|
5417
5433
|
if (totalFetched === 0 && data.length === 0) {
|
|
5418
5434
|
if (opts.json) {
|
|
5419
|
-
|
|
5420
|
-
|
|
5435
|
+
const emptyPayload = JSON.stringify(
|
|
5436
|
+
{
|
|
5437
|
+
workspace: { external_id: workspaceId, name: workspaceName },
|
|
5438
|
+
documents: []
|
|
5439
|
+
},
|
|
5440
|
+
null,
|
|
5441
|
+
opts.output ? 2 : 0
|
|
5442
|
+
);
|
|
5443
|
+
if (opts.output) fs5.writeFileSync(opts.output, emptyPayload + "\n");
|
|
5444
|
+
else console.log(emptyPayload);
|
|
5421
5445
|
} else if (opts.ids) {
|
|
5422
5446
|
if (opts.output) fs5.writeFileSync(opts.output, "");
|
|
5423
5447
|
} else if (opts.csv) {
|
|
5424
5448
|
if (opts.output) fs5.writeFileSync(opts.output, csvHeader + "\n");
|
|
5425
5449
|
} else if (opts.count) {
|
|
5450
|
+
const wsLabel2 = workspaceName ? `${workspaceName} (${workspaceId})` : workspaceId;
|
|
5451
|
+
console.log(chalk2__default.default.dim(`Workspace: ${wsLabel2}`));
|
|
5426
5452
|
console.log("0");
|
|
5427
5453
|
} else {
|
|
5454
|
+
const wsLabel2 = workspaceName ? `${workspaceName} (${workspaceId})` : workspaceId;
|
|
5455
|
+
console.log(chalk2__default.default.dim(`Workspace: ${wsLabel2}`));
|
|
5428
5456
|
console.log("No documents found.");
|
|
5429
5457
|
}
|
|
5430
5458
|
return;
|
|
@@ -5466,6 +5494,8 @@ function registerDocsCommand(program2) {
|
|
|
5466
5494
|
}).length;
|
|
5467
5495
|
const totalPages = data.reduce((sum, d) => sum + (d.n_pages ?? 0), 0);
|
|
5468
5496
|
const totalTokens = data.reduce((sum, d) => sum + (d.tokens ?? 0), 0);
|
|
5497
|
+
const wsLabel2 = workspaceName ? `${workspaceName} (${workspaceId})` : workspaceId;
|
|
5498
|
+
console.log(chalk2__default.default.dim(`Workspace: ${wsLabel2}`));
|
|
5469
5499
|
console.log(chalk2__default.default.bold(`Total: ${data.length} documents`));
|
|
5470
5500
|
for (const [status2, count] of Object.entries(counts).sort()) {
|
|
5471
5501
|
const colorFn = statusColor(status2);
|
|
@@ -5491,7 +5521,11 @@ function registerDocsCommand(program2) {
|
|
|
5491
5521
|
return;
|
|
5492
5522
|
}
|
|
5493
5523
|
if (opts.json) {
|
|
5494
|
-
|
|
5524
|
+
const payload = {
|
|
5525
|
+
workspace: { external_id: workspaceId, name: workspaceName },
|
|
5526
|
+
documents: data
|
|
5527
|
+
};
|
|
5528
|
+
writeOut(JSON.stringify(payload, null, opts.output ? 2 : 0), "json");
|
|
5495
5529
|
return;
|
|
5496
5530
|
}
|
|
5497
5531
|
if (opts.csv || opts.output && !opts.ids && !opts.json) {
|
|
@@ -5502,6 +5536,8 @@ function registerDocsCommand(program2) {
|
|
|
5502
5536
|
writeOut(lines.join("\n"), "csv");
|
|
5503
5537
|
return;
|
|
5504
5538
|
}
|
|
5539
|
+
const wsLabel = workspaceName ? `${workspaceName} (${workspaceId})` : workspaceId;
|
|
5540
|
+
console.log(chalk2__default.default.dim(`Workspace: ${wsLabel}`));
|
|
5505
5541
|
console.log(chalk2__default.default.dim(`${data.length} documents
|
|
5506
5542
|
`));
|
|
5507
5543
|
printTable(
|
|
@@ -6335,7 +6371,10 @@ function registerUploadCommand(program2) {
|
|
|
6335
6371
|
).option(
|
|
6336
6372
|
"-s, --s3",
|
|
6337
6373
|
"Upload via the direct-to-MinIO flow (SecretBox on the client, presigned PUT)"
|
|
6338
|
-
).option("--folder <name>", "Backend folder for plain-file uploads (direct upload only)").
|
|
6374
|
+
).option("--folder <name>", "Backend folder for plain-file uploads (direct upload only)").option(
|
|
6375
|
+
"--wp-type <type>",
|
|
6376
|
+
"Work product type: source (default), skill, memory, artifact, webpage. Use --wp-type skill with --folder skills/<slug> to upload a SKILL.md."
|
|
6377
|
+
).action(
|
|
6339
6378
|
(paths, opts) => runAction(async () => {
|
|
6340
6379
|
const isManifestMode = Boolean(opts.manifest || opts.log || opts.resume);
|
|
6341
6380
|
const inputPaths = paths ?? [];
|
|
@@ -6492,7 +6531,10 @@ function registerUploadCommand(program2) {
|
|
|
6492
6531
|
summary.totalFiles += 1;
|
|
6493
6532
|
continue;
|
|
6494
6533
|
}
|
|
6495
|
-
const result = await sdk.documentsNode.uploadLocalFile(auth, filePath
|
|
6534
|
+
const result = await sdk.documentsNode.uploadLocalFile(auth, filePath, {
|
|
6535
|
+
folder: opts.folder,
|
|
6536
|
+
wpType: opts.wpType
|
|
6537
|
+
});
|
|
6496
6538
|
if (!opts.json) {
|
|
6497
6539
|
success(`Uploaded: ${result.fileName} (${(result.doc_ext_ids ?? []).join(", ")})`);
|
|
6498
6540
|
if (result.skipped && result.skipped.length > 0) {
|
|
@@ -8947,8 +8989,8 @@ async function runQuickstart(url) {
|
|
|
8947
8989
|
try {
|
|
8948
8990
|
const { arbi, loginResult } = await sdk.performPasswordLogin(config, email, password2, store);
|
|
8949
8991
|
success(`Logged in as ${email}`);
|
|
8950
|
-
const { data:
|
|
8951
|
-
const wsList =
|
|
8992
|
+
const { data: workspaces4 } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
8993
|
+
const wsList = workspaces4 || [];
|
|
8952
8994
|
const memberWorkspaces = wsList.filter((ws) => ws.users?.some((u) => u.user.email === email));
|
|
8953
8995
|
const userProjects = await sdk.projects.listProjects(arbi);
|
|
8954
8996
|
const defaultProjectExtId = userProjects[0]?.external_id;
|
|
@@ -10040,6 +10082,142 @@ function registerAuthCommand(program2) {
|
|
|
10040
10082
|
await auth.commands.find((c) => c.name() === "profile").parseAsync(tail, { from: "user" });
|
|
10041
10083
|
});
|
|
10042
10084
|
}
|
|
10085
|
+
function extractSlugFromFrontmatter(body) {
|
|
10086
|
+
const normalized = body.replace(/\r\n/g, "\n");
|
|
10087
|
+
if (!normalized.startsWith("---\n")) return null;
|
|
10088
|
+
const end = normalized.indexOf("\n---", 4);
|
|
10089
|
+
if (end < 0) return null;
|
|
10090
|
+
const block = normalized.slice(4, end);
|
|
10091
|
+
for (const line of block.split("\n")) {
|
|
10092
|
+
const m = /^name:\s*(.+?)\s*$/.exec(line);
|
|
10093
|
+
if (m) {
|
|
10094
|
+
return m[1].toLowerCase().replace(/['"]/g, "").replace(/[_\s]+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
10095
|
+
}
|
|
10096
|
+
}
|
|
10097
|
+
return null;
|
|
10098
|
+
}
|
|
10099
|
+
async function loadSkillSource(source) {
|
|
10100
|
+
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
10101
|
+
const res = await fetch(source);
|
|
10102
|
+
if (!res.ok) {
|
|
10103
|
+
throw new Error(`Failed to fetch ${source}: HTTP ${res.status} ${res.statusText}`);
|
|
10104
|
+
}
|
|
10105
|
+
return await res.text();
|
|
10106
|
+
}
|
|
10107
|
+
const stat = fs5.statSync(source);
|
|
10108
|
+
if (stat.isDirectory()) {
|
|
10109
|
+
throw new Error(
|
|
10110
|
+
`${source} is a directory. Pass a single SKILL.md file, or use \`\`arbi upload --folder skills/<slug> --wp-type skill\`\` for multi-file skills.`
|
|
10111
|
+
);
|
|
10112
|
+
}
|
|
10113
|
+
return fs5.readFileSync(source, "utf8");
|
|
10114
|
+
}
|
|
10115
|
+
function registerSkillsCommand(program2) {
|
|
10116
|
+
const skills = program2.command("skills").description("Skills: list, show");
|
|
10117
|
+
skills.command("list").description("List user-invocable skills in the active workspace").option("--json", "Output as JSON").option("--include-hidden", "Include skills with user-invocable: false").action(
|
|
10118
|
+
(opts) => runAction(async () => {
|
|
10119
|
+
const { arbi } = await resolveWorkspace();
|
|
10120
|
+
const list = await sdk.assistant.listSkills(arbi, {
|
|
10121
|
+
includeHidden: opts.includeHidden
|
|
10122
|
+
});
|
|
10123
|
+
if (opts.json) {
|
|
10124
|
+
console.log(JSON.stringify(list, null, 2));
|
|
10125
|
+
return;
|
|
10126
|
+
}
|
|
10127
|
+
if (list.length === 0) {
|
|
10128
|
+
process.stderr.write(
|
|
10129
|
+
"No skills in this workspace yet. Upload a SKILL.md with wp_type=skill to add one.\n"
|
|
10130
|
+
);
|
|
10131
|
+
return;
|
|
10132
|
+
}
|
|
10133
|
+
printTable(
|
|
10134
|
+
[
|
|
10135
|
+
{ header: "SLUG", width: 20, value: (r) => r.slug ?? "" },
|
|
10136
|
+
{ header: "NAME", width: 24, value: (r) => r.name ?? "" },
|
|
10137
|
+
{
|
|
10138
|
+
header: "TYPE",
|
|
10139
|
+
width: 10,
|
|
10140
|
+
value: (r) => r.skill_type ?? "markdown"
|
|
10141
|
+
},
|
|
10142
|
+
{
|
|
10143
|
+
header: "ARGS",
|
|
10144
|
+
width: 20,
|
|
10145
|
+
value: (r) => r.arg_hint ?? ""
|
|
10146
|
+
},
|
|
10147
|
+
{
|
|
10148
|
+
header: "DESCRIPTION",
|
|
10149
|
+
width: 40,
|
|
10150
|
+
value: (r) => r.description ?? ""
|
|
10151
|
+
}
|
|
10152
|
+
],
|
|
10153
|
+
list
|
|
10154
|
+
);
|
|
10155
|
+
})()
|
|
10156
|
+
);
|
|
10157
|
+
skills.command("install <source>").description(
|
|
10158
|
+
"Install a skill from a URL or local path (SKILL.md). Slug derived from frontmatter unless --slug is given."
|
|
10159
|
+
).option("--slug <slug>", "Override the slug (default: derived from frontmatter name)").option("--json", "Output the upload result as JSON").action(
|
|
10160
|
+
(source, opts) => runAction(async () => {
|
|
10161
|
+
const ctx = await resolveWorkspace();
|
|
10162
|
+
const authHeaders = {
|
|
10163
|
+
baseUrl: ctx.config.baseUrl,
|
|
10164
|
+
accessToken: ctx.accessToken
|
|
10165
|
+
};
|
|
10166
|
+
const body = await loadSkillSource(source);
|
|
10167
|
+
const slug = opts.slug ?? extractSlugFromFrontmatter(body) ?? (() => {
|
|
10168
|
+
process.stderr.write(
|
|
10169
|
+
"Could not derive slug: no --slug flag and no ``name:`` in frontmatter.\nAdd a frontmatter block like:\n\n ---\n name: my-skill\n description: \u2026\n ---\n\nor pass ``--slug my-skill`` explicitly.\n"
|
|
10170
|
+
);
|
|
10171
|
+
process.exit(1);
|
|
10172
|
+
})();
|
|
10173
|
+
const blob = new Blob([body], { type: "text/markdown" });
|
|
10174
|
+
const result = await sdk.documents.uploadFile(authHeaders, blob, "SKILL.md", {
|
|
10175
|
+
folder: `skills/${slug}`,
|
|
10176
|
+
wpType: "skill"
|
|
10177
|
+
});
|
|
10178
|
+
if (opts.json) {
|
|
10179
|
+
console.log(JSON.stringify({ slug, ...result }, null, 2));
|
|
10180
|
+
return;
|
|
10181
|
+
}
|
|
10182
|
+
console.log(bold(`Installed skill: ${slug}`));
|
|
10183
|
+
console.log(dim(`source: ${source}`));
|
|
10184
|
+
console.log(dim(`folder: skills/${slug}`));
|
|
10185
|
+
console.log(
|
|
10186
|
+
dim("Backend frontmatter loader picks it up on the next /v1/assistant/skills call.")
|
|
10187
|
+
);
|
|
10188
|
+
})()
|
|
10189
|
+
);
|
|
10190
|
+
skills.command("show <slug>").description("Show a skill's SKILL.md body (read-only)").option("--json", "Output as JSON (includes metadata)").action(
|
|
10191
|
+
(slug, opts) => runAction(async () => {
|
|
10192
|
+
const ctx = await resolveWorkspace();
|
|
10193
|
+
const list = await sdk.assistant.listSkills(ctx.arbi, { includeHidden: true });
|
|
10194
|
+
const skill = list.find((s) => s.slug === slug || s.name === slug);
|
|
10195
|
+
if (!skill) {
|
|
10196
|
+
process.stderr.write(
|
|
10197
|
+
`No skill matching "${slug}" in this workspace. Try \`arbi skills list\`.
|
|
10198
|
+
`
|
|
10199
|
+
);
|
|
10200
|
+
process.exit(1);
|
|
10201
|
+
}
|
|
10202
|
+
const authHeaders = {
|
|
10203
|
+
baseUrl: ctx.config.baseUrl,
|
|
10204
|
+
accessToken: ctx.accessToken
|
|
10205
|
+
};
|
|
10206
|
+
const dlRes = await sdk.documents.downloadDocument(authHeaders, skill.doc_ext_id);
|
|
10207
|
+
const body = dlRes.ok ? await dlRes.text() : "";
|
|
10208
|
+
if (opts.json) {
|
|
10209
|
+
console.log(JSON.stringify({ ...skill, body }, null, 2));
|
|
10210
|
+
return;
|
|
10211
|
+
}
|
|
10212
|
+
console.log(bold(`${skill.name} (${skill.slug})`));
|
|
10213
|
+
if (skill.description) console.log(dim(skill.description));
|
|
10214
|
+
if (skill.arg_hint) console.log(dim(`args: ${skill.arg_hint}`));
|
|
10215
|
+
console.log(dim(`type: ${skill.skill_type} doc: ${skill.doc_ext_id}`));
|
|
10216
|
+
console.log("");
|
|
10217
|
+
console.log(body);
|
|
10218
|
+
})()
|
|
10219
|
+
);
|
|
10220
|
+
}
|
|
10043
10221
|
|
|
10044
10222
|
// src/index.ts
|
|
10045
10223
|
console.debug = () => {
|
|
@@ -10050,7 +10228,7 @@ console.info = (...args) => {
|
|
|
10050
10228
|
_origInfo(...args);
|
|
10051
10229
|
};
|
|
10052
10230
|
var program = new commander.Command();
|
|
10053
|
-
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.
|
|
10231
|
+
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.3.67").showHelpAfterError(true).showSuggestionAfterError(true);
|
|
10054
10232
|
registerConfigCommand(program);
|
|
10055
10233
|
registerLoginCommand(program);
|
|
10056
10234
|
registerRegisterCommand(program);
|
|
@@ -10087,6 +10265,7 @@ registerProjectCommand(program);
|
|
|
10087
10265
|
registerFilesCommand(program);
|
|
10088
10266
|
registerUsageCommand(program);
|
|
10089
10267
|
registerAuthCommand(program);
|
|
10268
|
+
registerSkillsCommand(program);
|
|
10090
10269
|
applyHelpGroups(program, {
|
|
10091
10270
|
"Getting started:": [
|
|
10092
10271
|
"quickstart",
|