@sage-protocol/cli 0.8.0 → 0.8.3

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.

Potentially problematic release.


This version of @sage-protocol/cli might be problematic. Click here for more details.

Files changed (34) hide show
  1. package/README.md +12 -11
  2. package/dist/cli/commands/boost.js +339 -62
  3. package/dist/cli/commands/bounty.js +28 -4
  4. package/dist/cli/commands/config.js +10 -1
  5. package/dist/cli/commands/contributor.js +16 -6
  6. package/dist/cli/commands/dao.js +1 -1
  7. package/dist/cli/commands/discover.js +3 -3
  8. package/dist/cli/commands/governance.js +141 -58
  9. package/dist/cli/commands/install.js +178 -36
  10. package/dist/cli/commands/ipfs.js +12 -2
  11. package/dist/cli/commands/library.js +277 -268
  12. package/dist/cli/commands/members.js +132 -18
  13. package/dist/cli/commands/multiplier.js +101 -13
  14. package/dist/cli/commands/nft.js +16 -3
  15. package/dist/cli/commands/personal.js +69 -2
  16. package/dist/cli/commands/prompt.js +1 -1
  17. package/dist/cli/commands/proposals.js +153 -3
  18. package/dist/cli/commands/stake-status.js +130 -56
  19. package/dist/cli/commands/sxxx.js +37 -4
  20. package/dist/cli/commands/wallet.js +5 -10
  21. package/dist/cli/contracts/index.js +2 -1
  22. package/dist/cli/index.js +5 -0
  23. package/dist/cli/privy-auth-wallet-manager.js +3 -2
  24. package/dist/cli/services/config/chain-defaults.js +1 -1
  25. package/dist/cli/services/config/manager.js +3 -0
  26. package/dist/cli/services/config/schema.js +1 -0
  27. package/dist/cli/services/ipfs/onboarding.js +11 -0
  28. package/dist/cli/utils/aliases.js +62 -3
  29. package/dist/cli/utils/cli-ui.js +1 -1
  30. package/dist/cli/utils/provider.js +7 -3
  31. package/dist/cli/wallet-manager.js +7 -12
  32. package/dist/prompts/e2e-test-prompt.md +22 -0
  33. package/dist/prompts/skills/build-web3/plugin.json +11 -0
  34. package/package.json +1 -1
@@ -364,7 +364,8 @@ QUICK START
364
364
  const subdaoStore = require('../utils/subdao-store');
365
365
 
366
366
  // Resolve SubDAO address
367
- let subdao = opts.subdao || subdaoStore.getCurrent() || process.env.SUBDAO;
367
+ const current = subdaoStore.getCurrent();
368
+ let subdao = opts.subdao || (current && current.address) || process.env.SUBDAO;
368
369
  if (!subdao) {
369
370
  throw new Error('No DAO specified. Use --subdao or run `sage dao use <address>`');
370
371
  }
@@ -490,323 +491,331 @@ QUICK START
490
491
  }
491
492
  });
492
493
 
493
- // ===== Personal Library Commands (Three-Tier Model) =====
494
+ // ===== Personal/Vault Library Commands (Three-Tier Model) =====
494
495
  // These use SIWE auth and the worker API at /git/personal/:libraryId/*
495
496
 
