vellum-cli 0.3.0 → 0.3.2
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/README.md +25 -0
- package/dist/index.js +199 -300
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -71,6 +71,31 @@ vellum push artifact.html --page-id pg_123 --json
|
|
|
71
71
|
On success it prints the new version number, the human view URL, and the raw
|
|
72
72
|
URL. With `--json` it prints the server's `CreateVersionResponse` verbatim.
|
|
73
73
|
|
|
74
|
+
### `vellum markup <page-id>`
|
|
75
|
+
|
|
76
|
+
Pin a comment to a passage of a published document. The `--quote` text must
|
|
77
|
+
appear verbatim in the document; the viewer highlights it and links your note to
|
|
78
|
+
the highlight. Without `--version`, the page's current version is used.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# anchor a note to a passage
|
|
82
|
+
vellum markup pg_123 --quote "Q3 dashboard" --body "tighten this headline"
|
|
83
|
+
|
|
84
|
+
# pipe the note in on stdin instead of --body
|
|
85
|
+
echo "tighten this headline" | vellum markup pg_123 --quote "Q3 dashboard"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The CLI checks the quote is anchorable before posting; pass `--force` to post
|
|
89
|
+
anyway, or `--json` for the raw response.
|
|
90
|
+
|
|
91
|
+
### `vellum whoami`
|
|
92
|
+
|
|
93
|
+
Show the identity the CLI is authenticated as for a server.
|
|
94
|
+
|
|
95
|
+
### `vellum logout`
|
|
96
|
+
|
|
97
|
+
Revoke this machine's stored token server-side and forget it locally.
|
|
98
|
+
|
|
74
99
|
## Development
|
|
75
100
|
|
|
76
101
|
From the repo root, Bun runs the TypeScript source directly (no build):
|
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ async function clearToken(baseUrl) {
|
|
|
61
61
|
return existing;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// src/commands/
|
|
64
|
+
// src/commands/archive.ts
|
|
65
65
|
import { parseArgs } from "node:util";
|
|
66
66
|
// ../core/src/client.ts
|
|
67
67
|
class VellumApiError extends Error {
|
|
@@ -119,6 +119,30 @@ class VellumClient {
|
|
|
119
119
|
await this.fail(res);
|
|
120
120
|
return await res.json();
|
|
121
121
|
}
|
|
122
|
+
async listPages(opts = {}) {
|
|
123
|
+
const url = new URL(`${this.baseUrl}/v1/pages`);
|
|
124
|
+
if (opts.archived)
|
|
125
|
+
url.searchParams.set("status", "archived");
|
|
126
|
+
else if (opts.all)
|
|
127
|
+
url.searchParams.set("include", "archived");
|
|
128
|
+
const res = await this.fetchImpl(url, { headers: this.authHeaders() });
|
|
129
|
+
if (!res.ok)
|
|
130
|
+
await this.fail(res);
|
|
131
|
+
return await res.json();
|
|
132
|
+
}
|
|
133
|
+
async archivePage(pageId) {
|
|
134
|
+
return this.setArchived(pageId, true);
|
|
135
|
+
}
|
|
136
|
+
async unarchivePage(pageId) {
|
|
137
|
+
return this.setArchived(pageId, false);
|
|
138
|
+
}
|
|
139
|
+
async setArchived(pageId, archived) {
|
|
140
|
+
const action = archived ? "archive" : "unarchive";
|
|
141
|
+
const res = await this.fetchImpl(`${this.baseUrl}/v1/pages/${encodeURIComponent(pageId)}/${action}`, { method: "POST", headers: this.authHeaders() });
|
|
142
|
+
if (!res.ok)
|
|
143
|
+
await this.fail(res);
|
|
144
|
+
return await res.json();
|
|
145
|
+
}
|
|
122
146
|
async createComment(pageId, opts) {
|
|
123
147
|
const res = await this.fetchImpl(`${this.baseUrl}/v1/pages/${encodeURIComponent(pageId)}/comments`, {
|
|
124
148
|
method: "POST",
|
|
@@ -134,21 +158,6 @@ class VellumClient {
|
|
|
134
158
|
await this.fail(res);
|
|
135
159
|
return await res.json();
|
|
136
160
|
}
|
|
137
|
-
async listComments(pageId, opts = {}) {
|
|
138
|
-
const url = new URL(`${this.baseUrl}/v1/pages/${encodeURIComponent(pageId)}/comments`);
|
|
139
|
-
if (opts.versionId)
|
|
140
|
-
url.searchParams.set("version_id", opts.versionId);
|
|
141
|
-
const res = await this.fetchImpl(url, { headers: this.authHeaders() });
|
|
142
|
-
if (!res.ok)
|
|
143
|
-
await this.fail(res);
|
|
144
|
-
return await res.json();
|
|
145
|
-
}
|
|
146
|
-
async resolveComment(commentId) {
|
|
147
|
-
const res = await this.fetchImpl(`${this.baseUrl}/v1/comments/${encodeURIComponent(commentId)}/resolve`, { method: "POST", headers: this.authHeaders() });
|
|
148
|
-
if (!res.ok)
|
|
149
|
-
await this.fail(res);
|
|
150
|
-
return await res.json();
|
|
151
|
-
}
|
|
152
161
|
async startCliAuth() {
|
|
153
162
|
const res = await this.fetchImpl(`${this.baseUrl}/v1/cli/auth/start`, {
|
|
154
163
|
method: "POST",
|
|
@@ -186,143 +195,159 @@ class VellumClient {
|
|
|
186
195
|
await this.fail(res);
|
|
187
196
|
}
|
|
188
197
|
}
|
|
189
|
-
// src/commands/
|
|
190
|
-
|
|
198
|
+
// src/commands/archive.ts
|
|
199
|
+
function help(verb) {
|
|
200
|
+
const what = verb === "archive" ? "hide a page from the gallery and make it read-only" : "restore an archived page to live";
|
|
201
|
+
return `vellum ${verb} — ${what}
|
|
191
202
|
|
|
192
203
|
Usage:
|
|
193
|
-
vellum
|
|
204
|
+
vellum ${verb} <page-id> [options]
|
|
194
205
|
|
|
195
|
-
|
|
196
|
-
are
|
|
206
|
+
${verb === "archive" ? `Archiving keeps the bytes, versions, comments, and URLs intact — new
|
|
207
|
+
versions and comments are paused until you unarchive. Owner/admin only.` : `Unarchiving restores the page to the gallery and re-opens it for new
|
|
208
|
+
versions and comments. Owner/admin only.`}
|
|
197
209
|
|
|
198
210
|
Options:
|
|
199
|
-
--open Show only unresolved threads
|
|
200
|
-
--version <id> Only comments anchored to this version id
|
|
201
211
|
--url <url> Server base URL (env: VELLUM_URL)
|
|
212
|
+
--api-key <key> Shared API key (env: VELLUM_API_KEY)
|
|
202
213
|
--json Print the raw JSON response
|
|
203
214
|
-h, --help Show this help`;
|
|
204
|
-
var truncate = (s, n) => s.length > n ? `${s.slice(0, n - 1)}…` : s;
|
|
205
|
-
var oneLine = (s) => s.replace(/\s+/g, " ").trim();
|
|
206
|
-
function printComment(c, indent) {
|
|
207
|
-
const who = c.author_email ?? c.author_name ?? "(unknown)";
|
|
208
|
-
const state = c.resolved ? "resolved" : "open";
|
|
209
|
-
console.log(`${indent}${c.id} [${state}] ${who}`);
|
|
210
|
-
if (c.anchor?.exact) {
|
|
211
|
-
console.log(`${indent} on “${truncate(oneLine(c.anchor.exact), 70)}”`);
|
|
212
|
-
}
|
|
213
|
-
console.log(`${indent} ${truncate(oneLine(c.body), 100)}`);
|
|
214
|
-
for (const reply of c.replies ?? []) {
|
|
215
|
-
printComment(reply, `${indent} `);
|
|
216
|
-
}
|
|
217
215
|
}
|
|
218
|
-
async function
|
|
216
|
+
async function run(verb, argv) {
|
|
219
217
|
const { values, positionals } = parseArgs({
|
|
220
218
|
args: argv,
|
|
221
219
|
allowPositionals: true,
|
|
222
220
|
options: {
|
|
223
|
-
open: { type: "boolean", default: false },
|
|
224
|
-
version: { type: "string" },
|
|
225
221
|
url: { type: "string" },
|
|
222
|
+
"api-key": { type: "string" },
|
|
226
223
|
json: { type: "boolean", default: false },
|
|
227
224
|
help: { type: "boolean", short: "h", default: false }
|
|
228
225
|
}
|
|
229
226
|
});
|
|
230
227
|
if (values.help) {
|
|
231
|
-
console.log(
|
|
228
|
+
console.log(help(verb));
|
|
232
229
|
return 0;
|
|
233
230
|
}
|
|
234
231
|
const pageId = positionals[0];
|
|
235
232
|
if (!pageId) {
|
|
236
233
|
console.error(`Error: missing <page-id>.
|
|
237
234
|
`);
|
|
238
|
-
console.error(
|
|
235
|
+
console.error(help(verb));
|
|
239
236
|
return 1;
|
|
240
237
|
}
|
|
241
|
-
const
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (comments.length === 0) {
|
|
253
|
-
console.log(values.open ? "No open comments." : "No comments.");
|
|
238
|
+
const flags = { url: values.url, apiKey: values["api-key"] };
|
|
239
|
+
const baseUrl = resolveBaseUrl(flags);
|
|
240
|
+
const credential = await resolveCredential(flags, baseUrl);
|
|
241
|
+
const client2 = new VellumClient({ baseUrl, ...credential });
|
|
242
|
+
try {
|
|
243
|
+
const res = verb === "archive" ? await client2.archivePage(pageId) : await client2.unarchivePage(pageId);
|
|
244
|
+
if (values.json) {
|
|
245
|
+
console.log(JSON.stringify(res, null, 2));
|
|
246
|
+
} else {
|
|
247
|
+
console.log(`✓ ${verb}d ${res.id}`);
|
|
248
|
+
}
|
|
254
249
|
return 0;
|
|
250
|
+
} catch (err) {
|
|
251
|
+
if (err instanceof VellumApiError && err.status === 401) {
|
|
252
|
+
console.error(`Error: ${verb} requires the owner API key. Set VELLUM_API_KEY or pass --api-key.`);
|
|
253
|
+
return 1;
|
|
254
|
+
}
|
|
255
|
+
if (err instanceof VellumApiError && err.status === 404) {
|
|
256
|
+
console.error(`Error: no page found at ${pageId}.`);
|
|
257
|
+
return 1;
|
|
258
|
+
}
|
|
259
|
+
throw err;
|
|
255
260
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return
|
|
261
|
+
}
|
|
262
|
+
function archiveCommand(argv) {
|
|
263
|
+
return run("archive", argv);
|
|
264
|
+
}
|
|
265
|
+
function unarchiveCommand(argv) {
|
|
266
|
+
return run("unarchive", argv);
|
|
259
267
|
}
|
|
260
268
|
|
|
261
|
-
// src/commands/
|
|
269
|
+
// src/commands/list.ts
|
|
262
270
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
263
|
-
var
|
|
271
|
+
var HELP = `vellum list — list your artifacts (owner/admin only)
|
|
264
272
|
|
|
265
273
|
Usage:
|
|
266
|
-
vellum
|
|
274
|
+
vellum list [options]
|
|
267
275
|
|
|
268
|
-
|
|
269
|
-
|
|
276
|
+
By default only live pages are shown. Use --archived for archived-only, or
|
|
277
|
+
--all for both. Listing requires the owner API key (VELLUM_API_KEY / --api-key).
|
|
270
278
|
|
|
271
279
|
Options:
|
|
272
|
-
--
|
|
280
|
+
--archived Show only archived pages
|
|
281
|
+
--all Show both live and archived pages
|
|
273
282
|
--url <url> Server base URL (env: VELLUM_URL)
|
|
283
|
+
--api-key <key> Shared API key (env: VELLUM_API_KEY)
|
|
284
|
+
--json Print the raw JSON response
|
|
274
285
|
-h, --help Show this help`;
|
|
275
|
-
function
|
|
276
|
-
if (
|
|
277
|
-
return
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
286
|
+
function cell(value, width) {
|
|
287
|
+
if (value.length > width)
|
|
288
|
+
return `${value.slice(0, width - 1)}…`;
|
|
289
|
+
return value.padEnd(width);
|
|
290
|
+
}
|
|
291
|
+
function renderTable(pages) {
|
|
292
|
+
const lines = [
|
|
293
|
+
`${cell("PAGE", 26)} ${cell("LATEST", 7)} ${cell("VERS", 5)} ${cell("COMM", 5)} TITLE`
|
|
294
|
+
];
|
|
295
|
+
for (const p of pages) {
|
|
296
|
+
const id = p.archived_at ? `${p.id} *` : p.id;
|
|
297
|
+
const latest = p.latest_version != null ? `v${p.latest_version}` : "—";
|
|
298
|
+
lines.push(`${cell(id, 26)} ${cell(latest, 7)} ${cell(String(p.version_count), 5)} ` + `${cell(String(p.comment_count), 5)} ${p.title ?? ""}`.trimEnd());
|
|
299
|
+
}
|
|
300
|
+
return lines.join(`
|
|
301
|
+
`);
|
|
281
302
|
}
|
|
282
|
-
async function
|
|
283
|
-
const { values
|
|
303
|
+
async function listCommand(argv) {
|
|
304
|
+
const { values } = parseArgs2({
|
|
284
305
|
args: argv,
|
|
285
|
-
allowPositionals:
|
|
306
|
+
allowPositionals: false,
|
|
286
307
|
options: {
|
|
287
|
-
|
|
308
|
+
archived: { type: "boolean", default: false },
|
|
309
|
+
all: { type: "boolean", default: false },
|
|
288
310
|
url: { type: "string" },
|
|
311
|
+
"api-key": { type: "string" },
|
|
312
|
+
json: { type: "boolean", default: false },
|
|
289
313
|
help: { type: "boolean", short: "h", default: false }
|
|
290
314
|
}
|
|
291
315
|
});
|
|
292
316
|
if (values.help) {
|
|
293
|
-
console.log(
|
|
317
|
+
console.log(HELP);
|
|
294
318
|
return 0;
|
|
295
319
|
}
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
320
|
+
const flags = { url: values.url, apiKey: values["api-key"] };
|
|
321
|
+
const baseUrl = resolveBaseUrl(flags);
|
|
322
|
+
const credential = await resolveCredential(flags, baseUrl);
|
|
323
|
+
const client2 = new VellumClient({ baseUrl, ...credential });
|
|
324
|
+
try {
|
|
325
|
+
const { pages } = await client2.listPages({
|
|
326
|
+
archived: values.archived,
|
|
327
|
+
all: values.all
|
|
328
|
+
});
|
|
329
|
+
if (values.json) {
|
|
330
|
+
console.log(JSON.stringify(pages, null, 2));
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
if (pages.length === 0) {
|
|
334
|
+
const scope = values.archived ? "archived " : "";
|
|
335
|
+
console.log(`No ${scope}pages.`);
|
|
336
|
+
return 0;
|
|
337
|
+
}
|
|
338
|
+
console.log(renderTable(pages));
|
|
339
|
+
const archivedCount = pages.filter((p) => p.archived_at).length;
|
|
340
|
+
const suffix = archivedCount ? ` (${archivedCount} archived, marked *)` : "";
|
|
341
|
+
console.log(`
|
|
342
|
+
${pages.length} page${pages.length === 1 ? "" : "s"}${suffix}`);
|
|
343
|
+
return 0;
|
|
344
|
+
} catch (err) {
|
|
345
|
+
if (err instanceof VellumApiError && err.status === 401) {
|
|
346
|
+
console.error("Error: list requires the owner API key. Set VELLUM_API_KEY or pass --api-key.");
|
|
308
347
|
return 1;
|
|
309
348
|
}
|
|
349
|
+
throw err;
|
|
310
350
|
}
|
|
311
|
-
const baseUrl = resolveBaseUrl({ url: values.url });
|
|
312
|
-
const client2 = new VellumClient({ baseUrl });
|
|
313
|
-
const page = await client2.getPage(pageId);
|
|
314
|
-
const target = resolveVersion(page, version);
|
|
315
|
-
if (!target) {
|
|
316
|
-
console.error(version != null ? `Error: page has no version ${version}.` : "Error: page has no versions.");
|
|
317
|
-
return 1;
|
|
318
|
-
}
|
|
319
|
-
const res = await fetch(target.raw_url);
|
|
320
|
-
if (!res.ok) {
|
|
321
|
-
console.error(`Error: could not fetch raw HTML (${res.status}).`);
|
|
322
|
-
return 1;
|
|
323
|
-
}
|
|
324
|
-
process.stdout.write(await res.text());
|
|
325
|
-
return 0;
|
|
326
351
|
}
|
|
327
352
|
|
|
328
353
|
// src/commands/login.ts
|
|
@@ -344,7 +369,7 @@ function openBrowser(url) {
|
|
|
344
369
|
}
|
|
345
370
|
|
|
346
371
|
// src/commands/login.ts
|
|
347
|
-
var
|
|
372
|
+
var HELP2 = `vellum login — authenticate this machine to a Vellum server
|
|
348
373
|
|
|
349
374
|
Opens your browser to approve a CLI login, then stores a token under
|
|
350
375
|
~/.config/vellum/config.json so future commands authenticate as you.
|
|
@@ -367,7 +392,7 @@ async function loginCommand(argv) {
|
|
|
367
392
|
}
|
|
368
393
|
});
|
|
369
394
|
if (values.help) {
|
|
370
|
-
console.log(
|
|
395
|
+
console.log(HELP2);
|
|
371
396
|
return 0;
|
|
372
397
|
}
|
|
373
398
|
const baseUrl = resolveBaseUrl({ url: values.url });
|
|
@@ -408,7 +433,7 @@ To authorize this CLI, visit:
|
|
|
408
433
|
|
|
409
434
|
// src/commands/logout.ts
|
|
410
435
|
import { parseArgs as parseArgs4 } from "node:util";
|
|
411
|
-
var
|
|
436
|
+
var HELP3 = `vellum logout — remove this machine's stored CLI token
|
|
412
437
|
|
|
413
438
|
Usage:
|
|
414
439
|
vellum logout [options]
|
|
@@ -425,7 +450,7 @@ async function logoutCommand(argv) {
|
|
|
425
450
|
}
|
|
426
451
|
});
|
|
427
452
|
if (values.help) {
|
|
428
|
-
console.log(
|
|
453
|
+
console.log(HELP3);
|
|
429
454
|
return 0;
|
|
430
455
|
}
|
|
431
456
|
const baseUrl = resolveBaseUrl({ url: values.url });
|
|
@@ -443,7 +468,7 @@ async function logoutCommand(argv) {
|
|
|
443
468
|
|
|
444
469
|
// src/commands/markup.ts
|
|
445
470
|
import { parseArgs as parseArgs5 } from "node:util";
|
|
446
|
-
var
|
|
471
|
+
var HELP4 = `vellum markup — pin a comment to a passage of a document
|
|
447
472
|
|
|
448
473
|
Usage:
|
|
449
474
|
vellum markup <page-id> --quote "<text>" --body "<note>" [options]
|
|
@@ -468,7 +493,7 @@ async function readStdin() {
|
|
|
468
493
|
chunks.push(chunk);
|
|
469
494
|
return Buffer.concat(chunks).toString("utf8");
|
|
470
495
|
}
|
|
471
|
-
function
|
|
496
|
+
function resolveVersion(page, requested) {
|
|
472
497
|
if (requested != null) {
|
|
473
498
|
return page.versions.find((v) => v.version_number === requested) ?? null;
|
|
474
499
|
}
|
|
@@ -499,14 +524,14 @@ async function markupCommand(argv) {
|
|
|
499
524
|
}
|
|
500
525
|
});
|
|
501
526
|
if (values.help) {
|
|
502
|
-
console.log(
|
|
527
|
+
console.log(HELP4);
|
|
503
528
|
return 0;
|
|
504
529
|
}
|
|
505
530
|
const pageId = positionals[0];
|
|
506
531
|
if (!pageId) {
|
|
507
532
|
console.error(`Error: missing <page-id>.
|
|
508
533
|
`);
|
|
509
|
-
console.error(
|
|
534
|
+
console.error(HELP4);
|
|
510
535
|
return 1;
|
|
511
536
|
}
|
|
512
537
|
const quote = (values.quote ?? "").trim();
|
|
@@ -532,7 +557,7 @@ async function markupCommand(argv) {
|
|
|
532
557
|
const credential = await resolveCredential(flags, baseUrl);
|
|
533
558
|
const client2 = new VellumClient({ baseUrl, ...credential });
|
|
534
559
|
const page = await client2.getPage(pageId);
|
|
535
|
-
const target =
|
|
560
|
+
const target = resolveVersion(page, version);
|
|
536
561
|
if (!target) {
|
|
537
562
|
console.error(version != null ? `Error: page has no version ${version}.` : "Error: page has no versions to mark up.");
|
|
538
563
|
return 1;
|
|
@@ -561,50 +586,10 @@ async function markupCommand(argv) {
|
|
|
561
586
|
return 0;
|
|
562
587
|
}
|
|
563
588
|
|
|
564
|
-
// src/commands/open.ts
|
|
565
|
-
import { parseArgs as parseArgs6 } from "node:util";
|
|
566
|
-
var HELP6 = `vellum open — print (and open) a document's view URL
|
|
567
|
-
|
|
568
|
-
Usage:
|
|
569
|
-
vellum open <page-id> [options]
|
|
570
|
-
|
|
571
|
-
Options:
|
|
572
|
-
--no-browser Just print the URL; don't open the browser
|
|
573
|
-
--url <url> Server base URL (env: VELLUM_URL)
|
|
574
|
-
-h, --help Show this help`;
|
|
575
|
-
async function openCommand(argv) {
|
|
576
|
-
const { values, positionals } = parseArgs6({
|
|
577
|
-
args: argv,
|
|
578
|
-
allowPositionals: true,
|
|
579
|
-
options: {
|
|
580
|
-
"no-browser": { type: "boolean", default: false },
|
|
581
|
-
url: { type: "string" },
|
|
582
|
-
help: { type: "boolean", short: "h", default: false }
|
|
583
|
-
}
|
|
584
|
-
});
|
|
585
|
-
if (values.help) {
|
|
586
|
-
console.log(HELP6);
|
|
587
|
-
return 0;
|
|
588
|
-
}
|
|
589
|
-
const pageId = positionals[0];
|
|
590
|
-
if (!pageId) {
|
|
591
|
-
console.error(`Error: missing <page-id>.
|
|
592
|
-
`);
|
|
593
|
-
console.error(HELP6);
|
|
594
|
-
return 1;
|
|
595
|
-
}
|
|
596
|
-
const baseUrl = resolveBaseUrl({ url: values.url });
|
|
597
|
-
const page = await new VellumClient({ baseUrl }).getPage(pageId);
|
|
598
|
-
console.log(page.view_url);
|
|
599
|
-
if (!values["no-browser"])
|
|
600
|
-
openBrowser(page.view_url);
|
|
601
|
-
return 0;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
589
|
// src/commands/push.ts
|
|
605
590
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
606
|
-
import { parseArgs as
|
|
607
|
-
var
|
|
591
|
+
import { parseArgs as parseArgs6 } from "node:util";
|
|
592
|
+
var HELP5 = `vellum push — create a Vellum artifact from HTML
|
|
608
593
|
|
|
609
594
|
Usage:
|
|
610
595
|
vellum push <file.html> [options]
|
|
@@ -623,7 +608,7 @@ async function readStdin2() {
|
|
|
623
608
|
return Buffer.concat(chunks).toString("utf8");
|
|
624
609
|
}
|
|
625
610
|
async function pushCommand(argv) {
|
|
626
|
-
const { values, positionals } =
|
|
611
|
+
const { values, positionals } = parseArgs6({
|
|
627
612
|
args: argv,
|
|
628
613
|
allowPositionals: true,
|
|
629
614
|
options: {
|
|
@@ -635,7 +620,7 @@ async function pushCommand(argv) {
|
|
|
635
620
|
}
|
|
636
621
|
});
|
|
637
622
|
if (values.help) {
|
|
638
|
-
console.log(
|
|
623
|
+
console.log(HELP5);
|
|
639
624
|
return 0;
|
|
640
625
|
}
|
|
641
626
|
const file = positionals[0];
|
|
@@ -658,144 +643,57 @@ async function pushCommand(argv) {
|
|
|
658
643
|
}
|
|
659
644
|
return 0;
|
|
660
645
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
const { values, positionals } = parseArgs8({
|
|
698
|
-
args: argv,
|
|
699
|
-
allowPositionals: true,
|
|
700
|
-
options: {
|
|
701
|
-
body: { type: "string" },
|
|
702
|
-
url: { type: "string" },
|
|
703
|
-
"api-key": { type: "string" },
|
|
704
|
-
json: { type: "boolean", default: false },
|
|
705
|
-
help: { type: "boolean", short: "h", default: false }
|
|
706
|
-
}
|
|
707
|
-
});
|
|
708
|
-
if (values.help) {
|
|
709
|
-
console.log(HELP8);
|
|
710
|
-
return 0;
|
|
711
|
-
}
|
|
712
|
-
const [pageId, commentId] = positionals;
|
|
713
|
-
if (!pageId || !commentId) {
|
|
714
|
-
console.error("Error: usage is `vellum reply <page-id> <comment-id>`.\n");
|
|
715
|
-
console.error(HELP8);
|
|
716
|
-
return 1;
|
|
646
|
+
// package.json
|
|
647
|
+
var package_default = {
|
|
648
|
+
name: "vellum-cli",
|
|
649
|
+
version: "0.3.2",
|
|
650
|
+
description: "The vellum CLI — publish agent-authored HTML artifacts to a Vellum server.",
|
|
651
|
+
type: "module",
|
|
652
|
+
license: "MIT",
|
|
653
|
+
bin: {
|
|
654
|
+
vellum: "dist/index.js"
|
|
655
|
+
},
|
|
656
|
+
files: [
|
|
657
|
+
"dist",
|
|
658
|
+
"README.md"
|
|
659
|
+
],
|
|
660
|
+
engines: {
|
|
661
|
+
node: ">=18"
|
|
662
|
+
},
|
|
663
|
+
keywords: [
|
|
664
|
+
"vellum",
|
|
665
|
+
"cli",
|
|
666
|
+
"html",
|
|
667
|
+
"artifacts",
|
|
668
|
+
"agents"
|
|
669
|
+
],
|
|
670
|
+
publishConfig: {
|
|
671
|
+
access: "public"
|
|
672
|
+
},
|
|
673
|
+
scripts: {
|
|
674
|
+
start: "bun run src/index.ts",
|
|
675
|
+
build: "bun build src/index.ts --target=node --format=esm --outfile=dist/index.js",
|
|
676
|
+
prepack: "bun run build",
|
|
677
|
+
release: "bun publish --access public",
|
|
678
|
+
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
679
|
+
},
|
|
680
|
+
devDependencies: {
|
|
681
|
+
"@vellum/core": "workspace:*"
|
|
717
682
|
}
|
|
718
|
-
|
|
719
|
-
if (!body) {
|
|
720
|
-
console.error("Error: no note provided (pass --body or pipe it via stdin).");
|
|
721
|
-
return 1;
|
|
722
|
-
}
|
|
723
|
-
const flags = { url: values.url, apiKey: values["api-key"] };
|
|
724
|
-
const baseUrl = resolveBaseUrl(flags);
|
|
725
|
-
const credential = await resolveCredential(flags, baseUrl);
|
|
726
|
-
const client2 = new VellumClient({ baseUrl, ...credential });
|
|
727
|
-
const parent = flatten(await client2.listComments(pageId)).find((c) => c.id === commentId);
|
|
728
|
-
if (!parent) {
|
|
729
|
-
console.error(`Error: no comment ${commentId} on page ${pageId}.`);
|
|
730
|
-
return 1;
|
|
731
|
-
}
|
|
732
|
-
if (!parent.version_id) {
|
|
733
|
-
console.error("Error: parent comment has no version to reply on.");
|
|
734
|
-
return 1;
|
|
735
|
-
}
|
|
736
|
-
const reply = await client2.createComment(pageId, {
|
|
737
|
-
versionId: parent.version_id,
|
|
738
|
-
body,
|
|
739
|
-
parentId: commentId
|
|
740
|
-
});
|
|
741
|
-
if (values.json) {
|
|
742
|
-
console.log(JSON.stringify(reply, null, 2));
|
|
743
|
-
} else {
|
|
744
|
-
console.log(`✓ replied to ${commentId}`);
|
|
745
|
-
}
|
|
746
|
-
return 0;
|
|
747
|
-
}
|
|
683
|
+
};
|
|
748
684
|
|
|
749
|
-
// src/
|
|
750
|
-
|
|
751
|
-
var HELP9 = `vellum resolve — mark a comment as resolved
|
|
685
|
+
// src/version.ts
|
|
686
|
+
var VERSION = package_default.version;
|
|
752
687
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
Options:
|
|
757
|
-
--url <url> Server base URL (env: VELLUM_URL)
|
|
758
|
-
--api-key <key> Shared API key (env: VELLUM_API_KEY)
|
|
759
|
-
--json Print the raw JSON response
|
|
760
|
-
-h, --help Show this help`;
|
|
761
|
-
async function resolveCommand(argv) {
|
|
762
|
-
const { values, positionals } = parseArgs9({
|
|
763
|
-
args: argv,
|
|
764
|
-
allowPositionals: true,
|
|
765
|
-
options: {
|
|
766
|
-
url: { type: "string" },
|
|
767
|
-
"api-key": { type: "string" },
|
|
768
|
-
json: { type: "boolean", default: false },
|
|
769
|
-
help: { type: "boolean", short: "h", default: false }
|
|
770
|
-
}
|
|
771
|
-
});
|
|
772
|
-
if (values.help) {
|
|
773
|
-
console.log(HELP9);
|
|
774
|
-
return 0;
|
|
775
|
-
}
|
|
776
|
-
const commentId = positionals[0];
|
|
777
|
-
if (!commentId) {
|
|
778
|
-
console.error(`Error: missing <comment-id>.
|
|
779
|
-
`);
|
|
780
|
-
console.error(HELP9);
|
|
781
|
-
return 1;
|
|
782
|
-
}
|
|
783
|
-
const flags = { url: values.url, apiKey: values["api-key"] };
|
|
784
|
-
const baseUrl = resolveBaseUrl(flags);
|
|
785
|
-
const credential = await resolveCredential(flags, baseUrl);
|
|
786
|
-
const client2 = new VellumClient({ baseUrl, ...credential });
|
|
787
|
-
const comment = await client2.resolveComment(commentId);
|
|
788
|
-
if (values.json) {
|
|
789
|
-
console.log(JSON.stringify(comment, null, 2));
|
|
790
|
-
} else {
|
|
791
|
-
console.log(`✓ resolved ${comment.id}`);
|
|
792
|
-
}
|
|
688
|
+
// src/commands/version.ts
|
|
689
|
+
async function versionCommand(_argv) {
|
|
690
|
+
console.log(VERSION);
|
|
793
691
|
return 0;
|
|
794
692
|
}
|
|
795
693
|
|
|
796
694
|
// src/commands/whoami.ts
|
|
797
|
-
import { parseArgs as
|
|
798
|
-
var
|
|
695
|
+
import { parseArgs as parseArgs7 } from "node:util";
|
|
696
|
+
var HELP6 = `vellum whoami — show the identity the CLI is authenticated as
|
|
799
697
|
|
|
800
698
|
Usage:
|
|
801
699
|
vellum whoami [options]
|
|
@@ -805,7 +703,7 @@ Options:
|
|
|
805
703
|
--api-key <key> Shared API key (env: VELLUM_API_KEY)
|
|
806
704
|
-h, --help Show this help`;
|
|
807
705
|
async function whoamiCommand(argv) {
|
|
808
|
-
const { values } =
|
|
706
|
+
const { values } = parseArgs7({
|
|
809
707
|
args: argv,
|
|
810
708
|
options: {
|
|
811
709
|
url: { type: "string" },
|
|
@@ -814,7 +712,7 @@ async function whoamiCommand(argv) {
|
|
|
814
712
|
}
|
|
815
713
|
});
|
|
816
714
|
if (values.help) {
|
|
817
|
-
console.log(
|
|
715
|
+
console.log(HELP6);
|
|
818
716
|
return 0;
|
|
819
717
|
}
|
|
820
718
|
const baseUrl = resolveBaseUrl({ url: values.url });
|
|
@@ -830,7 +728,7 @@ async function whoamiCommand(argv) {
|
|
|
830
728
|
}
|
|
831
729
|
|
|
832
730
|
// src/index.ts
|
|
833
|
-
var
|
|
731
|
+
var HELP7 = `vellum — CLI for the Vellum artifact store
|
|
834
732
|
|
|
835
733
|
Usage:
|
|
836
734
|
vellum <command> [options]
|
|
@@ -840,12 +738,11 @@ Commands:
|
|
|
840
738
|
logout Remove this machine's stored CLI token
|
|
841
739
|
whoami Show the identity the CLI is authenticated as
|
|
842
740
|
push Create an artifact (page) from HTML (file or stdin)
|
|
843
|
-
|
|
844
|
-
open Print (and open) a document's view URL
|
|
741
|
+
list List your artifacts (owner/admin only)
|
|
845
742
|
markup Pin a comment to a passage of a document
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
743
|
+
archive Archive a page (read-only, hidden from the gallery)
|
|
744
|
+
unarchive Restore an archived page to live
|
|
745
|
+
version Print the installed CLI version
|
|
849
746
|
|
|
850
747
|
Run 'vellum <command> --help' for command-specific options.`;
|
|
851
748
|
var commands = {
|
|
@@ -853,24 +750,26 @@ var commands = {
|
|
|
853
750
|
logout: logoutCommand,
|
|
854
751
|
whoami: whoamiCommand,
|
|
855
752
|
push: pushCommand,
|
|
856
|
-
|
|
857
|
-
open: openCommand,
|
|
753
|
+
list: listCommand,
|
|
858
754
|
markup: markupCommand,
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
755
|
+
archive: archiveCommand,
|
|
756
|
+
unarchive: unarchiveCommand,
|
|
757
|
+
version: versionCommand
|
|
862
758
|
};
|
|
863
759
|
async function main() {
|
|
864
760
|
const [, , cmd, ...rest] = process.argv;
|
|
865
761
|
if (!cmd || cmd === "-h" || cmd === "--help" || cmd === "help") {
|
|
866
|
-
console.log(
|
|
762
|
+
console.log(HELP7);
|
|
867
763
|
return cmd ? 0 : 1;
|
|
868
764
|
}
|
|
765
|
+
if (cmd === "-v" || cmd === "--version") {
|
|
766
|
+
return versionCommand(rest);
|
|
767
|
+
}
|
|
869
768
|
const handler = commands[cmd];
|
|
870
769
|
if (!handler) {
|
|
871
770
|
console.error(`Unknown command: ${cmd}
|
|
872
771
|
`);
|
|
873
|
-
console.error(
|
|
772
|
+
console.error(HELP7);
|
|
874
773
|
return 1;
|
|
875
774
|
}
|
|
876
775
|
return handler(rest);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vellum-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "The vellum CLI — publish agent-authored HTML artifacts to a Vellum server.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
"start": "bun run src/index.ts",
|
|
29
29
|
"build": "bun build src/index.ts --target=node --format=esm --outfile=dist/index.js",
|
|
30
30
|
"prepack": "bun run build",
|
|
31
|
+
"release": "bun publish --access public",
|
|
31
32
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
|
-
"@vellum/core": "
|
|
35
|
+
"@vellum/core": "0.1.0"
|
|
35
36
|
}
|
|
36
37
|
}
|