vellum-cli 0.2.0 → 0.3.0

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 (2) hide show
  1. package/dist/index.js +506 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -61,7 +61,7 @@ async function clearToken(baseUrl) {
61
61
  return existing;
62
62
  }
63
63
 
64
- // src/commands/login.ts
64
+ // src/commands/comments.ts
65
65
  import { parseArgs } from "node:util";
66
66
  // ../core/src/client.ts
67
67
  class VellumApiError extends Error {
@@ -113,6 +113,42 @@ class VellumClient {
113
113
  await this.fail(res);
114
114
  return await res.json();
115
115
  }
116
+ async getPage(pageId) {
117
+ const res = await this.fetchImpl(`${this.baseUrl}/v1/pages/${encodeURIComponent(pageId)}`, { headers: this.authHeaders() });
118
+ if (!res.ok)
119
+ await this.fail(res);
120
+ return await res.json();
121
+ }
122
+ async createComment(pageId, opts) {
123
+ const res = await this.fetchImpl(`${this.baseUrl}/v1/pages/${encodeURIComponent(pageId)}/comments`, {
124
+ method: "POST",
125
+ headers: { "Content-Type": "application/json", ...this.authHeaders() },
126
+ body: JSON.stringify({
127
+ version_id: opts.versionId,
128
+ body: opts.body,
129
+ anchor: opts.anchor,
130
+ parent_id: opts.parentId
131
+ })
132
+ });
133
+ if (!res.ok)
134
+ await this.fail(res);
135
+ return await res.json();
136
+ }
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
+ }
116
152
  async startCliAuth() {
117
153
  const res = await this.fetchImpl(`${this.baseUrl}/v1/cli/auth/start`, {
118
154
  method: "POST",
@@ -150,6 +186,148 @@ class VellumClient {
150
186
  await this.fail(res);
151
187
  }
152
188
  }
189
+ // src/commands/comments.ts
190
+ var HELP = `vellum comments — list the comments on a document
191
+
192
+ Usage:
193
+ vellum comments <page-id> [options]
194
+
195
+ Reads are public, so no login is required. Comments print as threads; replies
196
+ are indented under their parent.
197
+
198
+ Options:
199
+ --open Show only unresolved threads
200
+ --version <id> Only comments anchored to this version id
201
+ --url <url> Server base URL (env: VELLUM_URL)
202
+ --json Print the raw JSON response
203
+ -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
+ }
218
+ async function commentsCommand(argv) {
219
+ const { values, positionals } = parseArgs({
220
+ args: argv,
221
+ allowPositionals: true,
222
+ options: {
223
+ open: { type: "boolean", default: false },
224
+ version: { type: "string" },
225
+ url: { type: "string" },
226
+ json: { type: "boolean", default: false },
227
+ help: { type: "boolean", short: "h", default: false }
228
+ }
229
+ });
230
+ if (values.help) {
231
+ console.log(HELP);
232
+ return 0;
233
+ }
234
+ const pageId = positionals[0];
235
+ if (!pageId) {
236
+ console.error(`Error: missing <page-id>.
237
+ `);
238
+ console.error(HELP);
239
+ return 1;
240
+ }
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.");
254
+ return 0;
255
+ }
256
+ for (const c of comments)
257
+ printComment(c, "");
258
+ return 0;
259
+ }
260
+
261
+ // src/commands/get.ts
262
+ import { parseArgs as parseArgs2 } from "node:util";
263
+ var HELP2 = `vellum get — print a document's raw HTML
264
+
265
+ Usage:
266
+ vellum get <page-id> [options]
267
+
268
+ Reads are public, so no login is required. Without --version, the page's
269
+ current version is printed.
270
+
271
+ Options:
272
+ --version <n> Print a specific version number (default: current)
273
+ --url <url> Server base URL (env: VELLUM_URL)
274
+ -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;
281
+ }
282
+ async function getCommand(argv) {
283
+ const { values, positionals } = parseArgs2({
284
+ args: argv,
285
+ allowPositionals: true,
286
+ options: {
287
+ version: { type: "string" },
288
+ url: { type: "string" },
289
+ help: { type: "boolean", short: "h", default: false }
290
+ }
291
+ });
292
+ if (values.help) {
293
+ console.log(HELP2);
294
+ return 0;
295
+ }
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.");
308
+ return 1;
309
+ }
310
+ }
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
+ }
327
+
328
+ // src/commands/login.ts
329
+ import { parseArgs as parseArgs3 } from "node:util";
330
+
153
331
  // src/util/open.ts
