vibeiao 0.1.4 → 0.1.6

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 +2 -0
  2. package/package.json +1 -1
  3. package/src/index.js +125 -22
package/README.md CHANGED
@@ -14,6 +14,7 @@ Defaults used by the one-liners:
14
14
 
15
15
  - `human`: reads `agent.json` if present, writes `handoff.json`
16
16
  - `agent`: prefers `handoff.json`, then `agent.json`; uses `~/.config/solana/id.json` if present, otherwise auto-generates it on first run
17
+ - `agent` with no files: auto-bootstraps a valid `agent.json` + memory scaffold and requests a hosted manifest URL from the API
17
18
 
18
19
  ## Memory Layout (Required)
19
20
 
@@ -98,4 +99,5 @@ After `vibeiao agent` creates your listing, the CLI prints a required promotion
98
99
 
99
100
  - `--inject` writes `walletMode: "multisig"` and `revenueWallet` into the target JSON and creates a `.bak` backup.
100
101
  - API defaults to `https://api.vibeiao.com` (override with `--api` if needed).
102
+ - No-file `agent` bootstrap requires API route `/v1/manifests/bootstrap` (deploy latest `apps/api`).
101
103
  - Human apps are submitted by agents via CLI/SDK; the CLI list command is for browsing.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vibeiao",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "0.1.4",
5
+ "version": "0.1.6",
6
6
  "description": "VIBEIAO CLI for agent onboarding and multisig revenue setup.",
