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.
Files changed (3) hide show
  1. package/README.md +25 -0
  2. package/dist/index.js +199 -300
  3. 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/comments.ts
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/comments.ts
190
- var HELP = `vellum comments — list the comments on a document
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 comments <page-id> [options]
204
+ vellum ${verb} <page-id> [options]
194
205
 
195
- Reads are public, so no login is required. Comments print as threads; replies
196
- are indented under their parent.
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 commentsCommand(argv) {
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(HELP);
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(HELP);
235
+ console.error(help(verb));
239
236
  return 1;
240
237
  }
241
- const baseUrl = resolveBaseUrl({ url: values.url });
242
- const client2 = new VellumClient({ baseUrl });
243
- let comments = await client2.listComments(pageId, {
244
- versionId: values.version
245
- });
246
- if (values.open)
247
- comments = comments.filter((c) => !c.resolved);
248
- if (values.json) {
249
- console.log(JSON.stringify(comments, null, 2));
250
- return 0;
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
- for (const c of comments)
257
- printComment(c, "");
258
- return 0;
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/get.ts
269
+ // src/commands/list.ts
262
270
  import { parseArgs as parseArgs2 } from "node:util";
263
- var HELP2 = `vellum getprint a document's raw HTML
271
+ var HELP = `vellum listlist your artifacts (owner/admin only)
264
272
 
265
273
  Usage:
266
- vellum get <page-id> [options]
274
+ vellum list [options]
267
275
 
268
- Reads are public, so no login is required. Without --version, the page's
269
- current version is printed.
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
- --version <n> Print a specific version number (default: current)
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 resolveVersion(page, requested) {
276
- if (requested != null) {
277
- return page.versions.find((v) => v.version_number === requested) ?? null;
278
- }
279
- const current = page.current_version_id ? page.versions.find((v) => v.id === page.current_version_id) : undefined;
280
- return current ?? page.versions[page.versions.length - 1] ?? null;
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 getCommand(argv) {
283
- const { values, positionals } = parseArgs2({
303
+ async function listCommand(argv) {
304
+ const { values } = parseArgs2({
284
305
  args: argv,
285
- allowPositionals: true,
306
+ allowPositionals: false,
286
307
  options: {
287
- version: { type: "string" },
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(HELP2);
317
+ console.log(HELP);
294
318
  return 0;
295
319
  }
296
- const pageId = positionals[0];
297
- if (!pageId) {
298
- console.error(`Error: missing <page-id>.
299
- `);
300
- console.error(HELP2);
301
- return 1;
302
- }
303
- let version;
304
- if (values.version != null) {
305
- version = Number.parseInt(values.version, 10);
306
- if (!Number.isInteger(version) || version < 1) {
307
- console.error("Error: --version must be a positive integer.");
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 HELP3 = `vellum login — authenticate this machine to a Vellum server
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(HELP3);
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 HELP4 = `vellum logout — remove this machine's stored CLI token
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(HELP4);
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 HELP5 = `vellum markup — pin a comment to a passage of a document
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 resolveVersion2(page, requested) {
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(HELP5);
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(HELP5);
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 = resolveVersion2(page, version);
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 parseArgs7 } from "node:util";
607
- var HELP7 = `vellum push — create a Vellum artifact from HTML
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 } = parseArgs7({
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(HELP7);
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
- // src/commands/reply.ts
663
- import { parseArgs as parseArgs8 } from "node:util";
664
- var HELP8 = `vellum reply — reply to a comment thread
665
-
666
- Usage:
667
- vellum reply <page-id> <comment-id> --body "<note>"
668
- echo "<note>" | vellum reply <page-id> <comment-id>
669
-
670
- The reply is threaded under <comment-id> and inherits the parent's version.
671
- Run \`vellum comments <page-id>\` to find the page and comment ids.
672
-
673
- Options:
674
- --body <note> Your reply (or pipe it via stdin)
675
- --url <url> Server base URL (env: VELLUM_URL)
676
- --api-key <key> Shared API key (env: VELLUM_API_KEY)
677
- --json Print the raw JSON response
678
- -h, --help Show this help`;
679
- async function readStdin3() {
680
- const chunks = [];
681
- for await (const chunk of process.stdin)
682
- chunks.push(chunk);
683
- return Buffer.concat(chunks).toString("utf8");
684
- }
685
- function flatten(comments) {
686
- const out = [];
687
- const walk = (c) => {
688
- out.push(c);
689
- for (const reply of c.replies ?? [])
690
- walk(reply);
691
- };
692
- for (const c of comments)
693
- walk(c);
694
- return out;
695
- }
696
- async function replyCommand(argv) {
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
- const body = (values.body ?? await readStdin3()).trim();
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/commands/resolve.ts
750
- import { parseArgs as parseArgs9 } from "node:util";
751
- var HELP9 = `vellum resolve — mark a comment as resolved
685
+ // src/version.ts
686
+ var VERSION = package_default.version;
752
687
 
753
- Usage:
754
- vellum resolve <comment-id> [options]
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 parseArgs10 } from "node:util";
798
- var HELP10 = `vellum whoami — show the identity the CLI is authenticated as
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 } = parseArgs10({
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(HELP10);
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 HELP11 = `vellum — CLI for the Vellum artifact store
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
- get Print a document's raw HTML
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
- comments List the comments on a document
847
- reply Reply to a comment thread
848
- resolve Mark a comment as resolved
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
- get: getCommand,
857
- open: openCommand,
753
+ list: listCommand,
858
754
  markup: markupCommand,
859
- comments: commentsCommand,
860
- reply: replyCommand,
861
- resolve: resolveCommand
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(HELP11);
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(HELP11);
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.0",
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": "workspace:*"
35
+ "@vellum/core": "0.1.0"
35
36
  }
36
37
  }