496
- const personal = new Command('personal')
497
- .description('Personal library management (wallet-owned, no on-chain governance)');
497
+ function buildPersonalCommands({ name, label }) {
498
+ const personal = new Command(name)
499
+ .description(`${label} library management (wallet-owned, no on-chain governance)`);
500
+
501
+ personal
502
+ .command('create')
503
+ .description(`Create a ${label.toLowerCase()} library`)
504
+ .requiredOption('-n, --name <name>', 'Library name')
505
+ .option('-d, --description <desc>', 'Library description')
506
+ .option('--id <libraryId>', 'Custom library ID (default: slugified name)')
507
+ .option('--json', 'Output JSON', false)
508
+ .action(async (opts) => {
509
+ try {
510
+ const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
511
+ const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
498
512
 
499
- personal
500
- .command('create')
501
- .description('Create a personal library')
502
- .requiredOption('-n, --name <name>', 'Library name')
503
- .option('-d, --description <desc>', 'Library description')
504
- .option('--id <libraryId>', 'Custom library ID (default: slugified name)')
505
- .option('--json', 'Output JSON', false)
506
- .action(async (opts) => {
507
- try {
508
- const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
509
- const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
513
+ ui.info(`Creating ${label.toLowerCase()} library...`);
510
514
 
511
- ui.info('Creating personal library...');
515
+ // Get SIWE auth
516
+ const { signer } = await getSignerSession();
517
+ const walletAddress = await signer.getAddress();
518
+ const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
512
519
 
513
- // Get SIWE auth
514
- const { signer } = await getSignerSession();
515
- const walletAddress = await signer.getAddress();
516
- const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
517
-
518
- // Initialize library via worker API
519
- const response = await fetch(`${baseUrl}/git/personal/libraries`, {
520
- method: 'POST',
521
- headers: {
522
- 'Content-Type': 'application/json',
523
- 'X-Wallet-Address': walletAddress,
524
- 'X-Wallet-Signature': signature,
525
- 'X-Wallet-Nonce': nonce,
526
- 'X-Wallet-Message': Buffer.from(message).toString('base64'),
527
- },
528
- body: JSON.stringify({
529
- name: opts.name,
530
- description: opts.description || '',
531
- visibility: 'public',
532
- }),
533
- });
520
+ // Initialize library via worker API
521
+ const response = await fetch(`${baseUrl}/git/personal/libraries`, {
522
+ method: 'POST',
523
+ headers: {
524
+ 'Content-Type': 'application/json',
525
+ 'X-Wallet-Address': walletAddress,
526
+ 'X-Wallet-Signature': signature,
527
+ 'X-Wallet-Nonce': nonce,
528
+ 'X-Wallet-Message': Buffer.from(message).toString('base64'),
529
+ },
530
+ body: JSON.stringify({
531
+ name: opts.name,
532
+ description: opts.description || '',
533
+ visibility: 'public',
534
+ }),
535
+ });
534
536
 
535
- if (!response.ok) {
536
- const error = await response.json().catch(() => ({ error: response.statusText }));
537
- throw new Error(error.error || `Failed to create library: ${response.status}`);
538
- }
537
+ if (!response.ok) {
538
+ const error = await response.json().catch(() => ({ error: response.statusText }));
539
+ throw new Error(error.error || `Failed to create library: ${response.status}`);
540
+ }
539
541
 
540
- const result = await response.json();
541
- const libraryId = result.libraryId;
542
+ const result = await response.json();
543
+ const libraryId = result.libraryId;
542
544
 
543
- if (opts.json) {
544
- ui.json({ ...result, owner: walletAddress });
545
- } else {
546
- ui.success(`Personal library created: ${libraryId}`);
547
- ui.keyValue([
548
- ['Library ID', libraryId],
549
- ['Name', result.name || opts.name],
550
- ['Owner', walletAddress],
551
- ]);
552
- }
545
+ if (opts.json) {
546
+ ui.json({ ...result, owner: walletAddress });
547
+ } else {
548
+ ui.success(`${label} library created: ${libraryId}`);
549
+ ui.keyValue([
550
+ ['Library ID', libraryId],
551
+ ['Name', result.name || opts.name],
552
+ ['Owner', walletAddress],
553
+ ]);
554
+ }
553
555
 
554
- } catch (e) {
555
- handleCLIError('library:personal:create', e, { exit: true });
556
- }
557
- });
556
+ } catch (e) {
557
+ handleCLIError('library:personal:create', e, { exit: true });
558
+ }
559
+ });
558
560
 
559
- personal
560
- .command('list')
561
- .description('List your personal libraries')
562
- .option('--json', 'Output JSON', false)
563
- .action(async (opts) => {
564
- try {
565
- const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
566
- const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
561
+ personal
562
+ .command('list')
563
+ .description(`List your ${label.toLowerCase()} libraries`)
564
+ .option('--json', 'Output JSON', false)
565
+ .action(async (opts) => {
566
+ try {
567
+ const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
568
+ const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
567
569
 
568
- const { signer } = await getSignerSession();
569
- const walletAddress = await signer.getAddress();
570
- const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
571
-
572
- const response = await fetch(`${baseUrl}/git/personal/libraries`, {
573
- method: 'GET',
574
- headers: {
575
- 'X-Wallet-Address': walletAddress,
576
- 'X-Wallet-Signature': signature,
577
- 'X-Wallet-Nonce': nonce,
578
- 'X-Wallet-Message': Buffer.from(message).toString('base64'),
579
- },
580
- });
570
+ const { signer } = await getSignerSession();
571
+ const walletAddress = await signer.getAddress();
572
+ const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
581
573
 
582
- if (!response.ok) {
583
- const error = await response.json().catch(() => ({ error: response.statusText }));
584
- throw new Error(error.error || `Failed to list libraries: ${response.status}`);
585
- }
574
+ const response = await fetch(`${baseUrl}/git/personal/libraries`, {
575
+ method: 'GET',
576
+ headers: {
577
+ 'X-Wallet-Address': walletAddress,
578
+ 'X-Wallet-Signature': signature,
579
+ 'X-Wallet-Nonce': nonce,
580
+ 'X-Wallet-Message': Buffer.from(message).toString('base64'),
581
+ },
582
+ });
586
583
 
587
- const result = await response.json();
588
- const libraries = result.libraries || [];
584
+ if (!response.ok) {
585
+ const error = await response.json().catch(() => ({ error: response.statusText }));
586
+ throw new Error(error.error || `Failed to list libraries: ${response.status}`);
587
+ }
589
588
 
590
- if (opts.json) {
591
- ui.json(libraries);
592
- } else if (libraries.length === 0) {
593
- ui.info('No personal libraries found.');
594
- ui.output('Create one with: sage library personal create --name "My Library"');
595
- } else {
596
- ui.header('Personal Libraries');
597
- for (const lib of libraries) {
598
- ui.output(` ${lib.libraryId}: ${lib.name || '(unnamed)'}`);
589
+ const result = await response.json();
590
+ const libraries = result.libraries || [];
591
+
592
+ if (opts.json) {
593
+ ui.json(libraries);
594
+ } else if (libraries.length === 0) {
595
+ ui.info(`No ${label.toLowerCase()} libraries found.`);
596
+ ui.output(`Create one with: sage library ${name} create --name "My Library"`);
597
+ } else {
598
+ ui.header(`${label} Libraries`);
599
+ for (const lib of libraries) {
600
+ ui.output(` ${lib.libraryId}: ${lib.name || '(unnamed)'}`);
601
+ }
599
602
  }
603
+
604
+ } catch (e) {
605
+ handleCLIError('library:personal:list', e, { exit: true });
600
606
  }
607
+ });
601
608
 
602
- } catch (e) {
603
- handleCLIError('library:personal:list', e, { exit: true });
604
- }
605
- });
609
+ personal
610
+ .command('info')
611
+ .description(`Show ${label.toLowerCase()} library info`)
612
+ .argument('<libraryId>', 'Library ID')
613
+ .option('--json', 'Output JSON', false)
614
+ .action(async (libraryId, opts) => {
615
+ try {
616
+ const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
617
+ const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
606
618
 
607
- personal
608
- .command('info')
609
- .description('Show personal library info')
610
- .argument('<libraryId>', 'Library ID')
611
- .option('--json', 'Output JSON', false)
612
- .action(async (libraryId, opts) => {
613
- try {
614
- const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
615
- const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
619
+ const { signer } = await getSignerSession();
620
+ const walletAddress = await signer.getAddress();
621
+ const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
616
622
 
617
- const { signer } = await getSignerSession();
618
- const walletAddress = await signer.getAddress();
619
- const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
620
-
621
- const response = await fetch(`${baseUrl}/git/personal/${encodeURIComponent(libraryId)}`, {
622
- method: 'GET',
623
- headers: {
624
- 'X-Wallet-Address': walletAddress,
625
- 'X-Wallet-Signature': signature,
626
- 'X-Wallet-Nonce': nonce,
627
- 'X-Wallet-Message': Buffer.from(message).toString('base64'),
628
- },
629
- });
623
+ const response = await fetch(`${baseUrl}/git/personal/${encodeURIComponent(libraryId)}`, {
624
+ method: 'GET',
625
+ headers: {
626
+ 'X-Wallet-Address': walletAddress,
627
+ 'X-Wallet-Signature': signature,
628
+ 'X-Wallet-Nonce': nonce,
629
+ 'X-Wallet-Message': Buffer.from(message).toString('base64'),
630
+ },
631
+ });
630
632
 
631
- if (!response.ok) {
632
- const error = await response.json().catch(() => ({ error: response.statusText }));
633
- throw new Error(error.error || `Library not found: ${response.status}`);
634
- }
633
+ if (!response.ok) {
634
+ const error = await response.json().catch(() => ({ error: response.statusText }));
635
+ throw new Error(error.error || `Library not found: ${response.status}`);
636
+ }
635
637
 
636
- const result = await response.json();
638
+ const result = await response.json();
637
639
 
638
- if (opts.json) {
639
- ui.json(result);
640
- } else {
641
- ui.header(`Personal Library: ${libraryId}`);
642
- ui.keyValue([
643
- ['Name', result.name || '(unnamed)'],
644
- ['Description', result.description || '(none)'],
645
- ['Owner', result.owner || walletAddress],
646
- ['Created', result.createdAt ? new Date(result.createdAt).toISOString() : 'unknown'],
647
- ]);
640
+ if (opts.json) {
641
+ ui.json(result);
642
+ } else {
643
+ ui.header(`${label} Library: ${libraryId}`);
644
+ ui.keyValue([
645
+ ['Name', result.name || '(unnamed)'],
646
+ ['Description', result.description || '(none)'],
647
+ ['Owner', result.owner || walletAddress],
648
+ ['Created', result.createdAt ? new Date(result.createdAt).toISOString() : 'unknown'],
649
+ ]);
650
+ }
651
+
652
+ } catch (e) {
653
+ handleCLIError('library:personal:info', e, { exit: true });
648
654
  }
655
+ });
649
656
 
650
- } catch (e) {
651
- handleCLIError('library:personal:info', e, { exit: true });
652
- }
653
- });
657
+ personal
658
+ .command('push')
659
+ .description(`Push files to a ${label.toLowerCase()} library`)
660
+ .argument('<libraryId>', 'Library ID')
661
+ .option('--from-dir <path>', 'Directory to push (default: .)', '.')
662
+ .option('-m, --message <msg>', 'Commit message', 'Update library')
663
+ .option('--json', 'Output JSON', false)
664
+ .action(async (libraryId, opts) => {
665
+ try {
666
+ const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
667
+ const IPFSManager = require('../ipfs-manager');
668
+ const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
654
669
 
655
- personal
656
- .command('push')
657
- .description('Push files to a personal library')
658
- .argument('<libraryId>', 'Library ID')
659
- .option('--from-dir <path>', 'Directory to push (default: .)', '.')
660
- .option('-m, --message <msg>', 'Commit message', 'Update library')
661
- .option('--json', 'Output JSON', false)
662
- .action(async (libraryId, opts) => {
663
- try {
664
- const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
665
- const IPFSManager = require('../ipfs-manager');
666
- const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
670
+ const { signer } = await getSignerSession();
671
+ const walletAddress = await signer.getAddress();
672
+ const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
667
673
 
668
- const { signer } = await getSignerSession();
669
- const walletAddress = await signer.getAddress();
670
- const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
674
+ // Scan directory for files
675
+ const scanDir = path.isAbsolute(opts.fromDir)
676
+ ? opts.fromDir
677
+ : path.join(process.cwd(), opts.fromDir);
671
678
 
672
- // Scan directory for files
673
- const scanDir = path.isAbsolute(opts.fromDir)
674
- ? opts.fromDir
675
- : path.join(process.cwd(), opts.fromDir);
679
+ ui.info(`Scanning ${scanDir}...`);
680
+ const files = scanDirectory(scanDir);
676
681
 
677
- ui.info(`Scanning ${scanDir}...`);
678
- const files = scanDirectory(scanDir);
682
+ if (files.length === 0) {
683
+ ui.warn('No .md files found to push');
684
+ return;
685
+ }
679
686
 
680
- if (files.length === 0) {
681
- ui.warn('No .md files found to push');
682
- return;
683
- }
687
+ ui.success(`Found ${files.length} file(s)`);
684
688
 
685
- ui.success(`Found ${files.length} file(s)`);
689
+ // Upload files to IPFS
690
+ ui.info('Uploading to IPFS...');
691
+ const ipfs = new IPFSManager();
692
+ await ipfs.initialize();
686
693
 
687
- // Upload files to IPFS
688
- ui.info('Uploading to IPFS...');
689
- const ipfs = new IPFSManager();
690
- await ipfs.initialize();
694
+ for (const f of files) {
695
+ const content = fs.readFileSync(f.path, 'utf8');
696
+ f.cid = await ipfs.uploadText(content, path.basename(f.path));
697
+ f.files = [path.relative(scanDir, f.path)];
698
+ }
691
699
 
692
- for (const f of files) {
693
- const content = fs.readFileSync(f.path, 'utf8');
694
- f.cid = await ipfs.uploadText(content, path.basename(f.path));
695
- f.files = [path.relative(scanDir, f.path)];
696
- }
700
+ // Build manifest
701
+ const manifest = buildManifest(libraryId, '', files);
702
+ let manifestCID;
703
+ if (typeof ipfs.uploadRawJson === 'function') {
704
+ const result = await ipfs.uploadRawJson(manifest, { name: 'manifest.json' });
705
+ manifestCID = result.cid;
706
+ } else {
707
+ manifestCID = await ipfs.uploadJson(manifest, 'manifest.json');
708
+ }
697
709
 
698
- // Build manifest
699
- const manifest = buildManifest(libraryId, '', files);
700
- let manifestCID;
701
- if (typeof ipfs.uploadRawJson === 'function') {
702
- const result = await ipfs.uploadRawJson(manifest, { name: 'manifest.json' });
703
- manifestCID = result.cid;
704
- } else {
705
- manifestCID = await ipfs.uploadJson(manifest, 'manifest.json');
706
- }
710
+ ui.success(`Manifest: ${manifestCID}`);
707
711
 
708
- ui.success(`Manifest: ${manifestCID}`);
709
-
710
- // Push to library via worker API
711
- ui.info('Pushing to library...');
712
- const response = await fetch(`${baseUrl}/git/personal/${encodeURIComponent(libraryId)}/push`, {
713
- method: 'POST',
714
- headers: {
715
- 'Content-Type': 'application/json',
716
- 'X-Wallet-Address': walletAddress,
717
- 'X-Wallet-Signature': signature,
718
- 'X-Wallet-Nonce': nonce,
719
- 'X-Wallet-Message': Buffer.from(message).toString('base64'),
720
- },
721
- body: JSON.stringify({
722
- ref: 'refs/heads/main',
723
- message: opts.message,
724
- manifestCid: manifestCID,
725
- author: {
726
- name: walletAddress.slice(0, 10),
727
- address: walletAddress,
712
+ // Push to library via worker API
713
+ ui.info('Pushing to library...');
714
+ const response = await fetch(`${baseUrl}/git/personal/${encodeURIComponent(libraryId)}/push`, {
715
+ method: 'POST',
716
+ headers: {
717
+ 'Content-Type': 'application/json',
718
+ 'X-Wallet-Address': walletAddress,
719
+ 'X-Wallet-Signature': signature,
720
+ 'X-Wallet-Nonce': nonce,
721
+ 'X-Wallet-Message': Buffer.from(message).toString('base64'),
728
722
  },
729
- }),
730
- });
723
+ body: JSON.stringify({
724
+ ref: 'refs/heads/main',
725
+ message: opts.message,
726
+ manifestCid: manifestCID,
727
+ author: {
728
+ name: walletAddress.slice(0, 10),
729
+ address: walletAddress,
730
+ },
731
+ }),
732
+ });
731
733
 
732
- if (!response.ok) {
733
- const error = await response.json().catch(() => ({ error: response.statusText }));
734
- throw new Error(error.error || `Push failed: ${response.status}`);
735
- }
734
+ if (!response.ok) {
735
+ const error = await response.json().catch(() => ({ error: response.statusText }));
736
+ throw new Error(error.error || `Push failed: ${response.status}`);
737
+ }
736
738
 
737
- const result = await response.json();
739
+ const result = await response.json();
738
740
 
739
- if (opts.json) {
740
- ui.json({ libraryId, manifestCID, ...result });
741
- } else {
742
- ui.success(`Pushed to ${libraryId}`);
743
- ui.keyValue([
744
- ['Commit', result.commitHash || result.oid || 'created'],
745
- ['Manifest CID', manifestCID],
746
- ['Files', `${files.length}`],
747
- ]);
741
+ if (opts.json) {
742
+ ui.json({ libraryId, manifestCID, ...result });
743
+ } else {
744
+ ui.success(`Pushed to ${libraryId}`);
745
+ ui.keyValue([
746
+ ['Commit', result.commitHash || result.oid || 'created'],
747
+ ['Manifest CID', manifestCID],
748
+ ['Files', `${files.length}`],
749
+ ]);
750
+ }
751
+
752
+ } catch (e) {
753
+ handleCLIError('library:personal:push', e, { exit: true });
748
754
  }
755
+ });
749
756
 
750
- } catch (e) {
751
- handleCLIError('library:personal:push', e, { exit: true });
752
- }
753
- });
757
+ personal
758
+ .command('delete')
759
+ .description(`Delete a ${label.toLowerCase()} library`)
760
+ .argument('<libraryId>', 'Library ID')
761
+ .option('--json', 'Output JSON', false)
762
+ .option('--force', 'Skip confirmation')
763
+ .action(async (libraryId, opts) => {
764
+ try {
765
+ const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
766
+ const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
767
+
768
+ if (!opts.force && !process.env.SAGE_FORCE) {
769
+ const readline = require('readline');
770
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
771
+ const answer = await new Promise((resolve) => {
772
+ rl.question(`Delete library "${libraryId}"? This cannot be undone. (y/N) `, resolve);
773
+ });
774
+ rl.close();
775
+ if (answer.toLowerCase() !== 'y') {
776
+ ui.info('Aborted.');
777
+ return;
778
+ }
779
+ }
754
780
 
755
- personal
756
- .command('delete')
757
- .description('Delete a personal library')
758
- .argument('<libraryId>', 'Library ID')
759
- .option('--json', 'Output JSON', false)
760
- .option('--force', 'Skip confirmation')
761
- .action(async (libraryId, opts) => {
762
- try {
763
- const { getSignerSession, getSiweAuth } = require('../utils/cli-session');
764
- const baseUrl = process.env.SAGE_IPFS_WORKER_URL || 'https://api.sageprotocol.io';
765
-
766
- if (!opts.force && !process.env.SAGE_FORCE) {
767
- const readline = require('readline');
768
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
769
- const answer = await new Promise((resolve) => {
770
- rl.question(`Delete library "${libraryId}"? This cannot be undone. (y/N) `, resolve);
781
+ const { signer } = await getSignerSession();
782
+ const walletAddress = await signer.getAddress();
783
+ const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
784
+
785
+ const response = await fetch(`${baseUrl}/git/personal/${encodeURIComponent(libraryId)}`, {
786
+ method: 'DELETE',
787
+ headers: {
788
+ 'X-Wallet-Address': walletAddress,
789
+ 'X-Wallet-Signature': signature,
790
+ 'X-Wallet-Nonce': nonce,
791
+ 'X-Wallet-Message': Buffer.from(message).toString('base64'),
792
+ },
771
793
  });
772
- rl.close();
773
- if (answer.toLowerCase() !== 'y') {
774
- ui.info('Aborted.');
775
- return;
794
+
795
+ if (!response.ok) {
796
+ const error = await response.json().catch(() => ({ error: response.statusText }));
797
+ throw new Error(error.error || `Delete failed: ${response.status}`);
776
798
  }
777
- }
778
799
 
779
- const { signer } = await getSignerSession();
780
- const walletAddress = await signer.getAddress();
781
- const { signature, message, nonce } = await getSiweAuth(signer, baseUrl);
782
-
783
- const response = await fetch(`${baseUrl}/git/personal/${encodeURIComponent(libraryId)}`, {
784
- method: 'DELETE',
785
- headers: {
786
- 'X-Wallet-Address': walletAddress,
787
- 'X-Wallet-Signature': signature,
788
- 'X-Wallet-Nonce': nonce,
789
- 'X-Wallet-Message': Buffer.from(message).toString('base64'),
790
- },
791
- });
800
+ if (opts.json) {
801
+ ui.json({ deleted: true, libraryId });
802
+ } else {
803
+ ui.success(`Deleted library: ${libraryId}`);
804
+ }
792
805
 
793
- if (!response.ok) {
794
- const error = await response.json().catch(() => ({ error: response.statusText }));
795
- throw new Error(error.error || `Delete failed: ${response.status}`);
806
+ } catch (e) {
807
+ handleCLIError('library:personal:delete', e, { exit: true });
796
808
  }
809
+ });
797
810
 
798
- if (opts.json) {
799
- ui.json({ deleted: true, libraryId });
800
- } else {
801
- ui.success(`Deleted library: ${libraryId}`);
802
- }
811
+ return personal;
812
+ }
803
813
 
804
- } catch (e) {
805
- handleCLIError('library:personal:delete', e, { exit: true });
806
- }
807
- });
814
+ const personal = buildPersonalCommands({ name: 'personal', label: 'Personal' });
815
+ const vault = buildPersonalCommands({ name: 'vault', label: 'Vault' });
808
816
 
809
817
  cmd.addCommand(personal);
818
+ cmd.addCommand(vault);
810
819
 
811
820
  return cmd;
812
821
  };