7
7
  "bin": {
8
8
  "vibeiao": "src/index.js"
package/src/index.js CHANGED
@@ -534,12 +534,72 @@ const normalizeBuybackBps = (value) => {
534
534
  return Math.min(Math.max(asBps, 0), 10000);
535
535
  };
536
536
 
537
+ const createBootstrapManifestUrl = async (apiBase, manifest) => {
538
+ try {
539
+ const payload = await fetchJson(`${apiBase.replace(/\/+$/g, '')}/v1/manifests/bootstrap`, {
540
+ method: 'POST',
541
+ headers: { 'Content-Type': 'application/json' },
542
+ body: JSON.stringify({ manifest }),
543
+ });
544
+ const manifestUrl = payload?.data?.manifestUrl || payload?.data?.url;
545
+ if (!manifestUrl || typeof manifestUrl !== 'string') {
546
+ throw new Error('bootstrap_manifest_failed');
547
+ }
548
+ return manifestUrl;
549
+ } catch (err) {
550
+ const message = err instanceof Error ? err.message : 'bootstrap_manifest_failed';
551
+ if (message.includes("Unexpected token '<'")) {
552
+ throw new Error(
553
+ 'bootstrap_manifest_unavailable:api_route_missing_or_html_response (deploy latest apps/api and verify VIBEIAO_API_BASE)'
554
+ );
555
+ }
556
+ throw new Error(`bootstrap_manifest_unavailable:${message}`);
557
+ }
558
+ };
559
+
560
+ const buildAutonomousBootstrapListing = async ({ apiBase, walletAddress, memoryRoot }) => {
561
+ const endpointUrl = `${apiBase.replace(/\/+$/g, '')}/v1/runtime/execute`;
562
+ const suffix = walletAddress.slice(0, 8);
563
+ const manifest = {
564
+ name: `VIBEIAO Agent ${suffix}`,
565
+ wallet: walletAddress,
566
+ endpoint: endpointUrl,
567
+ version: '1.0.0',
568
+ selfReliance: buildSelfRelianceTemplate(),
569
+ memory: buildMemoryConfig(memoryRoot),
570
+ resourceProviders: buildResourceProvidersTemplate(),
571
+ };
572
+ const manifestUrl = await createBootstrapManifestUrl(apiBase, manifest);
573
+
574
+ return {
575
+ listingType: 'agent',
576
+ name: `VIBEIAO Agent ${suffix}`,
577
+ tagline: 'Autonomous producer bootstrapped by one-liner',
578
+ description:
579
+ 'Autonomous agent listing created from first-run bootstrap. Update metadata as your product evolves.',
580
+ category: 'Agent',
581
+ priceUsdc: 1,
582
+ imageUrl: '',
583
+ productUrl: 'https://vibeiao.com',
584
+ endpointUrl,
585
+ manifestUrl,
586
+ llmRequired: false,
587
+ llmBillingEnabled: false,
588
+ llmProvider: '',
589
+ ticketPrice: 0,
590
+ targetRevenue: 10,
591
+ buybackBps: 0,
592
+ };
593
+ };
594
+
537
595
  const formatCliError = (err) => {
538
596
  const message = err?.message || String(err);
597
+ const details = err?.details;
598
+ const detailsText = details ? `\nDetails: ${typeof details === 'string' ? details : JSON.stringify(details)}` : '';
539
599
  if (message.includes("reading '_bn'")) {
540
- return `${message}\nHint: likely Program ID / IDL mismatch. Use --program ${DEFAULT_PROGRAM_ID} and ensure you are on the latest CLI build.`;
600
+ return `${message}${detailsText}\nHint: likely Program ID / IDL mismatch. Use --program ${DEFAULT_PROGRAM_ID} and ensure you are on the latest CLI build.`;
541
601
  }
542
- return message;
602
+ return `${message}${detailsText}`;
543
603
  };
544
604
 
545
605
  const normalizeListingText = (value) =>
@@ -894,24 +954,38 @@ const handleHuman = async (flags) => {
894
954
  const rpcUrl =
895
955
  flags.rpc || process.env.VIBEIAO_RPC_URL || process.env.SOLANA_RPC_URL || DEFAULT_RPC;
896
956
  const programId = flags.program || process.env.VIBEIAO_PROGRAM_ID || DEFAULT_PROGRAM_ID;
897
- const interactive = !flags['non-interactive'];
957
+ const interactive = !!flags.interactive;
958
+ const claimOnly = flags['claim-only'] !== undefined || flags['owner-claim-only'] !== undefined
959
+ ? !!(flags['claim-only'] || flags['owner-claim-only'])
960
+ : !interactive;
898
961
 
962
+ // Humans should not be forced to decide listing/product details during onboarding.
963
+ // Default human flow to a "human" listing type unless explicitly overridden.
899
964
  const defaultConfig = resolveInputFile({
900
965
  explicit: flags.config,
901
966
  fallback: DEFAULT_AGENT_CONFIG_FILE,
902
967
  label: 'config',
903
968
  });
904
969
  const listingFlags = defaultConfig ? { ...flags, config: defaultConfig } : flags;
905
- const listing = await resolveListing(listingFlags, { interactive });
906
- const quotedListing = await applyPriceQuote(listing, flags);
907
- validateListing(quotedListing);
970
+ const effectiveListingFlags =
971
+ claimOnly || listingFlags['listing-type']
972
+ ? listingFlags
973
+ : { ...listingFlags, 'listing-type': 'human' };
974
+
975
+ const quotedListing = claimOnly
976
+ ? null
977
+ : await applyPriceQuote(await resolveListing(effectiveListingFlags, { interactive }), flags);
978
+ if (quotedListing) {
979
+ validateListing(quotedListing);
980
+ }
981
+
908
982
  const memoryRoot = String(flags['memory-root'] || DEFAULT_MEMORY_ROOT);
909
983
  const memoryConfig = buildMemoryConfig(memoryRoot);
910
984
 
911
985
  const walletMode = (
912
986
  flags['wallet-mode'] ||
913
987
  flags.ownership ||
914
- quotedListing.walletMode ||
988
+ quotedListing?.walletMode ||
915
989
  'single'
916
990
  ).toLowerCase();
917
991
  const ownerKeypairInput = flags['owner-keypair'];
@@ -919,10 +993,10 @@ const handleHuman = async (flags) => {
919
993
  const ownerWallet =
920
994
  ownerKeypair?.publicKey?.toBase58?.() ||
921
995
  flags['owner-wallet'] ||
922
- quotedListing.ownerWallet ||
996
+ quotedListing?.ownerWallet ||
923
997
  '';
924
- const revenueWallet = flags['revenue-wallet'] || quotedListing.revenueWallet || '';
925
- const ethWallet = flags['eth-wallet'] || quotedListing.ethWallet || '';
998
+ const revenueWallet = flags['revenue-wallet'] || quotedListing?.revenueWallet || '';
999
+ const ethWallet = flags['eth-wallet'] || quotedListing?.ethWallet || '';
926
1000
 
927
1001
  let ownerClaimId = null;
928
1002
  if (ownerKeypair) {
@@ -937,11 +1011,11 @@ const handleHuman = async (flags) => {
937
1011
  );
938
1012
  }
939
1013
 
940
- const agentWallet = flags.wallet || quotedListing.agentWallet || '';
1014
+ const agentWallet = flags.wallet || quotedListing?.agentWallet || '';
941
1015
  let claim = null;
942
1016
  let message = null;
943
1017
  if (agentWallet) {
944
- const purpose = quotedListing.listingType === 'agent' ? 'agent_register' : 'owner_claim';
1018
+ const purpose = quotedListing?.listingType === 'agent' ? 'agent_register' : 'owner_claim';
945
1019
  claim = await createClaim(apiBase, agentWallet, purpose);
946
1020
  message = buildClaimMessage(claim.data.nonce);
947
1021
  }
@@ -962,6 +1036,12 @@ const handleHuman = async (flags) => {
962
1036
  ownerClaimId,
963
1037
  },
964
1038
  listing: quotedListing,
1039
+ onboarding: {
1040
+ mode: claimOnly ? 'claim-only' : 'interactive',
1041
+ note: claimOnly
1042
+ ? 'Human onboarding ran in claim-only mode. Listing/product metadata is intentionally omitted.'
1043
+ : 'Human onboarding included listing metadata (legacy behavior).',
1044
+ },
965
1045
  createdAt: new Date().toISOString(),
966
1046
  };
967
1047
 
@@ -1010,22 +1090,45 @@ const handleAgent = async (flags) => {
1010
1090
  label: 'config',
1011
1091
  });
1012
1092
  const listingFlags = defaultConfig ? { ...flags, config: defaultConfig } : flags;
1013
- if (!handoff && !listingFlags.config && !flags.name && !flags.tagline && !flags.description) {
1014
- throw new Error(
1015
- `missing_listing_input (expected ${DEFAULT_HANDOFF_FILE}, ${DEFAULT_AGENT_CONFIG_FILE}, or explicit --name/--tagline/--description flags)`
1016
- );
1017
- }
1018
- const listing = handoff?.listing
1019
- ? normalizeListing(handoff.listing)
1020
- : await resolveListing(listingFlags, { interactive: false });
1021
1093
  const { keypair, generated: keypairGenerated, path: keypairPath } = resolveAgentKeypair(flags);
1022
1094
  if (keypairGenerated && keypairPath) {
1023
1095
  console.log(`🔐 No keypair found. Generated agent keypair at ${keypairPath}`);
1024
1096
  console.log(' Keep this file safe. It controls your on-chain agent wallet.');
1025
1097
  }
1098
+ const memoryRoot = String(flags['memory-root'] || handoff?.memory?.root || DEFAULT_MEMORY_ROOT);
1099
+ const hasHandoffListing =
1100
+ !!(handoff && handoff.listing && typeof handoff.listing === 'object');
1101
+ const noListingInput =
1102
+ !hasHandoffListing &&
1103
+ !listingFlags.config &&
1104
+ !flags.name &&
1105
+ !flags.tagline &&
1106
+ !flags.description &&
1107
+ !flags.product &&
1108
+ !flags.endpoint &&
1109
+ !flags.manifest &&
1110
+ !flags.runtime;
1111
+ const listing = hasHandoffListing
1112
+ ? normalizeListing(handoff.listing)
1113
+ : noListingInput
1114
+ ? await buildAutonomousBootstrapListing({
1115
+ apiBase,
1116
+ walletAddress: keypair.publicKey.toBase58(),
1117
+ memoryRoot,
1118
+ })
1119
+ : await resolveListing(listingFlags, { interactive: false });
1120
+ if (noListingInput) {
1121
+ const scaffoldPath = path.resolve(DEFAULT_AGENT_CONFIG_FILE);
1122
+ if (!fs.existsSync(scaffoldPath)) {
1123
+ fs.writeFileSync(scaffoldPath, `${JSON.stringify(listing, null, 2)}\n`);
1124
+ console.log(`🧩 Generated ${DEFAULT_AGENT_CONFIG_FILE} scaffold at ${scaffoldPath}`);
1125
+ } else {
1126
+ console.log(`🧩 Reusing existing ${DEFAULT_AGENT_CONFIG_FILE} in current directory`);
1127
+ }
1128
+ console.log('⚡ No handoff/config found. Bootstrapping with autonomous defaults.');
1129
+ }
1026
1130
  const quotedListing = await applyPriceQuote(listing, flags);
1027
1131
  validateListing(quotedListing);
1028
- const memoryRoot = String(flags['memory-root'] || handoff?.memory?.root || DEFAULT_MEMORY_ROOT);
1029
1132
  if (quotedListing.listingType === 'agent') {
1030
1133
  const memoryPath = ensureMemoryLayout(memoryRoot);
1031
1134
  console.log(`🧠 Memory layout ensured at ${memoryPath}`);
@@ -1499,7 +1602,7 @@ const main = async () => {
1499
1602
  console.log(`VibeIAO CLI
1500
1603
 
1501
1604
  Usage:
1502
- vibeiao human [--config agent.json] [--owner-keypair <path|base58>] [--owner-wallet <pubkey>] [--wallet-mode single|multisig] [--memory-root memory] [--output handoff.json] [--stdout]
1605
+ vibeiao human [--claim-only] [--config agent.json] [--owner-keypair <path|base58>] [--owner-wallet <pubkey>] [--wallet-mode single|multisig] [--memory-root memory] [--output handoff.json] [--stdout]
1503
1606
  vibeiao agent [--config agent.json] [--keypair <path|base58>] [--handoff handoff.json] [--memory-root memory] [--owner-claim <id>]
1504
1607
  (optional) --runtime openrouter --runtime-config runtime.json
1505
1608
  vibeiao list [--type agent|human|all] [--limit 10] [--offset 0] [--category <name>] [--sort recent|revenue|tickets|buyback] [--json]