154
332
  import { spawn } from "node:child_process";
155
333
  function openBrowser(url) {
@@ -166,7 +344,7 @@ function openBrowser(url) {
166
344
  }
167
345
 
168
346
  // src/commands/login.ts
169
- var HELP = `vellum login — authenticate this machine to a Vellum server
347
+ var HELP3 = `vellum login — authenticate this machine to a Vellum server
170
348
 
171
349
  Opens your browser to approve a CLI login, then stores a token under
172
350
  ~/.config/vellum/config.json so future commands authenticate as you.
@@ -180,7 +358,7 @@ Options:
180
358
  -h, --help Show this help`;
181
359
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
182
360
  async function loginCommand(argv) {
183
- const { values } = parseArgs({
361
+ const { values } = parseArgs3({
184
362
  args: argv,
185
363
  options: {
186
364
  url: { type: "string" },
@@ -189,7 +367,7 @@ async function loginCommand(argv) {
189
367
  }
190
368
  });
191
369
  if (values.help) {
192
- console.log(HELP);
370
+ console.log(HELP3);
193
371
  return 0;
194
372
  }
195
373
  const baseUrl = resolveBaseUrl({ url: values.url });
@@ -229,8 +407,8 @@ To authorize this CLI, visit:
229
407
  }
230
408
 
231
409
  // src/commands/logout.ts
232
- import { parseArgs as parseArgs2 } from "node:util";
233
- var HELP2 = `vellum logout — remove this machine's stored CLI token
410
+ import { parseArgs as parseArgs4 } from "node:util";
411
+ var HELP4 = `vellum logout — remove this machine's stored CLI token
234
412
 
235
413
  Usage:
236
414
  vellum logout [options]
@@ -239,7 +417,7 @@ Options:
239
417
  --url <url> Server base URL (env: VELLUM_URL)
240
418
  -h, --help Show this help`;
241
419
  async function logoutCommand(argv) {
242
- const { values } = parseArgs2({
420
+ const { values } = parseArgs4({
243
421
  args: argv,
244
422
  options: {
245
423
  url: { type: "string" },
@@ -247,7 +425,7 @@ async function logoutCommand(argv) {
247
425
  }
248
426
  });
249
427
  if (values.help) {
250
- console.log(HELP2);
428
+ console.log(HELP4);
251
429
  return 0;
252
430
  }
253
431
  const baseUrl = resolveBaseUrl({ url: values.url });
@@ -263,10 +441,170 @@ async function logoutCommand(argv) {
263
441
  return 0;
264
442
  }
265
443
 
444
+ // src/commands/markup.ts
445
+ import { parseArgs as parseArgs5 } from "node:util";
446
+ var HELP5 = `vellum markup — pin a comment to a passage of a document
447
+
448
+ Usage:
449
+ vellum markup <page-id> --quote "<text>" --body "<note>" [options]
450
+ echo "<note>" | vellum markup <page-id> --quote "<text>"
451
+
452
+ The --quote text must appear verbatim in the document; the viewer highlights it
453
+ and links the highlight to your note. Without --version, the page's current
454
+ version is used.
455
+
456
+ Options:
457
+ --quote <text> Passage to mark up (must match the document text)
458
+ --body <note> Your note (or pipe it via stdin)
459
+ --version <n> Pin to a specific version number (default: current)
460
+ --force Post even if the quote isn't found in the version
461
+ --url <url> Server base URL (env: VELLUM_URL)
462
+ --api-key <key> Shared API key (env: VELLUM_API_KEY)
463
+ --json Print the raw JSON response
464
+ -h, --help Show this help`;
465
+ async function readStdin() {
466
+ const chunks = [];
467
+ for await (const chunk of process.stdin)
468
+ chunks.push(chunk);
469
+ return Buffer.concat(chunks).toString("utf8");
470
+ }
471
+ function resolveVersion2(page, requested) {
472
+ if (requested != null) {
473
+ return page.versions.find((v) => v.version_number === requested) ?? null;
474
+ }
475
+ const current = page.current_version_id ? page.versions.find((v) => v.id === page.current_version_id) : undefined;
476
+ return current ?? page.versions[page.versions.length - 1] ?? null;
477
+ }
478
+ function extractText(html) {
479
+ return html.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<[^>]+>/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'");
480
+ }
481
+ var collapse = (s) => s.replace(/\s+/g, " ").trim();
482
+ function quoteIsAnchorable(html, quote) {
483
+ const text = extractText(html);
484
+ return text.includes(quote) || collapse(text).includes(collapse(quote));
485
+ }
486
+ async function markupCommand(argv) {
487
+ const { values, positionals } = parseArgs5({
488
+ args: argv,
489
+ allowPositionals: true,
490
+ options: {
491
+ quote: { type: "string" },
492
+ body: { type: "string" },
493
+ version: { type: "string" },
494
+ force: { type: "boolean", default: false },
495
+ url: { type: "string" },
496
+ "api-key": { type: "string" },
497
+ json: { type: "boolean", default: false },
498
+ help: { type: "boolean", short: "h", default: false }
499
+ }
500
+ });
501
+ if (values.help) {
502
+ console.log(HELP5);
503
+ return 0;
504
+ }
505
+ const pageId = positionals[0];
506
+ if (!pageId) {
507
+ console.error(`Error: missing <page-id>.
508
+ `);
509
+ console.error(HELP5);
510
+ return 1;
511
+ }
512
+ const quote = (values.quote ?? "").trim();
513
+ if (!quote) {
514
+ console.error("Error: --quote is required (the passage to mark up).");
515
+ return 1;
516
+ }
517
+ const body = (values.body ?? await readStdin()).trim();
518
+ if (!body) {
519
+ console.error("Error: no note provided (pass --body or pipe it via stdin).");
520
+ return 1;
521
+ }
522
+ let version;
523
+ if (values.version != null) {
524
+ version = Number.parseInt(values.version, 10);
525
+ if (!Number.isInteger(version) || version < 1) {
526
+ console.error("Error: --version must be a positive integer.");
527
+ return 1;
528
+ }
529
+ }
530
+ const flags = { url: values.url, apiKey: values["api-key"] };
531
+ const baseUrl = resolveBaseUrl(flags);
532
+ const credential = await resolveCredential(flags, baseUrl);
533
+ const client2 = new VellumClient({ baseUrl, ...credential });
534
+ const page = await client2.getPage(pageId);
535
+ const target = resolveVersion2(page, version);
536
+ if (!target) {
537
+ console.error(version != null ? `Error: page has no version ${version}.` : "Error: page has no versions to mark up.");
538
+ return 1;
539
+ }
540
+ if (!values.force) {
541
+ const html = await fetch(target.raw_url).then((r) => r.ok ? r.text() : "");
542
+ if (!quoteIsAnchorable(html, quote)) {
543
+ console.error(`Error: --quote was not found in v${target.version_number}; the highlight
544
+ ` + " would not appear. Check the wording, or pass --force to post anyway.");
545
+ return 1;
546
+ }
547
+ }
548
+ const anchor = { type: "text-quote", exact: quote };
549
+ const comment = await client2.createComment(pageId, {
550
+ versionId: target.id,
551
+ body,
552
+ anchor
553
+ });
554
+ if (values.json) {
555
+ console.log(JSON.stringify(comment, null, 2));
556
+ } else {
557
+ console.log("✓ markup added");
558
+ console.log(` on: “${quote.length > 80 ? `${quote.slice(0, 79)}…` : quote}”`);
559
+ console.log(` view: ${page.view_url}`);
560
+ }
561
+ return 0;
562
+ }
563
+
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
+
266
604
  // src/commands/push.ts
267
605
  import { readFile as readFile2 } from "node:fs/promises";
268
- import { parseArgs as parseArgs3 } from "node:util";
269
- var HELP3 = `vellum push — create a Vellum artifact from HTML
606
+ import { parseArgs as parseArgs7 } from "node:util";
607
+ var HELP7 = `vellum push — create a Vellum artifact from HTML
270
608
 
271
609
  Usage:
272
610
  vellum push <file.html> [options]
@@ -278,14 +616,14 @@ Options:
278
616
  --api-key <key> Shared API key (env: VELLUM_API_KEY)
279
617
  --json Print the raw JSON response
280
618
  -h, --help Show this help`;
281
- async function readStdin() {
619
+ async function readStdin2() {
282
620
  const chunks = [];
283
621
  for await (const chunk of process.stdin)
284
622
  chunks.push(chunk);
285
623
  return Buffer.concat(chunks).toString("utf8");
286
624
  }
287
625
  async function pushCommand(argv) {
288
- const { values, positionals } = parseArgs3({
626
+ const { values, positionals } = parseArgs7({
289
627
  args: argv,
290
628
  allowPositionals: true,
291
629
  options: {
@@ -297,11 +635,11 @@ async function pushCommand(argv) {
297
635
  }
298
636
  });
299
637
  if (values.help) {
300
- console.log(HELP3);
638
+ console.log(HELP7);
301
639
  return 0;
302
640
  }
303
641
  const file = positionals[0];
304
- const html = file ? await readFile2(file, "utf8") : await readStdin();
642
+ const html = file ? await readFile2(file, "utf8") : await readStdin2();
305
643
  if (!html.trim()) {
306
644
  console.error("Error: no HTML provided (empty file or stdin).");
307
645
  return 1;
@@ -321,9 +659,143 @@ async function pushCommand(argv) {
321
659
  return 0;
322
660
  }
323
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;
717
+ }
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
+ }
748
+
749
+ // src/commands/resolve.ts
750
+ import { parseArgs as parseArgs9 } from "node:util";
751
+ var HELP9 = `vellum resolve — mark a comment as resolved
752
+
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
+ }
793
+ return 0;
794
+ }
795
+
324
796
  // src/commands/whoami.ts
325
- import { parseArgs as parseArgs4 } from "node:util";
326
- var HELP4 = `vellum whoami — show the identity the CLI is authenticated as
797
+ import { parseArgs as parseArgs10 } from "node:util";
798
+ var HELP10 = `vellum whoami — show the identity the CLI is authenticated as
327
799
 
328
800
  Usage:
329
801
  vellum whoami [options]
@@ -333,7 +805,7 @@ Options:
333
805
  --api-key <key> Shared API key (env: VELLUM_API_KEY)
334
806
  -h, --help Show this help`;
335
807
  async function whoamiCommand(argv) {
336
- const { values } = parseArgs4({
808
+ const { values } = parseArgs10({
337
809
  args: argv,
338
810
  options: {
339
811
  url: { type: "string" },
@@ -342,7 +814,7 @@ async function whoamiCommand(argv) {
342
814
  }
343
815
  });
344
816
  if (values.help) {
345
- console.log(HELP4);
817
+ console.log(HELP10);
346
818
  return 0;
347
819
  }
348
820
  const baseUrl = resolveBaseUrl({ url: values.url });
@@ -358,7 +830,7 @@ async function whoamiCommand(argv) {
358
830
  }
359
831
 
360
832
  // src/index.ts
361
- var HELP5 = `vellum — CLI for the Vellum artifact store
833
+ var HELP11 = `vellum — CLI for the Vellum artifact store
362
834
 
363
835
  Usage:
364
836
  vellum <command> [options]
@@ -368,25 +840,37 @@ Commands:
368
840
  logout Remove this machine's stored CLI token
369
841
  whoami Show the identity the CLI is authenticated as
370
842
  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
845
+ 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
371
849
 
372
850
  Run 'vellum <command> --help' for command-specific options.`;
373
851
  var commands = {
374
852
  login: loginCommand,
375
853
  logout: logoutCommand,
376
854
  whoami: whoamiCommand,
377
- push: pushCommand
855
+ push: pushCommand,
856
+ get: getCommand,
857
+ open: openCommand,
858
+ markup: markupCommand,
859
+ comments: commentsCommand,
860
+ reply: replyCommand,
861
+ resolve: resolveCommand
378
862
  };
379
863
  async function main() {
380
864
  const [, , cmd, ...rest] = process.argv;
381
865
  if (!cmd || cmd === "-h" || cmd === "--help" || cmd === "help") {
382
- console.log(HELP5);
866
+ console.log(HELP11);
383
867
  return cmd ? 0 : 1;
384
868
  }
385
869
  const handler = commands[cmd];
386
870
  if (!handler) {
387
871
  console.error(`Unknown command: ${cmd}
388
872
  `);
389
- console.error(HELP5);
873
+ console.error(HELP11);
390
874
  return 1;
391
875
  }
392
876
  return handler(rest);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vellum-cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "The vellum CLI — publish agent-authored HTML artifacts to a Vellum server.",
5
5
  "type": "module",
6
6
  "license": "MIT",